12#ifndef CSCI441_MD5_CAMERA_HPP
13#define CSCI441_MD5_CAMERA_HPP
16#include "LogUtils.hpp"
73 explicit MD5Camera(
const char* MD5CAMERA_FILE,
AdvancementStrategy advancementStrategy, GLuint firstCutToRun = 0, GLfloat aspectRatio = 1.0f, GLfloat fovy = glm::half_pi<GLfloat>(), GLfloat nearClipPlane = 0.001f, GLfloat farClipPlane = 1000.0f, GLboolean INFO =
true, GLboolean ERRORS =
true);
105 bool _loadMD5CameraFromFile(
const char * MD5CAMERA_FILE, GLboolean INFO =
true, GLboolean ERRORS =
true);
113 glm::vec3 cameraPosition;
114 glm::vec3 cameraQuaternion;
121 GLuint* _cutPositions;
123 GLuint _currentFrameIndex;
124 GLuint _currentCutIndex;
127 void _updateCameraAttributesForCurrentFrame();
131 GLfloat _aspectRatio;
132 GLfloat _nearClipPlane;
133 GLfloat _farClipPlane;
138 const char *
const MD5CAMERA_FILE,
140 const GLuint firstCutToRun,
141 const GLfloat aspectRatio,
143 const GLfloat nearClipPlane,
144 const GLfloat farClipPlane,
145 const GLboolean INFO,
146 const GLboolean ERRORS
147) : _isInitialized(false),
151 _cutPositions(nullptr),
153 _currentFrameIndex(0),
154 _currentCutIndex(firstCutToRun),
155 _advancementStrategy(advancementStrategy),
157 _aspectRatio(aspectRatio),
158 _nearClipPlane(nearClipPlane),
159 _farClipPlane(farClipPlane)
161 mProjectionMatrix = glm::perspective(_fovy, _aspectRatio, _nearClipPlane, _farClipPlane);
163 _isInitialized = _loadMD5CameraFromFile(MD5CAMERA_FILE, INFO, ERRORS);
170 _isInitialized(false),
174 _cutPositions(nullptr),
176 _currentFrameIndex(0),
181 _nearClipPlane(0.001f),
182 _farClipPlane(1000.0f)
189) noexcept :
Camera(std::move(src)),
190 _isInitialized(
false),
194 _cutPositions(
nullptr),
196 _currentFrameIndex(0),
198 _advancementStrategy(AdvancementStrategy::RUN_SINGLE_CUT),
201 _nearClipPlane(0.001f),
202 _farClipPlane(1000.0f)
204 this->_moveFromSource(src);
223 this->_moveFromSource(src);
237inline void CSCI441::MD5Camera::_copy(
const MD5Camera& OTHER) {
239 _aspectRatio = OTHER._aspectRatio;
240 _nearClipPlane = OTHER._nearClipPlane;
241 _farClipPlane = OTHER._farClipPlane;
242 _frameRate = OTHER._frameRate;
243 _currentFrameIndex = OTHER._currentFrameIndex;
244 _currentCutIndex = OTHER._currentCutIndex;
245 _advancementStrategy = OTHER._advancementStrategy;
247 _isInitialized = OTHER._isInitialized;
249 _numCuts = OTHER._numCuts;
250 _cutPositions =
new GLuint[_numCuts];
251 for(
unsigned int i = 0; i < _numCuts; i++) {
252 _cutPositions[i] = OTHER._cutPositions[i];
255 _numFrames = OTHER._numFrames;
256 _frames =
new Frame[_numFrames];
257 for(
unsigned int i = 0; i < _numFrames; i++) {
258 _frames[i] = OTHER._frames[i];
266 _aspectRatio = src._aspectRatio;
267 src._aspectRatio = 0.0f;
269 _nearClipPlane = src._nearClipPlane;
270 src._nearClipPlane = 0.0f;
272 _farClipPlane = src._farClipPlane;
273 src._farClipPlane = 0.0f;
275 _frameRate = src._frameRate;
278 _currentFrameIndex = src._currentFrameIndex;
279 src._currentFrameIndex = 0;
281 _currentCutIndex = src._currentCutIndex;
282 src._currentCutIndex = 0;
284 _advancementStrategy = src._advancementStrategy;
286 _isInitialized = src._isInitialized;
287 src._isInitialized =
false;
289 _numCuts = src._numCuts;
292 _cutPositions = src._cutPositions;
293 src._cutPositions =
nullptr;
295 _numFrames = src._numFrames;
298 _frames = src._frames;
299 src._frames =
nullptr;
302inline void CSCI441::MD5Camera::_free() {
306 delete[] _cutPositions;
307 _cutPositions =
nullptr;
311inline bool CSCI441::MD5Camera::_loadMD5CameraFromFile(
312 const char *
const MD5CAMERA_FILE,
313 const GLboolean INFO,
314 const GLboolean ERRORS
316 if ( INFO )
CSCI441::LogUtils::log(
"[.md5camera]: -=-=-=-=-=-=-=- BEGIN %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
321 std::ifstream md5CameraFile(MD5CAMERA_FILE);
322 if( !md5CameraFile.is_open() ) {
324 if ( INFO )
CSCI441::LogUtils::log(
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
328 std::string sectionLabel, commandLineStr, brace;
330 Frame frame = { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 45.0f };
333 md5CameraFile >> sectionLabel >> md5version;
334 if(sectionLabel !=
"MD5Version" || md5version != 10) {
335 if (ERRORS) fprintf (stderr,
"[.md5camera]: [ERROR]: improper MD5Camera version found \"%s %d\"\n", sectionLabel.c_str(), md5version );
336 if ( INFO )
CSCI441::LogUtils::log(
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
341 md5CameraFile >> sectionLabel;
342 getline(md5CameraFile, commandLineStr);
344 for(
unsigned short i = 0; i < 5; i++) {
345 md5CameraFile >> sectionLabel;
346 if(sectionLabel ==
"numFrames") {
348 md5CameraFile >> _numFrames;
349 _frames =
new Frame[_numFrames];
350 }
else if(sectionLabel ==
"frameRate") {
352 md5CameraFile >> _frameRate;
353 }
else if(sectionLabel ==
"numCuts") {
355 md5CameraFile >> _numCuts;
356 _cutPositions =
new GLuint[_numCuts];
357 }
else if(sectionLabel ==
"cuts") {
362 md5CameraFile >> brace;
363 if (_cutPositions ==
nullptr) {
364 if (ERRORS)
CSCI441::LogUtils::logError(
"[.md5camera]: [ERROR]: malformed md5camera file. numCuts not previously defined in file\n" );
367 for(
unsigned int cutNumber = 0; cutNumber < _numCuts; cutNumber++) {
368 md5CameraFile >> _cutPositions[cutNumber];
370 md5CameraFile >> brace;
371 _currentFrameIndex = _cutPositions[_currentCutIndex];
372 }
else if(sectionLabel ==
"camera") {
376 md5CameraFile >> brace;
377 for(
unsigned int frameNumber = 0; frameNumber < _numFrames; frameNumber++) {
378 md5CameraFile >> brace >> frame.cameraPosition.x >> frame.cameraPosition.y >> frame.cameraPosition.z >> brace;
379 md5CameraFile >> brace >> frame.cameraQuaternion.x >> frame.cameraQuaternion.y >> frame.cameraQuaternion.z >> brace;
380 md5CameraFile >> frame.fieldOfView;
382 md5CameraFile >> brace;
385 if ( INFO )
CSCI441::LogUtils::log(
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
392 CSCI441::LogUtils::log(
"[.md5camera]: Num Frames:\t%u\tFrame Rate:\t%u\tNum Cuts: \t%u\n", _numFrames, _frameRate, _numCuts );
396 double seconds = difftime( end, start );
400 CSCI441::LogUtils::log(
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n\n", MD5CAMERA_FILE );
408 if( !_isInitialized )
return;
413 if( _currentFrameIndex == _numFrames - 1) {
414 switch(_advancementStrategy) {
415 case AdvancementStrategy::LOOP_ALL_CUTS:
417 _currentCutIndex = 0;
418 case AdvancementStrategy::LOOP_SINGLE_CUT:
420 _currentFrameIndex = _cutPositions[ _currentCutIndex ];
423 case AdvancementStrategy::RUN_SINGLE_CUT:
424 case AdvancementStrategy::RUN_ALL_CUTS:
430 else if( _currentCutIndex == _numCuts - 1 ) {
432 _currentFrameIndex++;
437 if( _currentFrameIndex == _cutPositions[_currentCutIndex + 1] - 1 ) {
438 switch(_advancementStrategy) {
439 case AdvancementStrategy::RUN_ALL_CUTS:
440 case AdvancementStrategy::LOOP_ALL_CUTS:
443 case AdvancementStrategy::LOOP_SINGLE_CUT:
445 _currentFrameIndex = _cutPositions[ _currentCutIndex ];
448 case AdvancementStrategy::RUN_SINGLE_CUT:
454 _currentFrameIndex++;
457 _updateCameraAttributesForCurrentFrame();
462 if( !_isInitialized )
return;
467 if( _currentFrameIndex == 0) {
468 switch(_advancementStrategy) {
469 case AdvancementStrategy::LOOP_ALL_CUTS:
471 _currentCutIndex = _numFrames-1;
474 case AdvancementStrategy::LOOP_SINGLE_CUT:
475 if( _numCuts == 1 ) {
477 _currentCutIndex = _numFrames-1;
480 _currentFrameIndex = _cutPositions[ _currentCutIndex+1 ] - 1;
484 case AdvancementStrategy::RUN_SINGLE_CUT:
485 case AdvancementStrategy::RUN_ALL_CUTS:
491 else if( _currentCutIndex == 0 ) {
493 _currentFrameIndex--;
498 if( _currentFrameIndex == _cutPositions[_currentCutIndex] ) {
499 switch(_advancementStrategy) {
500 case AdvancementStrategy::RUN_ALL_CUTS:
501 case AdvancementStrategy::LOOP_ALL_CUTS:
504 case AdvancementStrategy::LOOP_SINGLE_CUT:
506 _currentFrameIndex = _cutPositions[ _currentCutIndex+1 ] - 1;
509 case AdvancementStrategy::RUN_SINGLE_CUT:
515 _currentFrameIndex--;
518 _updateCameraAttributesForCurrentFrame();
521inline void CSCI441::MD5Camera::_updateCameraAttributesForCurrentFrame() {
523 mCameraPosition = _frames[_currentFrameIndex].cameraPosition;
527 glm::vec4 q(_frames[_currentFrameIndex].cameraQuaternion, 0.0f);
528 GLfloat t = 1.0f - (q.x * q.x) - (q.y * q.y) - (q.z * q.z);
535 glm::vec3 defaultCameraDirection(0.0f, 0.0f, -1.0f);
536 glm::vec4 inverseQ(-q.x, -q.y, -q.z, q.w);
537 inverseQ = glm::normalize(inverseQ);
539 glm::vec4 tmp( (q.w * defaultCameraDirection.x) + (q.y * defaultCameraDirection.z) - (q.z * defaultCameraDirection.y),
540 (q.w * defaultCameraDirection.y) + (q.z * defaultCameraDirection.x) - (q.x * defaultCameraDirection.z),
541 (q.w * defaultCameraDirection.z) + (q.x * defaultCameraDirection.y) - (q.y * defaultCameraDirection.x),
542 -(q.w * defaultCameraDirection.x) - (q.y * defaultCameraDirection.y) - (q.z * defaultCameraDirection.z) );
543 glm::vec4 rotatedCameraDirection((tmp.x * inverseQ.w) + (tmp.w * inverseQ.x) + (tmp.y * inverseQ.z) - (tmp.z * inverseQ.y),
544 (tmp.y * inverseQ.w) + (tmp.w * inverseQ.y) + (tmp.z * inverseQ.x) - (tmp.x * inverseQ.z),
545 (tmp.z * inverseQ.w) + (tmp.w * inverseQ.z) + (tmp.x * inverseQ.y) - (tmp.y * inverseQ.x),
546 (tmp.w * inverseQ.w) - (tmp.x * inverseQ.x) - (tmp.y * inverseQ.y) - (tmp.z * inverseQ.z) );
547 mCameraDirection = glm::vec3( rotatedCameraDirection.x, rotatedCameraDirection.y, rotatedCameraDirection.z );
548 mCameraLookAtPoint = mCameraPosition + mCameraDirection;
551 glm::vec3 defaultCameraUpVector(0.0f, 1.0f, 0.0f);
552 glm::vec4 tmp2( (q.w * defaultCameraUpVector.x) + (q.y * defaultCameraUpVector.z) - (q.z * defaultCameraUpVector.y),
553 (q.w * defaultCameraUpVector.y) + (q.z * defaultCameraUpVector.x) - (q.x * defaultCameraUpVector.z),
554 (q.w * defaultCameraUpVector.z) + (q.x * defaultCameraUpVector.y) - (q.y * defaultCameraUpVector.x),
555 -(q.w * defaultCameraUpVector.x) - (q.y * defaultCameraUpVector.y) - (q.z * defaultCameraUpVector.z) );
556 glm::vec4 rotatedCameraUpVector((tmp2.x * inverseQ.w) + (tmp2.w * inverseQ.x) + (tmp2.y * inverseQ.z) - (tmp2.z * inverseQ.y),
557 (tmp2.y * inverseQ.w) + (tmp2.w * inverseQ.y) + (tmp2.z * inverseQ.x) - (tmp2.x * inverseQ.z),
558 (tmp2.z * inverseQ.w) + (tmp2.w * inverseQ.z) + (tmp2.x * inverseQ.y) - (tmp2.y * inverseQ.x),
559 (tmp2.w * inverseQ.w) - (tmp2.x * inverseQ.x) - (tmp2.y * inverseQ.y) - (tmp2.z * inverseQ.z) );
560 mCameraUpVector = glm::vec3(rotatedCameraUpVector.x, rotatedCameraUpVector.y, rotatedCameraUpVector.z);
566 _fovy = _frames[_currentFrameIndex].fieldOfView;
567 mProjectionMatrix = glm::perspective(_fovy, _aspectRatio, _nearClipPlane, _farClipPlane);
Abstract Camera class to be placed (position and orientation) within our scene.
Abstract Class to represent a synthetic camera. The following methods must be overridden:
Definition: Camera.hpp:39
glm::mat4 mProjectionMatrix
stores the Projection Matrix
Definition: Camera.hpp:191
Camera & operator=(const Camera &)=default
assign a copy of an existing camera
A camera that implements the MD5Camera specification.
Definition: MD5Camera.hpp:29
MD5Camera & operator=(const MD5Camera &)
deep copy another MD5Camera
Definition: MD5Camera.hpp:207
~MD5Camera() override
delete cuts and frames
Definition: MD5Camera.hpp:233
AdvancementStrategy
what to do when the end of a cut is reached
Definition: MD5Camera.hpp:34
@ LOOP_SINGLE_CUT
run through just the initial specified cut, looping back to the beginning when the end is reached
@ LOOP_ALL_CUTS
run through all cuts beginning at initial specified cut, advancing to next cut when the end of the cu...
@ RUN_ALL_CUTS
run through all cuts beginning at initial specified cut, advancing to next cut when the end of the cu...
@ RUN_SINGLE_CUT
run through just the initial specified cut, stop when end is reached
void moveBackward(GLfloat unused) override
steps backward along the camera's view
Definition: MD5Camera.hpp:460
void recomputeOrientation() override
Uses theta, phi, & radius to update the camera's view matrix parameters. The camera orientation is co...
Definition: MD5Camera.hpp:100
void moveForward(GLfloat unused) override
steps forward along the camera's view
Definition: MD5Camera.hpp:406
MD5Camera()=delete
must create camera object from parameterized constructor
void log(const char *MSG,...)
log a message to both the standard output stream and file
Definition: LogUtils.hpp:116
void logError(const char *MSG,...)
log a message to both the standard error stream and file
Definition: LogUtils.hpp:128
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17