12#ifndef CSCI441_MD5_CAMERA_HPP
13#define CSCI441_MD5_CAMERA_HPP
72 explicit MD5Camera(
const char* MD5CAMERA_FILE,
AdvancementStrategy advancementStrategy, GLuint firstCutToRun = 0, GLfloat aspectRatio = 1.0f, GLfloat fovy = 45.0f, GLfloat nearClipPlane = 0.001f, GLfloat farClipPlane = 1000.0f, GLboolean INFO =
true, GLboolean ERRORS =
true);
93 bool _loadMD5CameraFromFile(
const char * MD5CAMERA_FILE, GLboolean INFO =
true, GLboolean ERRORS =
true);
97 bool _isInitialized{};
100 glm::vec3 cameraPosition;
101 glm::vec3 cameraQuaternion;
108 GLuint* _cutPositions{};
110 GLuint _currentFrameIndex{};
111 GLuint _currentCutIndex{};
114 void _updateCameraAttributesForCurrentFrame();
118 GLfloat _aspectRatio{};
119 GLfloat _nearClipPlane{};
120 GLfloat _farClipPlane{};
125 const char *
const MD5CAMERA_FILE,
127 const GLuint firstCutToRun,
128 const GLfloat aspectRatio,
130 const GLfloat nearClipPlane,
131 const GLfloat farClipPlane,
132 const GLboolean INFO,
133 const GLboolean ERRORS
135 _aspectRatio(aspectRatio),
136 _nearClipPlane(nearClipPlane),
137 _farClipPlane(farClipPlane),
141 _cutPositions(nullptr),
143 _currentFrameIndex(0),
144 _currentCutIndex(firstCutToRun),
145 _advancementStrategy(advancementStrategy)
147 mProjectionMatrix = glm::perspective(_fovy, _aspectRatio, _nearClipPlane, _farClipPlane);
149 _isInitialized = _loadMD5CameraFromFile(MD5CAMERA_FILE, INFO, ERRORS);
158 _nearClipPlane(0.001f),
159 _farClipPlane(1000.0f),
163 _cutPositions(nullptr),
165 _currentFrameIndex(0),
185inline void CSCI441::MD5Camera::_copy(
const MD5Camera& OTHER) {
187 _aspectRatio = OTHER._aspectRatio;
188 _nearClipPlane = OTHER._nearClipPlane;
189 _farClipPlane = OTHER._farClipPlane;
190 _frameRate = OTHER._frameRate;
191 _currentFrameIndex = OTHER._currentFrameIndex;
192 _currentCutIndex = OTHER._currentCutIndex;
193 _advancementStrategy = OTHER._advancementStrategy;
195 _isInitialized = OTHER._isInitialized;
197 _numCuts = OTHER._numCuts;
198 _cutPositions =
new GLuint[_numCuts];
199 for(
unsigned int i = 0; i < _numCuts; i++) {
200 _cutPositions[i] = OTHER._cutPositions[i];
203 _numFrames = OTHER._numFrames;
204 _frames =
new Frame[_numFrames];
205 for(
unsigned int i = 0; i < _numFrames; i++) {
206 _frames[i] = OTHER._frames[i];
210inline void CSCI441::MD5Camera::_free() {
212 free( _cutPositions );
216inline bool CSCI441::MD5Camera::_loadMD5CameraFromFile(
217 const char *
const MD5CAMERA_FILE,
218 const GLboolean INFO,
219 const GLboolean ERRORS
221 if ( INFO ) fprintf( stdout,
"[.md5camera]: -=-=-=-=-=-=-=- BEGIN %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
226 std::ifstream md5CameraFile(MD5CAMERA_FILE);
227 if( !md5CameraFile.is_open() ) {
228 if (ERRORS) fprintf( stderr,
"[.md5camera]: [ERROR]: Could not open \"%s\"\n", MD5CAMERA_FILE );
229 if ( INFO ) fprintf( stdout,
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
233 std::string sectionLabel, commandLineStr, brace;
235 Frame frame = { glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 45.0f };
238 md5CameraFile >> sectionLabel >> md5version;
239 if(sectionLabel !=
"MD5Version" || md5version != 10) {
240 if (ERRORS) fprintf (stderr,
"[.md5camera]: [ERROR]: improper MD5Camera version found \"%s %d\"\n", sectionLabel.c_str(), md5version );
241 if ( INFO ) fprintf( stdout,
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
246 md5CameraFile >> sectionLabel;
247 getline(md5CameraFile, commandLineStr);
249 for(
unsigned short i = 0; i < 5; i++) {
250 md5CameraFile >> sectionLabel;
251 if(sectionLabel ==
"numFrames") {
253 md5CameraFile >> _numFrames;
254 _frames = (Frame*)malloc(
sizeof(Frame) * _numFrames);
255 }
else if(sectionLabel ==
"frameRate") {
257 md5CameraFile >> _frameRate;
258 }
else if(sectionLabel ==
"numCuts") {
260 md5CameraFile >> _numCuts;
261 _cutPositions = (GLuint*)malloc(
sizeof(GLuint) * _numCuts);
262 }
else if(sectionLabel ==
"cuts") {
267 md5CameraFile >> brace;
268 for(
unsigned int cutNumber = 0; cutNumber < _numCuts; cutNumber++) {
269 md5CameraFile >> _cutPositions[cutNumber];
271 md5CameraFile >> brace;
272 _currentFrameIndex = _cutPositions[_currentCutIndex];
273 }
else if(sectionLabel ==
"camera") {
277 md5CameraFile >> brace;
278 for(
unsigned int frameNumber = 0; frameNumber < _numFrames; frameNumber++) {
279 md5CameraFile >> brace >> frame.cameraPosition.x >> frame.cameraPosition.y >> frame.cameraPosition.z >> brace;
280 md5CameraFile >> brace >> frame.cameraQuaternion.x >> frame.cameraQuaternion.y >> frame.cameraQuaternion.z >> brace;
281 md5CameraFile >> frame.fieldOfView;
283 md5CameraFile >> brace;
285 if (ERRORS) fprintf( stderr,
"[.md5camera]: [ERROR]: unknown section label found \"%s\"\n", sectionLabel.c_str() );
286 if ( INFO ) fprintf( stdout,
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n", MD5CAMERA_FILE );
292 printf(
"[.md5camera]: Camera Stats:\n" );
293 printf(
"[.md5camera]: Num Frames:\t%u\tFrame Rate:\t%u\tNum Cuts: \t%u\n", _numFrames, _frameRate, _numCuts );
297 double seconds = difftime( end, start );
300 printf(
"[.md5camera]: Completed in %.3fs\n", seconds );
301 printf(
"[.md5camera]: -=-=-=-=-=-=-=- END %s Info -=-=-=-=-=-=-=- \n\n", MD5CAMERA_FILE );
309 if( !_isInitialized )
return;
314 if( _currentFrameIndex == _numFrames - 1) {
315 switch(_advancementStrategy) {
316 case AdvancementStrategy::LOOP_ALL_CUTS:
318 _currentCutIndex = 0;
319 case AdvancementStrategy::LOOP_SINGLE_CUT:
321 _currentFrameIndex = _cutPositions[ _currentCutIndex ];
324 case AdvancementStrategy::RUN_SINGLE_CUT:
325 case AdvancementStrategy::RUN_ALL_CUTS:
331 else if( _currentCutIndex == _numCuts - 1 ) {
333 _currentFrameIndex++;
338 if( _currentFrameIndex == _cutPositions[_currentCutIndex + 1] - 1 ) {
339 switch(_advancementStrategy) {
340 case AdvancementStrategy::RUN_ALL_CUTS:
341 case AdvancementStrategy::LOOP_ALL_CUTS:
344 case AdvancementStrategy::LOOP_SINGLE_CUT:
346 _currentFrameIndex = _cutPositions[ _currentCutIndex ];
349 case AdvancementStrategy::RUN_SINGLE_CUT:
355 _currentFrameIndex++;
358 _updateCameraAttributesForCurrentFrame();
363 if( !_isInitialized )
return;
368 if( _currentFrameIndex == 0) {
369 switch(_advancementStrategy) {
370 case AdvancementStrategy::LOOP_ALL_CUTS:
372 _currentCutIndex = _numFrames-1;
375 case AdvancementStrategy::LOOP_SINGLE_CUT:
376 if( _numCuts == 1 ) {
378 _currentCutIndex = _numFrames-1;
381 _currentFrameIndex = _cutPositions[ _currentCutIndex+1 ] - 1;
385 case AdvancementStrategy::RUN_SINGLE_CUT:
386 case AdvancementStrategy::RUN_ALL_CUTS:
392 else if( _currentCutIndex == 0 ) {
394 _currentFrameIndex--;
399 if( _currentFrameIndex == _cutPositions[_currentCutIndex] ) {
400 switch(_advancementStrategy) {
401 case AdvancementStrategy::RUN_ALL_CUTS:
402 case AdvancementStrategy::LOOP_ALL_CUTS:
405 case AdvancementStrategy::LOOP_SINGLE_CUT:
407 _currentFrameIndex = _cutPositions[ _currentCutIndex+1 ] - 1;
410 case AdvancementStrategy::RUN_SINGLE_CUT:
416 _currentFrameIndex--;
419 _updateCameraAttributesForCurrentFrame();
422inline void CSCI441::MD5Camera::_updateCameraAttributesForCurrentFrame() {
424 mCameraPosition = _frames[_currentFrameIndex].cameraPosition;
428 glm::vec4 q(_frames[_currentFrameIndex].cameraQuaternion, 0.0f);
429 GLfloat t = 1.0f - (q.x * q.x) - (q.y * q.y) - (q.z * q.z);
436 glm::vec3 defaultCameraDirection(0.0f, 0.0f, -1.0f);
437 glm::vec4 inverseQ(-q.x, -q.y, -q.z, q.w);
438 inverseQ = glm::normalize(inverseQ);
440 glm::vec4 tmp( (q.w * defaultCameraDirection.x) + (q.y * defaultCameraDirection.z) - (q.z * defaultCameraDirection.y),
441 (q.w * defaultCameraDirection.y) + (q.z * defaultCameraDirection.x) - (q.x * defaultCameraDirection.z),
442 (q.w * defaultCameraDirection.z) + (q.x * defaultCameraDirection.y) - (q.y * defaultCameraDirection.x),
443 -(q.w * defaultCameraDirection.x) - (q.y * defaultCameraDirection.y) - (q.z * defaultCameraDirection.z) );
444 glm::vec4 rotatedCameraDirection((tmp.x * inverseQ.w) + (tmp.w * inverseQ.x) + (tmp.y * inverseQ.z) - (tmp.z * inverseQ.y),
445 (tmp.y * inverseQ.w) + (tmp.w * inverseQ.y) + (tmp.z * inverseQ.x) - (tmp.x * inverseQ.z),
446 (tmp.z * inverseQ.w) + (tmp.w * inverseQ.z) + (tmp.x * inverseQ.y) - (tmp.y * inverseQ.x),
447 (tmp.w * inverseQ.w) - (tmp.x * inverseQ.x) - (tmp.y * inverseQ.y) - (tmp.z * inverseQ.z) );
448 mCameraDirection = glm::vec3( rotatedCameraDirection.x, rotatedCameraDirection.y, rotatedCameraDirection.z );
449 mCameraLookAtPoint = mCameraPosition + mCameraDirection;
452 glm::vec3 defaultCameraUpVector(0.0f, 1.0f, 0.0f);
453 glm::vec4 tmp2( (q.w * defaultCameraUpVector.x) + (q.y * defaultCameraUpVector.z) - (q.z * defaultCameraUpVector.y),
454 (q.w * defaultCameraUpVector.y) + (q.z * defaultCameraUpVector.x) - (q.x * defaultCameraUpVector.z),
455 (q.w * defaultCameraUpVector.z) + (q.x * defaultCameraUpVector.y) - (q.y * defaultCameraUpVector.x),
456 -(q.w * defaultCameraUpVector.x) - (q.y * defaultCameraUpVector.y) - (q.z * defaultCameraUpVector.z) );
457 glm::vec4 rotatedCameraUpVector((tmp.x * inverseQ.w) + (tmp.w * inverseQ.x) + (tmp.y * inverseQ.z) - (tmp.z * inverseQ.y),
458 (tmp.y * inverseQ.w) + (tmp.w * inverseQ.y) + (tmp.z * inverseQ.x) - (tmp.x * inverseQ.z),
459 (tmp.z * inverseQ.w) + (tmp.w * inverseQ.z) + (tmp.x * inverseQ.y) - (tmp.y * inverseQ.x),
460 (tmp.w * inverseQ.w) - (tmp.x * inverseQ.x) - (tmp.y * inverseQ.y) - (tmp.z * inverseQ.z) );
461 mCameraUpVector = glm::vec3(rotatedCameraUpVector.x, rotatedCameraUpVector.y, rotatedCameraUpVector.z);
467 _fovy = _frames[_currentFrameIndex].fieldOfView;
468 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:37
glm::mat4 mProjectionMatrix
stores the Projection Matrix
Definition: Camera.hpp:164
A camera that implements the MD5Camera specification.
Definition: MD5Camera.hpp:28
void moveForward(GLfloat unused) final
steps forward along the camera's view
Definition: MD5Camera.hpp:307
MD5Camera & operator=(const MD5Camera &)
deep copy another MD5Camera
Definition: MD5Camera.hpp:172
~MD5Camera() final
delete cuts and frames
Definition: MD5Camera.hpp:181
AdvancementStrategy
what to do when the end of a cut is reached
Definition: MD5Camera.hpp:33
@ 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) final
steps backward along the camera's view
Definition: MD5Camera.hpp:361
void recomputeOrientation() final
Uses theta, phi, & radius to update the camera's view matrix parameters. The camera orientation is co...
Definition: MD5Camera.hpp:88
MD5Camera()=delete
must create camera object from parameterized constructor
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17