diff --git a/CHANGELOG.md b/CHANGELOG.md index 9905156f..9337c94a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Revision History -## v ?.?.? - ?? ??? ???? +## v 5.4.0 - 26 Aug 2024 - Updated glm dependency to v1.0.1 - Added half sphere and dome to HUD example - Fixed shader uniform debug output typos diff --git a/csci441.dox.config b/csci441.dox.config index baedbb15..1cbbc497 100644 --- a/csci441.dox.config +++ b/csci441.dox.config @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "CSCI441 OpenGL Library" -PROJECT_NUMBER = 5.3.0 +PROJECT_NUMBER = 5.4.0 PROJECT_BRIEF = "CS@Mines CSCI441 Computer Graphics Course Library" PROJECT_LOGO = OUTPUT_DIRECTORY = diff --git a/docs/_arcball_cam_8hpp.html b/docs/_arcball_cam_8hpp.html index 9bc37a67..9d283224 100644 --- a/docs/_arcball_cam_8hpp.html +++ b/docs/_arcball_cam_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_arcball_cam_8hpp_source.html b/docs/_arcball_cam_8hpp_source.html index c0d8167d..b8056c96 100644 --- a/docs/_arcball_cam_8hpp_source.html +++ b/docs/_arcball_cam_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_c_s_c_i441_8hpp.html b/docs/_c_s_c_i441_8hpp.html index cc86bd04..b6af771b 100644 --- a/docs/_c_s_c_i441_8hpp.html +++ b/docs/_c_s_c_i441_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
@@ -89,7 +89,10 @@ #include "ModelLoader.hpp"
#include "objects.hpp"
#include "OpenGL3DEngine.hpp"
+#include "OpenGLEngine.hpp"
#include "OpenGLUtils.hpp"
+#include "OrthographicCamera.hpp"
+#include "PerspectiveCamera.hpp"
#include "ShaderProgram.hpp"
#include "ShaderProgramPipeline.hpp"
#include "ShaderUtils.hpp"
diff --git a/docs/_c_s_c_i441_8hpp_source.html b/docs/_c_s_c_i441_8hpp_source.html index 6bd924a8..269b4368 100644 --- a/docs/_c_s_c_i441_8hpp_source.html +++ b/docs/_c_s_c_i441_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
@@ -90,15 +90,18 @@
44#include "ModelLoader.hpp" // to load OBJ, OFF, PLY, STL files
45#include "objects.hpp" // include 3D objects (cube, cylinder, cone, torus, sphere, disk, teapot)
46#include "OpenGL3DEngine.hpp" // to create a concrete 3D Rendering engine
-
47#include "OpenGLUtils.hpp" // to query OpenGL features
-
48#include "ShaderProgram.hpp" // helper class to compile and use shaders
-
49#include "ShaderProgramPipeline.hpp"// helper class to compile and use shader program pipelines
-
50#include "ShaderUtils.hpp" // helper functions to work with shader programs
-
51#include "SimpleShader.hpp" // default shader programs for 2D and 3D applications
-
52#include "TextureUtils.hpp" // helper functions for registering textures
-
53#include "UniformBufferObject.hpp" // helper class to use UBOs
-
54
-
55#endif // CSCI441_CSCI441_HPP
+
47#include "OpenGLEngine.hpp" // to create a concrete Rendering engine
+
48#include "OpenGLUtils.hpp" // to query OpenGL features
+
49#include "OrthographicCamera.hpp" // to create a camera with an orthographic projection
+
50#include "PerspectiveCamera.hpp" // to create a camera with a perspective projection
+
51#include "ShaderProgram.hpp" // helper class to compile and use shaders
+
52#include "ShaderProgramPipeline.hpp"// helper class to compile and use shader program pipelines
+
53#include "ShaderUtils.hpp" // helper functions to work with shader programs
+
54#include "SimpleShader.hpp" // default shader programs for 2D and 3D applications
+
55#include "TextureUtils.hpp" // helper functions for registering textures
+
56#include "UniformBufferObject.hpp" // helper class to use UBOs
+
57
+
58#endif // CSCI441_CSCI441_HPP
Concrete Arcball Camera implementation with Perspective Projection.
Abstract Camera class to be placed (position and orientation) within our scene.
Class to work with OpenGL Compute Shaders.
@@ -110,6 +113,7 @@
Doom3 MD5 Model + Animation implementations.
Loads OBJ+MTL, OFF, PLY, STL object files into a VAO.
Abstract class engine class to setup a 3D world with an arcball camera, storage for left button state...
+
Abstract class engine class to setup window, register callbacks, vaos, textures, and shaders,...
Helper functions to work with OpenGL 3.0+.
Class to work with OpenGL 4.0+ Shaders.
Class to work with Shader Program Pipelines.
diff --git a/docs/_camera_8hpp.html b/docs/_camera_8hpp.html index 45d0b947..696c2ff0 100644 --- a/docs/_camera_8hpp.html +++ b/docs/_camera_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_camera_8hpp_source.html b/docs/_camera_8hpp_source.html index 1f66053c..7e958eb9 100644 --- a/docs/_camera_8hpp_source.html +++ b/docs/_camera_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_compute_shader_program_8hpp.html b/docs/_compute_shader_program_8hpp.html index 4e23d222..cb9b70a6 100644 --- a/docs/_compute_shader_program_8hpp.html +++ b/docs/_compute_shader_program_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_compute_shader_program_8hpp_source.html b/docs/_compute_shader_program_8hpp_source.html index 87c72d33..76ecf20b 100644 --- a/docs/_compute_shader_program_8hpp_source.html +++ b/docs/_compute_shader_program_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_fixed_cam_8hpp.html b/docs/_fixed_cam_8hpp.html index ecd09065..3c0c7722 100644 --- a/docs/_fixed_cam_8hpp.html +++ b/docs/_fixed_cam_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_fixed_cam_8hpp_source.html b/docs/_fixed_cam_8hpp_source.html index 182b3dfe..0d847a12 100644 --- a/docs/_fixed_cam_8hpp_source.html +++ b/docs/_fixed_cam_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_framebuffer_utils_8hpp.html b/docs/_framebuffer_utils_8hpp.html index 947058a9..1a2ca458 100644 --- a/docs/_framebuffer_utils_8hpp.html +++ b/docs/_framebuffer_utils_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_framebuffer_utils_8hpp_source.html b/docs/_framebuffer_utils_8hpp_source.html index 1d167abe..609be466 100644 --- a/docs/_framebuffer_utils_8hpp_source.html +++ b/docs/_framebuffer_utils_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_free_cam_8hpp.html b/docs/_free_cam_8hpp.html index 94c74a4f..d0e02dbd 100644 --- a/docs/_free_cam_8hpp.html +++ b/docs/_free_cam_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_free_cam_8hpp_source.html b/docs/_free_cam_8hpp_source.html index a8542f36..b344d37e 100644 --- a/docs/_free_cam_8hpp_source.html +++ b/docs/_free_cam_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_h_u_d_camera_8hpp.html b/docs/_h_u_d_camera_8hpp.html index 88b10510..c26ffd42 100644 --- a/docs/_h_u_d_camera_8hpp.html +++ b/docs/_h_u_d_camera_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_h_u_d_camera_8hpp_source.html b/docs/_h_u_d_camera_8hpp_source.html index 8f8bc312..a788f586 100644 --- a/docs/_h_u_d_camera_8hpp_source.html +++ b/docs/_h_u_d_camera_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_m_d5_camera_8hpp.html b/docs/_m_d5_camera_8hpp.html index 61c512a3..2e9cd792 100644 --- a/docs/_m_d5_camera_8hpp.html +++ b/docs/_m_d5_camera_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
diff --git a/docs/_m_d5_camera_8hpp_source.html b/docs/_m_d5_camera_8hpp_source.html index b1bcf99f..1d8fd846 100644 --- a/docs/_m_d5_camera_8hpp_source.html +++ b/docs/_m_d5_camera_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
@@ -452,7 +452,7 @@
435 // set direction and look at point
436 glm::vec3 defaultCameraDirection(0.0f, 0.0f, -1.0f);
437 glm::vec4 inverseQ(-q.x, -q.y, -q.z, q.w);
-
438 glm::normalize(inverseQ);
+
438 inverseQ = glm::normalize(inverseQ);
439
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),
diff --git a/docs/_m_d5_model_8hpp.html b/docs/_m_d5_model_8hpp.html index ef912630..a66e11f0 100644 --- a/docs/_m_d5_model_8hpp.html +++ b/docs/_m_d5_model_8hpp.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
@@ -72,7 +72,8 @@
MD5Model.hpp File Reference
diff --git a/docs/_m_d5_model_8hpp_source.html b/docs/_m_d5_model_8hpp_source.html index 4a257d13..cfe8f4c8 100644 --- a/docs/_m_d5_model_8hpp_source.html +++ b/docs/_m_d5_model_8hpp_source.html @@ -21,7 +21,7 @@ -
CSCI441 OpenGL Library 5.3.0 +
CSCI441 OpenGL Library 5.4.0
CS@Mines CSCI441 Computer Graphics Course Library
@@ -121,1012 +121,1014 @@
56#include <glm/exponential.hpp>
57#include <glm/ext/quaternion_common.hpp>
58#include <glm/ext/quaternion_float.hpp>
-
59#include <glm/gtx/quaternion.hpp>
-
60
-
61#include <cassert>
-
62#include <cmath>
-
63#include <cstdio>
-
64#include <cstdlib>
-
65#include <cstring>
-
66
-
67namespace CSCI441 {
+
59
+
60#define GLM_ENABLE_EXPERIMENTAL
+
61#include <glm/gtx/quaternion.hpp>
+
62
+
63#include <cassert>
+
64#include <cmath>
+
65#include <cstdio>
+
66#include <cstdlib>
+
67#include <cstring>
68
-
73 class [[maybe_unused]] MD5Model {
-
74 protected:
-
75 // md5mesh types
-
79 struct MD5Joint {
-
83 static const GLint NULL_JOINT = -1;
-
87 char name[256] = "";
-
91 GLint parent = NULL_JOINT;
-
95 glm::vec3 position = {0.0f, 0.0f, 0.0f};
-
99 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
-
100 };
-
101
-
105 struct MD5Vertex {
-
109 glm::vec2 texCoord = {0.0f, 0.0f};
-
113 GLint start = 0;
-
117 GLint count = 0;
-
118 };
-
119
-
123 struct MD5Triangle {
-
127 GLint index[3] = {0};
-
128 };
-
129
-
133 struct MD5Weight {
-
137 GLint joint = MD5Joint::NULL_JOINT;
-
141 GLfloat bias = 0.f;
-
145 glm::vec3 position = {0.0f, 0.0f, 0.0f};
-
146 };
-
147
-
151 struct MD5Texture {
-
155 GLuint texHandle = 0;
-
159 char filename[512] = "";
-
160 };
-
161
-
165 struct MD5Mesh {
-
169 MD5Vertex *vertices = nullptr;
-
173 MD5Triangle *triangles = nullptr;
-
177 MD5Weight *weights = nullptr;
-
181 MD5Texture textures[4];
- - - - -
201 HEIGHT
-
202 };
-
203
-
207 GLint numVertices = 0;
-
211 GLint numTriangles = 0;
-
215 GLint numWeights = 0;
-
216
-
220 char shader[512] = "";
-
221 };
-
222
-
223 // md5anim types
- -
231 char name[256] = "";
-
235 GLint parent = MD5Joint::NULL_JOINT;
-
239 GLuint flags = 0;
-
243 GLint startIndex = 0;
-
244 };
-
245
- -
253 glm::vec3 position = {0.0f, 0.0f, 0.0f};
-
257 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
-
258 };
-
259
- -
268 glm::vec3 min = {0.0f, 0.0f, 0.0f};
-
272 glm::vec3 max = {0.0f, 0.0f, 0.0f};
-
273 };
-
274
- -
282 GLint numFrames = 0;
-
287 GLint numJoints = 0;
-
292 GLint frameRate = 0;
-
293
-
297 MD5Joint **skeletonFrames = nullptr;
-
301 MD5BoundingBox *boundingBoxes = nullptr;
-
302 };
-
303
- -
311 GLint currFrame = 0;
-
315 GLint nextFrame = 0;
-
316
-
320 GLfloat lastTime = 0.0f;
-
325 GLfloat maxTime = 0.0f;
-
326 };
-
327
-
328 public:
-
333 MD5Model();
-
337 ~MD5Model();
-
338
-
342 MD5Model(const MD5Model&) = delete;
-
346 MD5Model& operator=(const MD5Model&) = delete;
-
347
-
354 [[maybe_unused]] bool loadMD5Model(const char* MD5_MESH_FILE, const char* MD5_ANIM_FILE = "");
-
355
-
360 [[nodiscard]] bool isAnimated() const { return _isAnimated; }
-
361
-
362 // md5mesh prototypes
-
368 [[nodiscard]] bool readMD5Model(const char* FILENAME);
-
377 [[maybe_unused]]void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc);
-
381 [[maybe_unused]] void draw() const;
-
385 [[maybe_unused]] void drawSkeleton() const;
-
386
-
387 // md5anim prototypes
-
393 [[nodiscard]] bool readMD5Anim(const char* filename);
-
398 void animate(GLfloat dt);
-
399
-
400 private:
-
401 MD5Joint* _baseSkeleton;
-
402 MD5Mesh* _meshes;
-
403
-
404 GLint _numJoints;
-
405 GLint _numMeshes;
-
406
-
407 // vertex array related stuff
-
408 GLint _maxVertices;
-
409 GLint _maxTriangles;
-
410
-
411 glm::vec3* _vertexArray;
-
412 glm::vec2* _texelArray;
-
413 GLuint* _vertexIndicesArray;
-
414
-
415 GLuint _vao;
-
416 GLuint _vbo[2];
-
417
-
418 GLuint _skeletonVAO;
-
419 GLuint _skeletonVBO;
-
420
-
424 MD5Joint* _skeleton;
-
428 MD5Animation _animation;
-
432 bool _isAnimated;
-
436 MD5AnimationState _animationInfo;
-
437
-
438 void _prepareMesh(const MD5Mesh* pMESH) const;
-
439 void _drawMesh(const MD5Mesh* pMESH) const;
-
440 [[nodiscard]] bool _checkAnimValidity() const;
-
441 static void _buildFrameSkeleton(const MD5JointInfo* pJOINT_INFOS,
-
442 const MD5BaseFrameJoint* pBASE_FRAME,
-
443 const GLfloat* pANIM_FRAME_DATA,
-
444 MD5Joint* pSkeletonFrame,
-
445 GLint NUM_JOINTS);
-
446 void _interpolateSkeletons(GLfloat interp);
-
447 void _freeModel();
-
448 void _freeVertexArrays();
-
449 void _freeAnim();
-
450 };
-
451}
-
452
-
453//----------------------------------------------------------------------------------------------------
+
69namespace CSCI441 {
+
70
+
75 class [[maybe_unused]] MD5Model {
+
76 protected:
+
77 // md5mesh types
+
81 struct MD5Joint {
+
85 static const GLint NULL_JOINT = -1;
+
89 char name[256] = "";
+
93 GLint parent = NULL_JOINT;
+
97 glm::vec3 position = {0.0f, 0.0f, 0.0f};
+
101 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
+
102 };
+
103
+
107 struct MD5Vertex {
+
111 glm::vec2 texCoord = {0.0f, 0.0f};
+
115 GLint start = 0;
+
119 GLint count = 0;
+
120 };
+
121
+
125 struct MD5Triangle {
+
129 GLint index[3] = {0};
+
130 };
+
131
+
135 struct MD5Weight {
+
139 GLint joint = MD5Joint::NULL_JOINT;
+
143 GLfloat bias = 0.f;
+
147 glm::vec3 position = {0.0f, 0.0f, 0.0f};
+
148 };
+
149
+
153 struct MD5Texture {
+
157 GLuint texHandle = 0;
+
161 char filename[512] = "";
+
162 };
+
163
+
167 struct MD5Mesh {
+
171 MD5Vertex *vertices = nullptr;
+
175 MD5Triangle *triangles = nullptr;
+
179 MD5Weight *weights = nullptr;
+
183 MD5Texture textures[4];
+ + + + +
203 HEIGHT
+
204 };
+
205
+
209 GLint numVertices = 0;
+
213 GLint numTriangles = 0;
+
217 GLint numWeights = 0;
+
218
+
222 char shader[512] = "";
+
223 };
+
224
+
225 // md5anim types
+ +
233 char name[256] = "";
+
237 GLint parent = MD5Joint::NULL_JOINT;
+
241 GLuint flags = 0;
+
245 GLint startIndex = 0;
+
246 };
+
247
+ +
255 glm::vec3 position = {0.0f, 0.0f, 0.0f};
+
259 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
+
260 };
+
261
+ +
270 glm::vec3 min = {0.0f, 0.0f, 0.0f};
+
274 glm::vec3 max = {0.0f, 0.0f, 0.0f};
+
275 };
+
276
+ +
284 GLint numFrames = 0;
+
289 GLint numJoints = 0;
+
294 GLint frameRate = 0;
+
295
+
299 MD5Joint **skeletonFrames = nullptr;
+
303 MD5BoundingBox *boundingBoxes = nullptr;
+
304 };
+
305
+ +
313 GLint currFrame = 0;
+
317 GLint nextFrame = 0;
+
318
+
322 GLfloat lastTime = 0.0f;
+
327 GLfloat maxTime = 0.0f;
+
328 };
+
329
+
330 public:
+
335 MD5Model();
+
339 ~MD5Model();
+
340
+
344 MD5Model(const MD5Model&) = delete;
+
348 MD5Model& operator=(const MD5Model&) = delete;
+
349
+
356 [[maybe_unused]] bool loadMD5Model(const char* MD5_MESH_FILE, const char* MD5_ANIM_FILE = "");
+
357
+
362 [[nodiscard]] bool isAnimated() const { return _isAnimated; }
+
363
+
364 // md5mesh prototypes
+
370 [[nodiscard]] bool readMD5Model(const char* FILENAME);
+
379 [[maybe_unused]]void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc);
+
383 [[maybe_unused]] void draw() const;
+
387 [[maybe_unused]] void drawSkeleton() const;
+
388
+
389 // md5anim prototypes
+
395 [[nodiscard]] bool readMD5Anim(const char* filename);
+
400 void animate(GLfloat dt);
+
401
+
402 private:
+
403 MD5Joint* _baseSkeleton;
+
404 MD5Mesh* _meshes;
+
405
+
406 GLint _numJoints;
+
407 GLint _numMeshes;
+
408
+
409 // vertex array related stuff
+
410 GLint _maxVertices;
+
411 GLint _maxTriangles;
+
412
+
413 glm::vec3* _vertexArray;
+
414 glm::vec2* _texelArray;
+
415 GLuint* _vertexIndicesArray;
+
416
+
417 GLuint _vao;
+
418 GLuint _vbo[2];
+
419
+
420 GLuint _skeletonVAO;
+
421 GLuint _skeletonVBO;
+
422
+
426 MD5Joint* _skeleton;
+
430 MD5Animation _animation;
+
434 bool _isAnimated;
+
438 MD5AnimationState _animationInfo;
+
439
+
440 void _prepareMesh(const MD5Mesh* pMESH) const;
+
441 void _drawMesh(const MD5Mesh* pMESH) const;
+
442 [[nodiscard]] bool _checkAnimValidity() const;
+
443 static void _buildFrameSkeleton(const MD5JointInfo* pJOINT_INFOS,
+
444 const MD5BaseFrameJoint* pBASE_FRAME,
+
445 const GLfloat* pANIM_FRAME_DATA,
+
446 MD5Joint* pSkeletonFrame,
+
447 GLint NUM_JOINTS);
+
448 void _interpolateSkeletons(GLfloat interp);
+
449 void _freeModel();
+
450 void _freeVertexArrays();
+
451 void _freeAnim();
+
452 };
+
453}
454
- -
456{
-
457 _baseSkeleton = nullptr;
-
458 _meshes = nullptr;
-
459 _numJoints = 0;
-
460 _numMeshes = 0;
-
461 _maxVertices = 0;
-
462 _maxTriangles = 0;
-
463 _vertexArray = nullptr;
-
464 _texelArray = nullptr;
-
465 _vertexIndicesArray = nullptr;
-
466 _vao = 0;
-
467 _vbo[0] = 0;
-
468 _vbo[1] = 0;
-
469 _skeletonVAO = 0;
-
470 _skeletonVBO = 0;
-
471 _animation = MD5Animation();
-
472 _skeleton = nullptr;
-
473 _animationInfo = MD5AnimationState();
-
474 _isAnimated = false;
-
475}
-
476
- -
478{
-
479 _freeVertexArrays();
-
480 _freeAnim();
-
481 _freeModel();
-
482}
-
483
-
484// load our MD5 model
-
485[[maybe_unused]]
-
486inline bool
- -
488 const char* MD5_MESH_FILE,
-
489 const char* MD5_ANIM_FILE
-
490) {
-
491 // Load MD5 _model file
-
492 if( readMD5Model(MD5_MESH_FILE) ) {
-
493 // if MD5 animation file name provided
-
494 if(strcmp(MD5_ANIM_FILE, "") != 0 ) {
-
495 // Load MD5 animation file
-
496 if( !readMD5Anim(MD5_ANIM_FILE) ) {
-
497 return false;
-
498 }
-
499 }
-
500 if( !isAnimated() ) {
-
501 printf ("[.MD5_ANIM_FILE]: no animation loaded.\n");
-
502 }
-
503 } else {
-
504 return false;
-
505 }
-
506 return true;
-
507}
-
508
-
509// Load an MD5 model from file.
-
510inline bool
- -
512 const char* FILENAME
-
513) {
-
514 FILE *fp;
-
515 char buff[512];
-
516 GLint version;
-
517 GLint currentMesh = 0;
-
518 GLint i;
-
519 unsigned long uli;
-
520
-
521 GLint totalVertices = 0;
-
522 GLint totalWeights = 0;
-
523 GLint totalTriangles = 0;
-
524
-
525 GLfloat minX = 999999, minY = 999999, minZ = 999999;
-
526 GLfloat maxX = -999999, maxY = -999999, maxZ = -999999;
-
527
-
528 printf("[.md5mesh]: about to read %s\n", FILENAME );
+
455//----------------------------------------------------------------------------------------------------
+
456
+ +
458{
+
459 _baseSkeleton = nullptr;
+
460 _meshes = nullptr;
+
461 _numJoints = 0;
+
462 _numMeshes = 0;
+
463 _maxVertices = 0;
+
464 _maxTriangles = 0;
+
465 _vertexArray = nullptr;
+
466 _texelArray = nullptr;
+
467 _vertexIndicesArray = nullptr;
+
468 _vao = 0;
+
469 _vbo[0] = 0;
+
470 _vbo[1] = 0;
+
471 _skeletonVAO = 0;
+
472 _skeletonVBO = 0;
+
473 _animation = MD5Animation();
+
474 _skeleton = nullptr;
+
475 _animationInfo = MD5AnimationState();
+
476 _isAnimated = false;
+
477}
+
478
+ +
480{
+
481 _freeVertexArrays();
+
482 _freeAnim();
+
483 _freeModel();
+
484}
+
485
+
486// load our MD5 model
+
487[[maybe_unused]]
+
488inline bool
+ +
490 const char* MD5_MESH_FILE,
+
491 const char* MD5_ANIM_FILE
+
492) {
+
493 // Load MD5 _model file
+
494 if( readMD5Model(MD5_MESH_FILE) ) {
+
495 // if MD5 animation file name provided
+
496 if(strcmp(MD5_ANIM_FILE, "") != 0 ) {
+
497 // Load MD5 animation file
+
498 if( !readMD5Anim(MD5_ANIM_FILE) ) {
+
499 return false;
+
500 }
+
501 }
+
502 if( !isAnimated() ) {
+
503 printf ("[.MD5_ANIM_FILE]: no animation loaded.\n");
+
504 }
+
505 } else {
+
506 return false;
+
507 }
+
508 return true;
+
509}
+
510
+
511// Load an MD5 model from file.
+
512inline bool
+ +
514 const char* FILENAME
+
515) {
+
516 FILE *fp;
+
517 char buff[512];
+
518 GLint version;
+
519 GLint currentMesh = 0;
+
520 GLint i;
+
521 unsigned long uli;
+
522
+
523 GLint totalVertices = 0;
+
524 GLint totalWeights = 0;
+
525 GLint totalTriangles = 0;
+
526
+
527 GLfloat minX = 999999, minY = 999999, minZ = 999999;
+
528 GLfloat maxX = -999999, maxY = -999999, maxZ = -999999;
529
-
530 fp = fopen(FILENAME, "rb" );
-
531 if( !fp ) {
-
532 fprintf (stderr, "[.md5mesh]: Error: couldn't open \"%s\"!\n", FILENAME);
-
533 return false;
-
534 }
-
535
-
536 while( !feof(fp) ) {
-
537 // Read whole line
-
538 fgets( buff, sizeof(buff), fp );
-
539
-
540 if( sscanf(buff, " MD5Version %d", &version) == 1 ) {
-
541 if( version != 10 ) {
-
542 // Bad version
-
543 fprintf (stderr, "[.md5mesh]: Error: bad model version\n");
-
544 fclose (fp);
-
545 return false;
-
546 }
-
547 } else if( sscanf(buff, " numJoints %d", &_numJoints) == 1 ) {
-
548 if( _numJoints > 0 ) {
-
549 // Allocate memory for base skeleton joints
-
550 _baseSkeleton = new MD5Joint[_numJoints];
-
551 }
-
552 } else if( sscanf(buff, " numMeshes %d", &_numMeshes) == 1 ) {
-
553 if( _numMeshes > 0 ) {
-
554 // Allocate memory for meshes
-
555 _meshes = new MD5Mesh[_numMeshes];
-
556 }
-
557 } else if( strncmp(buff, "joints {", 8) == 0 ) {
-
558 // Read each joint
-
559 for(i = 0; i < _numJoints; ++i) {
-
560 MD5Joint *joint = &_baseSkeleton[i];
-
561
-
562 // Read whole line
-
563 fgets( buff, sizeof(buff), fp );
-
564
-
565 if( sscanf(buff, "%s %d ( %f %f %f ) ( %f %f %f )",
-
566 joint->name, &joint->parent,
-
567 &joint->position[0], &joint->position[1], &joint->position[2],
-
568 &joint->orientation[0],&joint->orientation[1], &joint->orientation[2]) == 8
-
569 ) {
-
570 // Compute the w component
-
571 joint->orientation.w = glm::extractRealComponent(joint->orientation);
-
572 }
-
573 }
-
574 } else if( strncmp(buff, "mesh {", 6) == 0 ) {
-
575 MD5Mesh *mesh = &_meshes[currentMesh];
-
576 GLint vert_index = 0;
-
577 GLint tri_index = 0;
-
578 GLint weight_index = 0;
-
579 GLfloat fdata[4];
-
580 GLint idata[3];
-
581
-
582 while( buff[0] != '}' && !feof(fp) ) {
-
583 // Read whole line
-
584 fgets( buff, sizeof(buff), fp );
-
585
-
586 if( strstr( buff, "shader ") ) {
-
587 GLint quote = 0, j = 0;
-
588
-
589 // Copy the shader name without the quote marks
-
590 for(uli = 0; uli < sizeof(buff) && (quote < 2); ++uli) {
-
591 if( buff[uli] == '\"' )
-
592 quote++;
-
593
-
594 if( (quote == 1) && (buff[uli] != '\"') ) {
-
595 mesh->shader[j] = buff[uli];
-
596 j++;
-
597 }
-
598 }
-
599 // there was a shader name
-
600 if( j > 0 ) {
-
601 // diffuse map
-
602 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
-
603 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, ".tga");
-
604 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
605 if( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle == 0 ) {
-
606 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
-
607 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, "_d.tga");
-
608 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
609 if( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle == 0 ) {
-
610 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
-
611 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, ".png");
-
612 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
613 }
-
614 }
-
615
-
616 // specular map
-
617 strcpy(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, mesh->shader);
-
618 strcat(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, "_s.tga");
-
619 mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
620 if( mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle == 0 ) {
-
621 strcpy(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, mesh->shader);
-
622 strcat(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, "_s.png");
-
623 mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
624 }
-
625
-
626 // normal map
-
627 strcpy(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, mesh->shader);
-
628 strcat(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, "_local.tga");
-
629 mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
630 if( mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle == 0 ) {
-
631 strcpy(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, mesh->shader);
-
632 strcat(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, "_local.png");
-
633 mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
634 }
-
635
-
636 // height map
-
637 strcpy(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, mesh->shader);
-
638 strcat(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, "_h.tga");
-
639 mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
640 if( mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle == 0 ) {
-
641 strcpy(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, mesh->shader);
-
642 strcat(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, "_h.png");
-
643 mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
-
644 }
-
645 }
-
646 } else if( sscanf(buff, " numverts %d", &mesh->numVertices) == 1 ) {
-
647 if( mesh->numVertices > 0 ) {
-
648 // Allocate memory for vertices
-
649 mesh->vertices = new MD5Vertex[mesh->numVertices];
-
650 }
-
651
-
652 if( mesh->numVertices > _maxVertices )
-
653 _maxVertices = mesh->numVertices;
-
654
-
655 totalVertices += mesh->numVertices;
-
656 } else if( sscanf(buff, " numtris %d", &mesh->numTriangles) == 1 ) {
-
657 if( mesh->numTriangles > 0 ) {
-
658 // Allocate memory for triangles
-
659 mesh->triangles = new MD5Triangle[mesh->numTriangles];
-
660 }
-
661
-
662 if( mesh->numTriangles > _maxTriangles )
-
663 _maxTriangles = mesh->numTriangles;
-
664
-
665 totalTriangles += mesh->numTriangles;
-
666 } else if( sscanf(buff, " numweights %d", &mesh->numWeights) == 1 ) {
-
667 if( mesh->numWeights > 0 ) {
-
668 // Allocate memory for vertex weights
-
669 mesh->weights = new MD5Weight[mesh->numWeights];
-
670 }
-
671
-
672 totalWeights += mesh->numWeights;
-
673 } else if( sscanf(buff, " vert %d ( %f %f ) %d %d",
-
674 &vert_index,
-
675 &fdata[0], &fdata[1],
-
676 &idata[0], &idata[1]) == 5
-
677 ) {
-
678 // Copy vertex data
-
679 mesh->vertices[vert_index].texCoord.s = fdata[0];
-
680 mesh->vertices[vert_index].texCoord.t = fdata[1];
-
681 mesh->vertices[vert_index].start = idata[0];
-
682 mesh->vertices[vert_index].count = idata[1];
-
683 } else if( sscanf(buff, " tri %d %d %d %d",
-
684 &tri_index,
-
685 &idata[0], &idata[1], &idata[2]) == 4
-
686 ) {
-
687 // Copy triangle data
-
688 mesh->triangles[tri_index ].index[0] = idata[0];
-
689 mesh->triangles[tri_index ].index[1] = idata[1];
-
690 mesh->triangles[tri_index ].index[2] = idata[2];
-
691 } else if( sscanf(buff, " weight %d %d %f ( %f %f %f )",
-
692 &weight_index, &idata[0], &fdata[3],
-
693 &fdata[0], &fdata[1], &fdata[2]) == 6
-
694 ) {
-
695 // Copy vertex data
-
696 mesh->weights[weight_index].joint = idata[0];
-
697 mesh->weights[weight_index].bias = fdata[3];
-
698 mesh->weights[weight_index].position[0] = fdata[0];
-
699 mesh->weights[weight_index].position[1] = fdata[1];
-
700 mesh->weights[weight_index].position[2] = fdata[2];
-
701
-
702 if( fdata[0] < minX ) { minX = fdata[0]; }
-
703 if( fdata[0] > maxX ) { maxX = fdata[0]; }
-
704 if( fdata[1] < minY ) { minY = fdata[1]; }
-
705 if( fdata[1] > maxY ) { maxY = fdata[1]; }
-
706 if( fdata[2] < minZ ) { minZ = fdata[2]; }
-
707 if( fdata[2] > maxZ ) { maxZ = fdata[2]; }
-
708 }
-
709 }
-
710
-
711 currentMesh++;
-
712 }
-
713 }
-
714
-
715 fclose(fp);
+
530 printf("[.md5mesh]: about to read %s\n", FILENAME );
+
531
+
532 fp = fopen(FILENAME, "rb" );
+
533 if( !fp ) {
+
534 fprintf (stderr, "[.md5mesh]: Error: couldn't open \"%s\"!\n", FILENAME);
+
535 return false;
+
536 }
+
537
+
538 while( !feof(fp) ) {
+
539 // Read whole line
+
540 fgets( buff, sizeof(buff), fp );
+
541
+
542 if( sscanf(buff, " MD5Version %d", &version) == 1 ) {
+
543 if( version != 10 ) {
+
544 // Bad version
+
545 fprintf (stderr, "[.md5mesh]: Error: bad model version\n");
+
546 fclose (fp);
+
547 return false;
+
548 }
+
549 } else if( sscanf(buff, " numJoints %d", &_numJoints) == 1 ) {
+
550 if( _numJoints > 0 ) {
+
551 // Allocate memory for base skeleton joints
+
552 _baseSkeleton = new MD5Joint[_numJoints];
+
553 }
+
554 } else if( sscanf(buff, " numMeshes %d", &_numMeshes) == 1 ) {
+
555 if( _numMeshes > 0 ) {
+
556 // Allocate memory for meshes
+
557 _meshes = new MD5Mesh[_numMeshes];
+
558 }
+
559 } else if( strncmp(buff, "joints {", 8) == 0 ) {
+
560 // Read each joint
+
561 for(i = 0; i < _numJoints; ++i) {
+
562 MD5Joint *joint = &_baseSkeleton[i];
+
563
+
564 // Read whole line
+
565 fgets( buff, sizeof(buff), fp );
+
566
+
567 if( sscanf(buff, "%s %d ( %f %f %f ) ( %f %f %f )",
+
568 joint->name, &joint->parent,
+
569 &joint->position[0], &joint->position[1], &joint->position[2],
+
570 &joint->orientation[0],&joint->orientation[1], &joint->orientation[2]) == 8
+
571 ) {
+
572 // Compute the w component
+
573 joint->orientation.w = glm::extractRealComponent(joint->orientation);
+
574 }
+
575 }
+
576 } else if( strncmp(buff, "mesh {", 6) == 0 ) {
+
577 MD5Mesh *mesh = &_meshes[currentMesh];
+
578 GLint vert_index = 0;
+
579 GLint tri_index = 0;
+
580 GLint weight_index = 0;
+
581 GLfloat fdata[4];
+
582 GLint idata[3];
+
583
+
584 while( buff[0] != '}' && !feof(fp) ) {
+
585 // Read whole line
+
586 fgets( buff, sizeof(buff), fp );
+
587
+
588 if( strstr( buff, "shader ") ) {
+
589 GLint quote = 0, j = 0;
+
590
+
591 // Copy the shader name without the quote marks
+
592 for(uli = 0; uli < sizeof(buff) && (quote < 2); ++uli) {
+
593 if( buff[uli] == '\"' )
+
594 quote++;
+
595
+
596 if( (quote == 1) && (buff[uli] != '\"') ) {
+
597 mesh->shader[j] = buff[uli];
+
598 j++;
+
599 }
+
600 }
+
601 // there was a shader name
+
602 if( j > 0 ) {
+
603 // diffuse map
+
604 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
+
605 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, ".tga");
+
606 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
607 if( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle == 0 ) {
+
608 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
+
609 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, "_d.tga");
+
610 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
611 if( mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle == 0 ) {
+
612 strcpy(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, mesh->shader);
+
613 strcat(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, ".png");
+
614 mesh->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture(mesh->textures[MD5Mesh::TextureMap::DIFFUSE].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
615 }
+
616 }
+
617
+
618 // specular map
+
619 strcpy(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, mesh->shader);
+
620 strcat(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, "_s.tga");
+
621 mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
622 if( mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle == 0 ) {
+
623 strcpy(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, mesh->shader);
+
624 strcat(mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, "_s.png");
+
625 mesh->textures[MD5Mesh::TextureMap::SPECULAR].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::SPECULAR].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
626 }
+
627
+
628 // normal map
+
629 strcpy(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, mesh->shader);
+
630 strcat(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, "_local.tga");
+
631 mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
632 if( mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle == 0 ) {
+
633 strcpy(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, mesh->shader);
+
634 strcat(mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, "_local.png");
+
635 mesh->textures[MD5Mesh::TextureMap::NORMAL].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::NORMAL].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
636 }
+
637
+
638 // height map
+
639 strcpy(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, mesh->shader);
+
640 strcat(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, "_h.tga");
+
641 mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
642 if( mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle == 0 ) {
+
643 strcpy(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, mesh->shader);
+
644 strcat(mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, "_h.png");
+
645 mesh->textures[MD5Mesh::TextureMap::HEIGHT].texHandle = CSCI441::TextureUtils::loadAndRegisterTexture( mesh->textures[MD5Mesh::TextureMap::HEIGHT].filename, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_REPEAT, GL_REPEAT, false );
+
646 }
+
647 }
+
648 } else if( sscanf(buff, " numverts %d", &mesh->numVertices) == 1 ) {
+
649 if( mesh->numVertices > 0 ) {
+
650 // Allocate memory for vertices
+
651 mesh->vertices = new MD5Vertex[mesh->numVertices];
+
652 }
+
653
+
654 if( mesh->numVertices > _maxVertices )
+
655 _maxVertices = mesh->numVertices;
+
656
+
657 totalVertices += mesh->numVertices;
+
658 } else if( sscanf(buff, " numtris %d", &mesh->numTriangles) == 1 ) {
+
659 if( mesh->numTriangles > 0 ) {
+
660 // Allocate memory for triangles
+
661 mesh->triangles = new MD5Triangle[mesh->numTriangles];
+
662 }
+
663
+
664 if( mesh->numTriangles > _maxTriangles )
+
665 _maxTriangles = mesh->numTriangles;
+
666
+
667 totalTriangles += mesh->numTriangles;
+
668 } else if( sscanf(buff, " numweights %d", &mesh->numWeights) == 1 ) {
+
669 if( mesh->numWeights > 0 ) {
+
670 // Allocate memory for vertex weights
+
671 mesh->weights = new MD5Weight[mesh->numWeights];
+
672 }
+
673
+
674 totalWeights += mesh->numWeights;
+
675 } else if( sscanf(buff, " vert %d ( %f %f ) %d %d",
+
676 &vert_index,
+
677 &fdata[0], &fdata[1],
+
678 &idata[0], &idata[1]) == 5
+
679 ) {
+
680 // Copy vertex data
+
681 mesh->vertices[vert_index].texCoord.s = fdata[0];
+
682 mesh->vertices[vert_index].texCoord.t = fdata[1];
+
683 mesh->vertices[vert_index].start = idata[0];
+
684 mesh->vertices[vert_index].count = idata[1];
+
685 } else if( sscanf(buff, " tri %d %d %d %d",
+
686 &tri_index,
+
687 &idata[0], &idata[1], &idata[2]) == 4
+
688 ) {
+
689 // Copy triangle data
+
690 mesh->triangles[tri_index ].index[0] = idata[0];
+
691 mesh->triangles[tri_index ].index[1] = idata[1];
+
692 mesh->triangles[tri_index ].index[2] = idata[2];
+
693 } else if( sscanf(buff, " weight %d %d %f ( %f %f %f )",
+
694 &weight_index, &idata[0], &fdata[3],
+
695 &fdata[0], &fdata[1], &fdata[2]) == 6
+
696 ) {
+
697 // Copy vertex data
+
698 mesh->weights[weight_index].joint = idata[0];
+
699 mesh->weights[weight_index].bias = fdata[3];
+
700 mesh->weights[weight_index].position[0] = fdata[0];
+
701 mesh->weights[weight_index].position[1] = fdata[1];
+
702 mesh->weights[weight_index].position[2] = fdata[2];
+
703
+
704 if( fdata[0] < minX ) { minX = fdata[0]; }
+
705 if( fdata[0] > maxX ) { maxX = fdata[0]; }
+
706 if( fdata[1] < minY ) { minY = fdata[1]; }
+
707 if( fdata[1] > maxY ) { maxY = fdata[1]; }
+
708 if( fdata[2] < minZ ) { minZ = fdata[2]; }
+
709 if( fdata[2] > maxZ ) { maxZ = fdata[2]; }
+
710 }
+
711 }
+
712
+
713 currentMesh++;
+
714 }
+
715 }
716
-
717 _skeleton = _baseSkeleton;
+
717 fclose(fp);
718
-
719 printf("[.md5mesh]: finished reading %s\n", FILENAME );
-
720 printf("[.md5mesh]: read in %d meshes, %d joints, %d vertices, %d weights, and %d triangles\n", _numMeshes, _numJoints, totalVertices, totalWeights, totalTriangles );
-
721 printf( "[.md5mesh]: base pose %f units across in X, %f units across in Y, %f units across in Z\n", (maxX - minX), (maxY-minY), (maxZ - minZ) );
-
722 printf( "\n" );
-
723
-
724 return true;
-
725}
-
726
-
727//Free resources allocated for the model.
-
728inline void
-
729CSCI441::MD5Model::_freeModel()
-
730{
-
731 delete _baseSkeleton;
-
732 _baseSkeleton = nullptr;
-
733
-
734 // Free mesh data
-
735 for(GLint i = 0; i < _numMeshes; ++i) {
-
736 delete _meshes[i].vertices;
-
737 _meshes[i].vertices = nullptr;
-
738
-
739 delete _meshes[i].triangles;
-
740 _meshes[i].triangles = nullptr;
-
741
-
742 delete _meshes[i].weights;
-
743 _meshes[i].weights = nullptr;
-
744 }
-
745
-
746 delete _meshes;
-
747 _meshes = nullptr;
-
748}
-
749
-
750[[maybe_unused]]
-
751inline void
- -
753{
-
754 // Draw each mesh of the model
-
755 for(GLint i = 0; i < _numMeshes; ++i) {
-
756 MD5Mesh mesh = _meshes[i]; // get the mesh
-
757 _prepareMesh(&mesh); // do some preprocessing on it
-
758 _drawMesh(&mesh);
-
759 }
-
760}
-
761
-
762// Prepare a mesh for drawing. Compute mesh's final vertex positions
-
763// given a skeleton. Put the vertices in vertex arrays.
-
764inline void
-
765CSCI441::MD5Model::_prepareMesh(
-
766 const MD5Mesh *pMESH
-
767) const {
-
768 GLint i, j, k;
-
769
-
770 // Setup vertex indices
-
771 for(k = 0, i = 0; i < pMESH->numTriangles; ++i) {
-
772 for(j = 0; j < 3; ++j, ++k)
-
773 _vertexIndicesArray[k] = pMESH->triangles[i].index[j];
-
774 }
-
775
-
776 // Setup vertices
-
777 for(i = 0; i < pMESH->numVertices; ++i) {
-
778 glm::vec3 finalVertex = {0.0f, 0.0f, 0.0f };
-
779
-
780 // Calculate final vertex to draw with weights
-
781 for(j = 0; j < pMESH->vertices[i].count; ++j) {
-
782 const MD5Weight *weight = &pMESH->weights[pMESH->vertices[i].start + j];
-
783 const MD5Joint *joint = &_skeleton[weight->joint];
-
784
-
785 // Calculate transformed vertex for this weight
-
786 glm::vec3 weightedVertex;
-
787 weightedVertex = glm::rotate(joint->orientation, glm::vec4(weight->position, 0.0f));
-
788
-
789 // The sum of all weight->bias should be 1.0
-
790 finalVertex.x += (joint->position.x + weightedVertex.x) * weight->bias;
-
791 finalVertex.y += (joint->position.y + weightedVertex.y) * weight->bias;
-
792 finalVertex.z += (joint->position.z + weightedVertex.z) * weight->bias;
-
793 }
-
794
-
795 _vertexArray[i].x = finalVertex.x;
-
796 _vertexArray[i].y = finalVertex.y;
-
797 _vertexArray[i].z = finalVertex.z;
-
798
-
799 _texelArray[i].s = pMESH->vertices[i].texCoord.s;
-
800 _texelArray[i].t = pMESH->vertices[i].texCoord.t;
-
801 }
-
802
-
803 glBindVertexArray(_vao );
-
804 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
-
805 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * pMESH->numVertices, &_vertexArray[0] );
-
806 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _maxVertices, sizeof(glm::vec2) * pMESH->numVertices, &_texelArray[0] );
-
807 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
-
808 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint) * pMESH->numTriangles * 3, _vertexIndicesArray );
-
809}
-
810
-
811inline void
-
812CSCI441::MD5Model::_drawMesh(
-
813 const MD5Mesh *pMESH
-
814) const {
-
815 // Bind Diffuse Map
-
816 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle );
-
817
-
818 glBindVertexArray(_vao );
-
819 glDrawElements(GL_TRIANGLES, pMESH->numTriangles * 3, GL_UNSIGNED_INT, (void*)nullptr );
-
820}
-
821
-
822[[maybe_unused]]
-
823inline void
- -
825 GLuint vPosAttribLoc,
-
826 GLuint vColorAttribLoc,
-
827 GLuint vTexCoordAttribLoc
-
828) {
-
829 _vertexArray = new glm::vec3[_maxVertices];
-
830 _texelArray = new glm::vec2[_maxVertices];
-
831 _vertexIndicesArray = new GLuint[_maxTriangles * 3];
-
832
-
833 glGenVertexArrays( 1, &_vao );
-
834 glBindVertexArray(_vao );
-
835
-
836 glGenBuffers(2, _vbo );
-
837 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
-
838 glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _maxVertices + sizeof(glm::vec2) * _maxVertices, nullptr, GL_DYNAMIC_DRAW );
-
839
-
840 glEnableVertexAttribArray( vPosAttribLoc );
-
841 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)nullptr );
-
842
-
843 glEnableVertexAttribArray( vTexCoordAttribLoc );
-
844 glVertexAttribPointer( vTexCoordAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * _maxVertices) );
-
845
-
846 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
-
847 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * _maxTriangles * 3, nullptr, GL_DYNAMIC_DRAW );
-
848
-
849 printf("[.md5mesh]: Model VAO/VBO/IBO registered at %u/%u/%u\n", _vao, _vbo[0], _vbo[1] );
+
719 _skeleton = _baseSkeleton;
+
720
+
721 printf("[.md5mesh]: finished reading %s\n", FILENAME );
+
722 printf("[.md5mesh]: read in %d meshes, %d joints, %d vertices, %d weights, and %d triangles\n", _numMeshes, _numJoints, totalVertices, totalWeights, totalTriangles );
+
723 printf( "[.md5mesh]: base pose %f units across in X, %f units across in Y, %f units across in Z\n", (maxX - minX), (maxY-minY), (maxZ - minZ) );
+
724 printf( "\n" );
+
725
+
726 return true;
+
727}
+
728
+
729//Free resources allocated for the model.
+
730inline void
+
731CSCI441::MD5Model::_freeModel()
+
732{
+
733 delete _baseSkeleton;
+
734 _baseSkeleton = nullptr;
+
735
+
736 // Free mesh data
+
737 for(GLint i = 0; i < _numMeshes; ++i) {
+
738 delete _meshes[i].vertices;
+
739 _meshes[i].vertices = nullptr;
+
740
+
741 delete _meshes[i].triangles;
+
742 _meshes[i].triangles = nullptr;
+
743
+
744 delete _meshes[i].weights;
+
745 _meshes[i].weights = nullptr;
+
746 }
+
747
+
748 delete _meshes;
+
749 _meshes = nullptr;
+
750}
+
751
+
752[[maybe_unused]]
+
753inline void
+ +
755{
+
756 // Draw each mesh of the model
+
757 for(GLint i = 0; i < _numMeshes; ++i) {
+
758 MD5Mesh mesh = _meshes[i]; // get the mesh
+
759 _prepareMesh(&mesh); // do some preprocessing on it
+
760 _drawMesh(&mesh);
+
761 }
+
762}
+
763
+
764// Prepare a mesh for drawing. Compute mesh's final vertex positions
+
765// given a skeleton. Put the vertices in vertex arrays.
+
766inline void
+
767CSCI441::MD5Model::_prepareMesh(
+
768 const MD5Mesh *pMESH
+
769) const {
+
770 GLint i, j, k;
+
771
+
772 // Setup vertex indices
+
773 for(k = 0, i = 0; i < pMESH->numTriangles; ++i) {
+
774 for(j = 0; j < 3; ++j, ++k)
+
775 _vertexIndicesArray[k] = pMESH->triangles[i].index[j];
+
776 }
+
777
+
778 // Setup vertices
+
779 for(i = 0; i < pMESH->numVertices; ++i) {
+
780 glm::vec3 finalVertex = {0.0f, 0.0f, 0.0f };
+
781
+
782 // Calculate final vertex to draw with weights
+
783 for(j = 0; j < pMESH->vertices[i].count; ++j) {
+
784 const MD5Weight *weight = &pMESH->weights[pMESH->vertices[i].start + j];
+
785 const MD5Joint *joint = &_skeleton[weight->joint];
+
786
+
787 // Calculate transformed vertex for this weight
+
788 glm::vec3 weightedVertex;
+
789 weightedVertex = glm::rotate(joint->orientation, glm::vec4(weight->position, 0.0f));
+
790
+
791 // The sum of all weight->bias should be 1.0
+
792 finalVertex.x += (joint->position.x + weightedVertex.x) * weight->bias;
+
793 finalVertex.y += (joint->position.y + weightedVertex.y) * weight->bias;
+
794 finalVertex.z += (joint->position.z + weightedVertex.z) * weight->bias;
+
795 }
+
796
+
797 _vertexArray[i].x = finalVertex.x;
+
798 _vertexArray[i].y = finalVertex.y;
+
799 _vertexArray[i].z = finalVertex.z;
+
800
+
801 _texelArray[i].s = pMESH->vertices[i].texCoord.s;
+
802 _texelArray[i].t = pMESH->vertices[i].texCoord.t;
+
803 }
+
804
+
805 glBindVertexArray(_vao );
+
806 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
+
807 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * pMESH->numVertices, &_vertexArray[0] );
+
808 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _maxVertices, sizeof(glm::vec2) * pMESH->numVertices, &_texelArray[0] );
+
809 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
+
810 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint) * pMESH->numTriangles * 3, _vertexIndicesArray );
+
811}
+
812
+
813inline void
+
814CSCI441::MD5Model::_drawMesh(
+
815 const MD5Mesh *pMESH
+
816) const {
+
817 // Bind Diffuse Map
+
818 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle );
+
819
+
820 glBindVertexArray(_vao );
+
821 glDrawElements(GL_TRIANGLES, pMESH->numTriangles * 3, GL_UNSIGNED_INT, (void*)nullptr );
+
822}
+
823
+
824[[maybe_unused]]
+
825inline void
+ +
827 GLuint vPosAttribLoc,
+
828 GLuint vColorAttribLoc,
+
829 GLuint vTexCoordAttribLoc
+
830) {
+
831 _vertexArray = new glm::vec3[_maxVertices];
+
832 _texelArray = new glm::vec2[_maxVertices];
+
833 _vertexIndicesArray = new GLuint[_maxTriangles * 3];
+
834
+
835 glGenVertexArrays( 1, &_vao );
+
836 glBindVertexArray(_vao );
+
837
+
838 glGenBuffers(2, _vbo );
+
839 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
+
840 glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _maxVertices + sizeof(glm::vec2) * _maxVertices, nullptr, GL_DYNAMIC_DRAW );
+
841
+
842 glEnableVertexAttribArray( vPosAttribLoc );
+
843 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)nullptr );
+
844
+
845 glEnableVertexAttribArray( vTexCoordAttribLoc );
+
846 glVertexAttribPointer( vTexCoordAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * _maxVertices) );
+
847
+
848 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
+
849 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * _maxTriangles * 3, nullptr, GL_DYNAMIC_DRAW );
850
-
851 glGenVertexArrays( 1, &_skeletonVAO );
-
852 glBindVertexArray(_skeletonVAO );
-
853
-
854 glGenBuffers( 1, &_skeletonVBO );
-
855 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
-
856 glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints * 3 * 2, nullptr, GL_DYNAMIC_DRAW );
-
857
-
858 glEnableVertexAttribArray( vPosAttribLoc ); // vPos
-
859 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)nullptr );
-
860
-
861 glEnableVertexAttribArray( vColorAttribLoc ); // vColor
-
862 glVertexAttribPointer( vColorAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * _numJoints * 3) );
-
863
-
864 printf("[.md5mesh]: Skeleton VAO/VBO registered at %u/%u\n", _skeletonVAO, _skeletonVBO );
-
865}
-
866
-
867inline void
-
868CSCI441::MD5Model::_freeVertexArrays()
-
869{
-
870 delete[] _vertexArray;
-
871 _vertexArray = nullptr;
-
872
-
873 delete[] _vertexIndicesArray;
-
874 _vertexIndicesArray = nullptr;
-
875
-
876 delete[] _texelArray;
-
877 _texelArray = nullptr;
-
878
-
879 glDeleteVertexArrays( 1, &_vao );
-
880 glDeleteBuffers(2, _vbo );
-
881 glDeleteVertexArrays( 1, &_skeletonVAO );
-
882 glDeleteBuffers( 1, &_skeletonVBO );
-
883}
-
884
-
885// Draw the skeleton as lines and points (for joints).
-
886[[maybe_unused]]
-
887inline void
- -
889{
-
890 glBindVertexArray(_skeletonVAO );
-
891 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
-
892
-
893 glm::vec3 jointColor = {1.0f, 1.0f, 0.0f };
-
894 glm::vec3 boneColor = {1.0f, 0.0f, 1.0f };
-
895
-
896 // put in points for joints
-
897 for(GLint i = 0; i < _numJoints; ++i ) {
-
898 glBufferSubData(GL_ARRAY_BUFFER, i * sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[i].position) );
-
899 glBufferSubData(GL_ARRAY_BUFFER, i * sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &jointColor[0]);
-
900 }
-
901
-
902 // put in lines for bones
-
903 GLint numBones = 0;
-
904 for(GLint i = 0; i < _numJoints; ++i ) {
-
905 if( _skeleton[i].parent != MD5Joint::NULL_JOINT ) {
-
906 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[_skeleton[i].parent].position) );
-
907 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &boneColor[0]);
-
908
-
909 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[i].position) );
-
910 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &boneColor[0]);
-
911 numBones++;
-
912 }
-
913 }
-
914
-
915 glPointSize (5.0f);
-
916 glDrawArrays(GL_POINTS, 0, _numJoints );
-
917 glPointSize(1.0f);
-
918
-
919 glLineWidth( 3.0f );
-
920 glDrawArrays(GL_LINES, _numJoints, numBones * 2 );
-
921 glLineWidth(1.0f);
-
922}
-
923
-
924// Check if an animation can be used for a given model. Model's
-
925// skeleton and animation's skeleton must match.
-
926inline bool
-
927CSCI441::MD5Model::_checkAnimValidity() const
-
928{
-
929 // md5mesh and md5anim must have the same number of joints
-
930 if( _numJoints != _animation.numJoints ) {
-
931 printf("\n[.md5anim]: skeleton and animation do not have same number of joints. cannot apply animation to skeleton\n\n");
-
932 return false;
-
933 }
-
934
-
935 // We just check with frame[0]
-
936 for(GLint i = 0; i < _numJoints; ++i) {
-
937 // Joints must have the same parent index
-
938 if (_baseSkeleton[i].parent != _animation.skeletonFrames[0][i].parent) {
-
939 printf("\n[.md5anim]: skeleton and animation joints do not have same parent index. cannot apply animation to skeleton\n\n");
-
940 return false;
-
941 }
-
942
-
943 // Joints must have the same name
-
944 if (strcmp (_baseSkeleton[i].name, _animation.skeletonFrames[0][i].name) != 0) {
-
945 printf("\n[.md5anim]: skeleton and animation joints do not have same name. cannot apply animation to skeleton\n\n");
-
946 return false;
-
947 }
-
948 }
-
949
-
950 printf("\n[.md5anim]: skeleton and animation match. animation can be applied to skeleton\n\n");
-
951 return true;
-
952}
-
953
-
954// Build _skeleton for a given frame data.
-
955inline void
-
956CSCI441::MD5Model::_buildFrameSkeleton(
-
957 const MD5JointInfo* pJOINT_INFOS,
-
958 const MD5BaseFrameJoint* pBASE_FRAME,
-
959 const GLfloat* pANIM_FRAME_DATA,
-
960 MD5Joint* pSkeletonFrame,
-
961 const GLint NUM_JOINTS
-
962) {
-
963 if(pJOINT_INFOS == nullptr
-
964 || pBASE_FRAME == nullptr
-
965 || pANIM_FRAME_DATA == nullptr
-
966 || pSkeletonFrame == nullptr) return;
-
967
-
968 GLint i;
+
851 printf("[.md5mesh]: Model VAO/VBO/IBO registered at %u/%u/%u\n", _vao, _vbo[0], _vbo[1] );
+
852
+
853 glGenVertexArrays( 1, &_skeletonVAO );
+
854 glBindVertexArray(_skeletonVAO );
+
855
+
856 glGenBuffers( 1, &_skeletonVBO );
+
857 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
+
858 glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints * 3 * 2, nullptr, GL_DYNAMIC_DRAW );
+
859
+
860 glEnableVertexAttribArray( vPosAttribLoc ); // vPos
+
861 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)nullptr );
+
862
+
863 glEnableVertexAttribArray( vColorAttribLoc ); // vColor
+
864 glVertexAttribPointer( vColorAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * _numJoints * 3) );
+
865
+
866 printf("[.md5mesh]: Skeleton VAO/VBO registered at %u/%u\n", _skeletonVAO, _skeletonVBO );
+
867}
+
868
+
869inline void
+
870CSCI441::MD5Model::_freeVertexArrays()
+
871{
+
872 delete[] _vertexArray;
+
873 _vertexArray = nullptr;
+
874
+
875 delete[] _vertexIndicesArray;
+
876 _vertexIndicesArray = nullptr;
+
877
+
878 delete[] _texelArray;
+
879 _texelArray = nullptr;
+
880
+
881 glDeleteVertexArrays( 1, &_vao );
+
882 glDeleteBuffers(2, _vbo );
+
883 glDeleteVertexArrays( 1, &_skeletonVAO );
+
884 glDeleteBuffers( 1, &_skeletonVBO );
+
885}
+
886
+
887// Draw the skeleton as lines and points (for joints).
+
888[[maybe_unused]]
+
889inline void
+ +
891{
+
892 glBindVertexArray(_skeletonVAO );
+
893 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
+
894
+
895 glm::vec3 jointColor = {1.0f, 1.0f, 0.0f };
+
896 glm::vec3 boneColor = {1.0f, 0.0f, 1.0f };
+
897
+
898 // put in points for joints
+
899 for(GLint i = 0; i < _numJoints; ++i ) {
+
900 glBufferSubData(GL_ARRAY_BUFFER, i * sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[i].position) );
+
901 glBufferSubData(GL_ARRAY_BUFFER, i * sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &jointColor[0]);
+
902 }
+
903
+
904 // put in lines for bones
+
905 GLint numBones = 0;
+
906 for(GLint i = 0; i < _numJoints; ++i ) {
+
907 if( _skeleton[i].parent != MD5Joint::NULL_JOINT ) {
+
908 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[_skeleton[i].parent].position) );
+
909 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &boneColor[0]);
+
910
+
911 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3), sizeof(glm::vec3), &(_skeleton[i].position) );
+
912 glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _numJoints + (i * 2) * sizeof(glm::vec3) + sizeof(glm::vec3) + sizeof(glm::vec3) * _numJoints * 3, sizeof(glm::vec3), &boneColor[0]);
+
913 numBones++;
+
914 }
+
915 }
+
916
+
917 glPointSize (5.0f);
+
918 glDrawArrays(GL_POINTS, 0, _numJoints );
+
919 glPointSize(1.0f);
+
920
+
921 glLineWidth( 3.0f );
+
922 glDrawArrays(GL_LINES, _numJoints, numBones * 2 );
+
923 glLineWidth(1.0f);
+
924}
+
925
+
926// Check if an animation can be used for a given model. Model's
+
927// skeleton and animation's skeleton must match.
+
928inline bool
+
929CSCI441::MD5Model::_checkAnimValidity() const
+
930{
+
931 // md5mesh and md5anim must have the same number of joints
+
932 if( _numJoints != _animation.numJoints ) {
+
933 printf("\n[.md5anim]: skeleton and animation do not have same number of joints. cannot apply animation to skeleton\n\n");
+
934 return false;
+
935 }
+
936
+
937 // We just check with frame[0]
+
938 for(GLint i = 0; i < _numJoints; ++i) {
+
939 // Joints must have the same parent index
+
940 if (_baseSkeleton[i].parent != _animation.skeletonFrames[0][i].parent) {
+
941 printf("\n[.md5anim]: skeleton and animation joints do not have same parent index. cannot apply animation to skeleton\n\n");
+
942 return false;
+
943 }
+
944
+
945 // Joints must have the same name
+
946 if (strcmp (_baseSkeleton[i].name, _animation.skeletonFrames[0][i].name) != 0) {
+
947 printf("\n[.md5anim]: skeleton and animation joints do not have same name. cannot apply animation to skeleton\n\n");
+
948 return false;
+
949 }
+
950 }
+
951
+
952 printf("\n[.md5anim]: skeleton and animation match. animation can be applied to skeleton\n\n");
+
953 return true;
+
954}
+
955
+
956// Build _skeleton for a given frame data.
+
957inline void
+
958CSCI441::MD5Model::_buildFrameSkeleton(
+
959 const MD5JointInfo* pJOINT_INFOS,
+
960 const MD5BaseFrameJoint* pBASE_FRAME,
+
961 const GLfloat* pANIM_FRAME_DATA,
+
962 MD5Joint* pSkeletonFrame,
+
963 const GLint NUM_JOINTS
+
964) {
+
965 if(pJOINT_INFOS == nullptr
+
966 || pBASE_FRAME == nullptr
+
967 || pANIM_FRAME_DATA == nullptr
+
968 || pSkeletonFrame == nullptr) return;
969
-
970 for(i = 0; i < NUM_JOINTS; ++i) {
-
971 const MD5BaseFrameJoint *baseJoint = &pBASE_FRAME[i];
-
972 glm::vec3 animatedPosition = baseJoint->position;
-
973 glm::quat animatedOrientation = baseJoint->orientation;
-
974 GLint j = 0;
-
975
-
976 // Tx
-
977 if(pJOINT_INFOS[i].flags & 1 ) {
-
978 animatedPosition.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
979 ++j;
-
980 }
-
981
-
982 // Ty
-
983 if(pJOINT_INFOS[i].flags & 2 ) {
-
984 animatedPosition.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
985 ++j;
-
986 }
-
987
-
988 // Tz
-
989 if(pJOINT_INFOS[i].flags & 4 ) {
-
990 animatedPosition.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
991 ++j;
-
992 }
-
993
-
994 // Qx
-
995 if(pJOINT_INFOS[i].flags & 8 ) {
-
996 animatedOrientation.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
997 ++j;
-
998 }
-
999
-
1000 // Qy
-
1001 if(pJOINT_INFOS[i].flags & 16 ) {
-
1002 animatedOrientation.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
1003 ++j;
-
1004 }
-
1005
-
1006 // Qz
-
1007 if(pJOINT_INFOS[i].flags & 32 ) {
-
1008 animatedOrientation.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
-
1009 }
-
1010
-
1011 // Compute orientation quaternion's w value
-
1012 animatedOrientation.w = glm::extractRealComponent(animatedOrientation);
-
1013
-
1014 // NOTE: we assume that this joint's parent has
-
1015 // already been calculated, i.e. joint's ID should
-
1016 // never be smaller than its parent ID.
-
1017 MD5Joint *thisJoint = &pSkeletonFrame[i];
-
1018
-
1019 GLint parent = pJOINT_INFOS[i].parent;
-
1020 thisJoint->parent = parent;
-
1021 strcpy (thisJoint->name, pJOINT_INFOS[i].name);
-
1022
-
1023 // Has parent?
-
1024 if( thisJoint->parent == MD5Joint::NULL_JOINT ) {
-
1025 thisJoint->position = animatedPosition;
-
1026 thisJoint->orientation = animatedOrientation;
-
1027 } else {
-
1028 MD5Joint *parentJoint = &pSkeletonFrame[parent];
-
1029 glm::vec3 rotatedPosition = glm::rotate(parentJoint->orientation, glm::vec4(animatedPosition, 0.0f));
-
1030
-
1031 // Add positions
-
1032 thisJoint->position = parentJoint->position + rotatedPosition;
-
1033
-
1034 // Concatenate rotations
-
1035 thisJoint->orientation = glm::normalize( glm::cross(parentJoint->orientation, animatedOrientation) );
-
1036 }
-
1037 }
-
1038}
-
1039
-
1040// Load an MD5 animation from file.
-
1041inline bool
- -
1043 const char *filename
-
1044) {
-
1045 char buff[512];
-
1046 MD5JointInfo *jointInfos = nullptr;
-
1047 MD5BaseFrameJoint *baseFrame = nullptr;
-
1048 GLfloat *animFrameData = nullptr;
-
1049 GLint version;
-
1050 GLint numAnimatedComponents;
-
1051 GLint frameIndex;
-
1052 GLint i;
-
1053
-
1054 printf( "[.md5anim]: about to read %s\n", filename );
+
970 GLint i;
+
971
+
972 for(i = 0; i < NUM_JOINTS; ++i) {
+
973 const MD5BaseFrameJoint *baseJoint = &pBASE_FRAME[i];
+
974 glm::vec3 animatedPosition = baseJoint->position;
+
975 glm::quat animatedOrientation = baseJoint->orientation;
+
976 GLint j = 0;
+
977
+
978 // Tx
+
979 if(pJOINT_INFOS[i].flags & 1 ) {
+
980 animatedPosition.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
981 ++j;
+
982 }
+
983
+
984 // Ty
+
985 if(pJOINT_INFOS[i].flags & 2 ) {
+
986 animatedPosition.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
987 ++j;
+
988 }
+
989
+
990 // Tz
+
991 if(pJOINT_INFOS[i].flags & 4 ) {
+
992 animatedPosition.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
993 ++j;
+
994 }
+
995
+
996 // Qx
+
997 if(pJOINT_INFOS[i].flags & 8 ) {
+
998 animatedOrientation.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
999 ++j;
+
1000 }
+
1001
+
1002 // Qy
+
1003 if(pJOINT_INFOS[i].flags & 16 ) {
+
1004 animatedOrientation.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
1005 ++j;
+
1006 }
+
1007
+
1008 // Qz
+
1009 if(pJOINT_INFOS[i].flags & 32 ) {
+
1010 animatedOrientation.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
+
1011 }
+
1012
+
1013 // Compute orientation quaternion's w value
+
1014 animatedOrientation.w = glm::extractRealComponent(animatedOrientation);
+
1015
+
1016 // NOTE: we assume that this joint's parent has
+
1017 // already been calculated, i.e. joint's ID should
+
1018 // never be smaller than its parent ID.
+
1019 MD5Joint *thisJoint = &pSkeletonFrame[i];
+
1020
+
1021 GLint parent = pJOINT_INFOS[i].parent;
+
1022 thisJoint->parent = parent;
+
1023 strcpy (thisJoint->name, pJOINT_INFOS[i].name);
+
1024
+
1025 // Has parent?
+
1026 if( thisJoint->parent == MD5Joint::NULL_JOINT ) {
+
1027 thisJoint->position = animatedPosition;
+
1028 thisJoint->orientation = animatedOrientation;
+
1029 } else {
+
1030 MD5Joint *parentJoint = &pSkeletonFrame[parent];
+
1031 glm::vec3 rotatedPosition = glm::rotate(parentJoint->orientation, glm::vec4(animatedPosition, 0.0f));
+
1032
+
1033 // Add positions
+
1034 thisJoint->position = parentJoint->position + rotatedPosition;
+
1035
+
1036 // Concatenate rotations
+
1037 thisJoint->orientation = glm::normalize( glm::cross(parentJoint->orientation, animatedOrientation) );
+
1038 }
+
1039 }
+
1040}
+
1041
+
1042// Load an MD5 animation from file.
+
1043inline bool
+ +
1045 const char *filename
+
1046) {
+
1047 char buff[512];
+
1048 MD5JointInfo *jointInfos = nullptr;
+
1049 MD5BaseFrameJoint *baseFrame = nullptr;
+
1050 GLfloat *animFrameData = nullptr;
+
1051 GLint version;
+
1052 GLint numAnimatedComponents;
+
1053 GLint frameIndex;
+
1054 GLint i;
1055
-
1056 FILE *fp = fopen( filename, "rb" );
-
1057 if( !fp ) {
-
1058 fprintf (stderr, "[.md5anim]: Error: couldn't open \"%s\"!\n", filename);
-
1059 return false;
-
1060 }
-
1061
-
1062 while( !feof(fp) ) {
-
1063 // Read whole line
-
1064 fgets( buff, sizeof(buff), fp );
-
1065
-
1066 if( sscanf(buff, " MD5Version %d", &version) == 1 ) {
-
1067 if( version != 10 ) {
-
1068 // Bad version
-
1069 fprintf (stderr, "[.md5anim]: Error: bad animation version\n");
-
1070 fclose (fp);
-
1071 return false;
-
1072 }
-
1073 } else if( sscanf(buff, " numFrames %d", &_animation.numFrames) == 1 ) {
-
1074 // Allocate memory for skeleton frames and bounding boxes
-
1075 if( _animation.numFrames > 0 ) {
-
1076 _animation.skeletonFrames = new MD5Joint*[_animation.numFrames];
-
1077 _animation.boundingBoxes = new MD5BoundingBox[_animation.numFrames];
-
1078 }
-
1079 } else if( sscanf(buff, " numJoints %d", &_animation.numJoints) == 1 ) {
-
1080 if( _animation.numJoints > 0 ) {
-
1081 for(i = 0; i < _animation.numFrames; ++i) {
-
1082 // Allocate memory for joints of each frame
-
1083 _animation.skeletonFrames[i] = new MD5Joint[_animation.numJoints];
-
1084 }
-
1085
-
1086 // Allocate temporary memory for building skeleton frames
-
1087 jointInfos = new MD5JointInfo[_animation.numJoints];
-
1088
-
1089 baseFrame = new MD5BaseFrameJoint[_animation.numJoints];
-
1090 }
-
1091 } else if( sscanf(buff, " frameRate %d", &_animation.frameRate) == 1 ) {
-
1092
-
1093 } else if( sscanf(buff, " numAnimatedComponents %d", &numAnimatedComponents) == 1 ) {
-
1094 if( numAnimatedComponents > 0 ) {
-
1095 // Allocate memory for animation frame data
-
1096 animFrameData = new GLfloat[numAnimatedComponents];
-
1097 }
-
1098 } else if( strncmp(buff, "hierarchy {", 11) == 0 ) {
-
1099 for(i = 0; i < _animation.numJoints; ++i) {
-
1100 // Read whole line
-
1101 fgets( buff, sizeof(buff), fp );
-
1102
-
1103 // Read joint info
-
1104 sscanf(buff, " %s %d %d %d",
-
1105 jointInfos[i].name, &jointInfos[i].parent,
-
1106 &jointInfos[i].flags, &jointInfos[i].startIndex);
-
1107 }
-
1108 } else if( strncmp(buff, "bounds {", 8) == 0 ) {
-
1109 for(i = 0; i < _animation.numFrames; ++i) {
-
1110 // Read whole line
-
1111 fgets( buff, sizeof(buff), fp );
-
1112
-
1113 // Read bounding box
-
1114 sscanf(buff, " ( %f %f %f ) ( %f %f %f )",
-
1115 &_animation.boundingBoxes[i].min[0], &_animation.boundingBoxes[i].min[1], &_animation.boundingBoxes[i].min[2],
-
1116 &_animation.boundingBoxes[i].max[0], &_animation.boundingBoxes[i].max[1], &_animation.boundingBoxes[i].max[2]);
-
1117 }
-
1118 } else if( strncmp(buff, "baseframe {", 10) == 0 ) {
-
1119 for(i = 0; i < _animation.numJoints; ++i) {
-
1120 // Read whole line
-
1121 fgets( buff, sizeof(buff), fp );
-
1122
-
1123 // Read base frame joint
-
1124 if( sscanf(buff, " ( %f %f %f ) ( %f %f %f )",
-
1125 &baseFrame[i].position[0], &baseFrame[i].position[1], &baseFrame[i].position[2],
-
1126 &baseFrame[i].orientation[0], &baseFrame[i].orientation[1], &baseFrame[i].orientation[2]) == 6 ) {
-
1127 // Compute the w component
-
1128 baseFrame[i].orientation.w = glm::extractRealComponent(baseFrame[i].orientation);
-
1129 }
-
1130 }
-
1131 } else if(sscanf(buff, " frame %d", &frameIndex) == 1 ) {
-
1132 // Read frame data
-
1133 for(i = 0; i < numAnimatedComponents; ++i)
-
1134 fscanf( fp, "%f", &animFrameData[i] );
-
1135
-
1136 // Build frame _skeleton from the collected data
-
1137 _buildFrameSkeleton(jointInfos, baseFrame, animFrameData,
-
1138 _animation.skeletonFrames[frameIndex],
-
1139 _animation.numJoints);
-
1140 }
-
1141 }
-
1142
-
1143 fclose( fp );
+
1056 printf( "[.md5anim]: about to read %s\n", filename );
+
1057
+
1058 FILE *fp = fopen( filename, "rb" );
+
1059 if( !fp ) {
+
1060 fprintf (stderr, "[.md5anim]: Error: couldn't open \"%s\"!\n", filename);
+
1061 return false;
+
1062 }
+
1063
+
1064 while( !feof(fp) ) {
+
1065 // Read whole line
+
1066 fgets( buff, sizeof(buff), fp );
+
1067
+
1068 if( sscanf(buff, " MD5Version %d", &version) == 1 ) {
+
1069 if( version != 10 ) {
+
1070 // Bad version
+
1071 fprintf (stderr, "[.md5anim]: Error: bad animation version\n");
+
1072 fclose (fp);
+
1073 return false;
+
1074 }
+
1075 } else if( sscanf(buff, " numFrames %d", &_animation.numFrames) == 1 ) {
+
1076 // Allocate memory for skeleton frames and bounding boxes
+
1077 if( _animation.numFrames > 0 ) {
+
1078 _animation.skeletonFrames = new MD5Joint*[_animation.numFrames];
+
1079 _animation.boundingBoxes = new MD5BoundingBox[_animation.numFrames];
+
1080 }
+
1081 } else if( sscanf(buff, " numJoints %d", &_animation.numJoints) == 1 ) {
+
1082 if( _animation.numJoints > 0 ) {
+
1083 for(i = 0; i < _animation.numFrames; ++i) {
+
1084 // Allocate memory for joints of each frame
+
1085 _animation.skeletonFrames[i] = new MD5Joint[_animation.numJoints];
+
1086 }
+
1087
+
1088 // Allocate temporary memory for building skeleton frames
+
1089 jointInfos = new MD5JointInfo[_animation.numJoints];
+
1090
+
1091 baseFrame = new MD5BaseFrameJoint[_animation.numJoints];
+
1092 }
+
1093 } else if( sscanf(buff, " frameRate %d", &_animation.frameRate) == 1 ) {
+
1094
+
1095 } else if( sscanf(buff, " numAnimatedComponents %d", &numAnimatedComponents) == 1 ) {
+
1096 if( numAnimatedComponents > 0 ) {
+
1097 // Allocate memory for animation frame data
+
1098 animFrameData = new GLfloat[numAnimatedComponents];
+
1099 }
+
1100 } else if( strncmp(buff, "hierarchy {", 11) == 0 ) {
+
1101 for(i = 0; i < _animation.numJoints; ++i) {
+
1102 // Read whole line
+
1103 fgets( buff, sizeof(buff), fp );
+
1104
+
1105 // Read joint info
+
1106 sscanf(buff, " %s %d %d %d",
+
1107 jointInfos[i].name, &jointInfos[i].parent,
+
1108 &jointInfos[i].flags, &jointInfos[i].startIndex);
+
1109 }
+
1110 } else if( strncmp(buff, "bounds {", 8) == 0 ) {
+
1111 for(i = 0; i < _animation.numFrames; ++i) {
+
1112 // Read whole line
+
1113 fgets( buff, sizeof(buff), fp );
+
1114
+
1115 // Read bounding box
+
1116 sscanf(buff, " ( %f %f %f ) ( %f %f %f )",
+
1117 &_animation.boundingBoxes[i].min[0], &_animation.boundingBoxes[i].min[1], &_animation.boundingBoxes[i].min[2],
+
1118 &_animation.boundingBoxes[i].max[0], &_animation.boundingBoxes[i].max[1], &_animation.boundingBoxes[i].max[2]);
+
1119 }
+
1120 } else if( strncmp(buff, "baseframe {", 10) == 0 ) {
+
1121 for(i = 0; i < _animation.numJoints; ++i) {
+
1122 // Read whole line
+
1123 fgets( buff, sizeof(buff), fp );
+
1124
+
1125 // Read base frame joint
+
1126 if( sscanf(buff, " ( %f %f %f ) ( %f %f %f )",
+
1127 &baseFrame[i].position[0], &baseFrame[i].position[1], &baseFrame[i].position[2],
+
1128 &baseFrame[i].orientation[0], &baseFrame[i].orientation[1], &baseFrame[i].orientation[2]) == 6 ) {
+
1129 // Compute the w component
+
1130 baseFrame[i].orientation.w = glm::extractRealComponent(baseFrame[i].orientation);
+
1131 }
+
1132 }
+
1133 } else if(sscanf(buff, " frame %d", &frameIndex) == 1 ) {
+
1134 // Read frame data
+
1135 for(i = 0; i < numAnimatedComponents; ++i)
+
1136 fscanf( fp, "%f", &animFrameData[i] );
+
1137
+
1138 // Build frame _skeleton from the collected data
+
1139 _buildFrameSkeleton(jointInfos, baseFrame, animFrameData,
+
1140 _animation.skeletonFrames[frameIndex],
+
1141 _animation.numJoints);
+
1142 }
+
1143 }
1144
-
1145 printf( "[.md5anim]: finished reading %s\n", filename );
-
1146 printf( "[.md5anim]: read in %d frames of %d joints with %d animated components\n", _animation.numFrames, _animation.numJoints, numAnimatedComponents );
-
1147 printf( "[.md5anim]: animation's frame rate is %d\n", _animation.frameRate );
-
1148
-
1149 // Free temporary data allocated
-
1150 if( animFrameData )
-
1151 free( animFrameData );
-
1152
-
1153 if( baseFrame )
-
1154 free( baseFrame );
-
1155
-
1156 if( jointInfos )
-
1157 free( jointInfos );
-
1158
-
1159 // successful loading...set up animation parameters
-
1160 _animationInfo.currFrame = 0;
-
1161 _animationInfo.nextFrame = 1;
-
1162
-
1163 _animationInfo.lastTime = 0.0f;
-
1164 _animationInfo.maxTime = 1.0f / (GLfloat)_animation.frameRate;
-
1165
-
1166 // Allocate memory for animated _skeleton
-
1167 _skeleton = new MD5Joint[_animation.numJoints];
-
1168
-
1169 if( _checkAnimValidity() ) {
-
1170 _isAnimated = true;
-
1171 // compute initial pose
-
1172 animate(0.0);
-
1173 }
-
1174
-
1175 return true;
-
1176}
-
1177
-
1178// Free resources allocated for the animation.
-
1179inline void
-
1180CSCI441::MD5Model::_freeAnim()
-
1181{
-
1182 GLint i;
-
1183
-
1184 for(i = 0; i < _animation.numFrames; ++i) {
-
1185 delete _animation.skeletonFrames[i];
-
1186 _animation.skeletonFrames[i] = nullptr;
-
1187 }
-
1188
-
1189 delete[] _animation.skeletonFrames;
-
1190 _animation.skeletonFrames = nullptr;
-
1191
-
1192 delete _animation.boundingBoxes;
-
1193 _animation.boundingBoxes = nullptr;
-
1194
-
1195 delete _skeleton;
-
1196 _skeleton = nullptr;
-
1197}
-
1198
-
1199// Smoothly interpolate two skeletons
-
1200inline void
-
1201CSCI441::MD5Model::_interpolateSkeletons(GLfloat interp)
-
1202{
-
1203 const MD5Joint *skeletonA = _animation.skeletonFrames[_animationInfo.currFrame];
-
1204 const MD5Joint *skeletonB = _animation.skeletonFrames[_animationInfo.nextFrame];
-
1205
-
1206 GLint i;
+
1145 fclose( fp );
+
1146
+
1147 printf( "[.md5anim]: finished reading %s\n", filename );
+
1148 printf( "[.md5anim]: read in %d frames of %d joints with %d animated components\n", _animation.numFrames, _animation.numJoints, numAnimatedComponents );
+
1149 printf( "[.md5anim]: animation's frame rate is %d\n", _animation.frameRate );
+
1150
+
1151 // Free temporary data allocated
+
1152 if( animFrameData )
+
1153 free( animFrameData );
+
1154
+
1155 if( baseFrame )
+
1156 free( baseFrame );
+
1157
+
1158 if( jointInfos )
+
1159 free( jointInfos );
+
1160
+
1161 // successful loading...set up animation parameters
+
1162 _animationInfo.currFrame = 0;
+
1163 _animationInfo.nextFrame = 1;
+
1164
+
1165 _animationInfo.lastTime = 0.0f;
+
1166 _animationInfo.maxTime = 1.0f / (GLfloat)_animation.frameRate;
+
1167
+
1168 // Allocate memory for animated _skeleton
+
1169 _skeleton = new MD5Joint[_animation.numJoints];
+
1170
+
1171 if( _checkAnimValidity() ) {
+
1172 _isAnimated = true;
+
1173 // compute initial pose
+
1174 animate(0.0);
+
1175 }
+
1176
+
1177 return true;
+
1178}
+
1179
+
1180// Free resources allocated for the animation.
+
1181inline void
+
1182CSCI441::MD5Model::_freeAnim()
+
1183{
+
1184 GLint i;
+
1185
+
1186 for(i = 0; i < _animation.numFrames; ++i) {
+
1187 delete _animation.skeletonFrames[i];
+
1188 _animation.skeletonFrames[i] = nullptr;
+
1189 }
+
1190
+
1191 delete[] _animation.skeletonFrames;
+
1192 _animation.skeletonFrames = nullptr;
+
1193
+
1194 delete _animation.boundingBoxes;
+
1195 _animation.boundingBoxes = nullptr;
+
1196
+
1197 delete _skeleton;
+
1198 _skeleton = nullptr;
+
1199}
+
1200
+
1201// Smoothly interpolate two skeletons
+
1202inline void
+
1203CSCI441::MD5Model::_interpolateSkeletons(GLfloat interp)
+
1204{
+
1205 const MD5Joint *skeletonA = _animation.skeletonFrames[_animationInfo.currFrame];
+
1206 const MD5Joint *skeletonB = _animation.skeletonFrames[_animationInfo.nextFrame];
1207
-
1208 for(i = 0; i < _animation.numJoints; ++i) {
-
1209 // Copy parent index
-
1210 _skeleton[i].parent = skeletonA[i].parent;
-
1211
-
1212 // Linear interpolation for position
-
1213 _skeleton[i].position[0] = skeletonA[i].position[0] + interp * (skeletonB[i].position[0] - skeletonA[i].position[0]);
-
1214 _skeleton[i].position[1] = skeletonA[i].position[1] + interp * (skeletonB[i].position[1] - skeletonA[i].position[1]);
-
1215 _skeleton[i].position[2] = skeletonA[i].position[2] + interp * (skeletonB[i].position[2] - skeletonA[i].position[2]);
-
1216
-
1217 // Spherical linear interpolation for orientation
-
1218 _skeleton[i].orientation = glm::slerp(skeletonA[i].orientation, skeletonB[i].orientation, interp);
-
1219 }
-
1220}
-
1221
-
1222// Perform animation related computations. Calculate the current and
-
1223// next frames, given a delta time.
-
1224inline void
- -
1226{
-
1227 GLint maxFrames = _animation.numFrames - 1;
-
1228
-
1229 _animationInfo.lastTime += dt;
+
1208 GLint i;
+
1209
+
1210 for(i = 0; i < _animation.numJoints; ++i) {
+
1211 // Copy parent index
+
1212 _skeleton[i].parent = skeletonA[i].parent;
+
1213
+
1214 // Linear interpolation for position
+
1215 _skeleton[i].position[0] = skeletonA[i].position[0] + interp * (skeletonB[i].position[0] - skeletonA[i].position[0]);
+
1216 _skeleton[i].position[1] = skeletonA[i].position[1] + interp * (skeletonB[i].position[1] - skeletonA[i].position[1]);
+
1217 _skeleton[i].position[2] = skeletonA[i].position[2] + interp * (skeletonB[i].position[2] - skeletonA[i].position[2]);
+
1218
+
1219 // Spherical linear interpolation for orientation
+
1220 _skeleton[i].orientation = glm::slerp(skeletonA[i].orientation, skeletonB[i].orientation, interp);
+
1221 }
+
1222}
+
1223
+
1224// Perform animation related computations. Calculate the current and
+
1225// next frames, given a delta time.
+
1226inline void
+ +
1228{
+
1229 GLint maxFrames = _animation.numFrames - 1;
1230
-
1231 // move to next frame
-
1232 if( _animationInfo.lastTime >= _animationInfo.maxTime ) {
-
1233 _animationInfo.currFrame++;
-
1234 _animationInfo.nextFrame++;
-
1235 _animationInfo.lastTime = 0.0;
-
1236
-
1237 if( _animationInfo.currFrame > maxFrames )
-
1238 _animationInfo.currFrame = 0;
-
1239
-
1240 if( _animationInfo.nextFrame > maxFrames )
-
1241 _animationInfo.nextFrame = 0;
-
1242 }
-
1243
-
1244 // Interpolate skeletons between two frames
-
1245 _interpolateSkeletons( _animationInfo.lastTime * _animation.frameRate );
-
1246}
-
1247
-
1248#endif//CSCI441_MD5_MODEL_HPP
+
1231 _animationInfo.lastTime += dt;
+
1232
+
1233 // move to next frame
+
1234 if( _animationInfo.lastTime >= _animationInfo.maxTime ) {
+
1235 _animationInfo.currFrame++;
+
1236 _animationInfo.nextFrame++;
+
1237 _animationInfo.lastTime = 0.0;
+
1238
+
1239 if( _animationInfo.currFrame > maxFrames )
+
1240 _animationInfo.currFrame = 0;
+
1241
+
1242 if( _animationInfo.nextFrame > maxFrames )
+
1243 _animationInfo.nextFrame = 0;
+
1244 }
+
1245
+
1246 // Interpolate skeletons between two frames
+
1247 _interpolateSkeletons( _animationInfo.lastTime * _animation.frameRate );
+
1248}
+
1249
+
1250#endif//CSCI441_MD5_MODEL_HPP
Helper functions to work with OpenGL Textures.
-
stores a Doom3 MD5 Mesh + Animation
Definition: MD5Model.hpp:73
-
void draw() const
draws all the meshes that make up the model
Definition: MD5Model.hpp:752
-
bool readMD5Model(const char *FILENAME)
parses md5mesh file and allocates corresponding mesh data
Definition: MD5Model.hpp:511
-
bool isAnimated() const
returns if the MD5 Model has an accompanying animation
Definition: MD5Model.hpp:360
-
bool loadMD5Model(const char *MD5_MESH_FILE, const char *MD5_ANIM_FILE="")
loads a corresponding md5mesh and md5anim file to the object
Definition: MD5Model.hpp:487
-
MD5Model()
initializes an empty MD5 Model
Definition: MD5Model.hpp:455
+
stores a Doom3 MD5 Mesh + Animation
Definition: MD5Model.hpp:75
+
void draw() const
draws all the meshes that make up the model
Definition: MD5Model.hpp:754
+
bool readMD5Model(const char *FILENAME)
parses md5mesh file and allocates corresponding mesh data
Definition: MD5Model.hpp:513
+
bool isAnimated() const
returns if the MD5 Model has an accompanying animation
Definition: MD5Model.hpp:362
+
bool loadMD5Model(const char *MD5_MESH_FILE, const char *MD5_ANIM_FILE="")
loads a corresponding md5mesh and md5anim file to the object
Definition: MD5Model.hpp:489
+
MD5Model()
initializes an empty MD5 Model
Definition: MD5Model.hpp:457
MD5Model & operator=(const MD5Model &)=delete
do not allow MD5 models to be copied
-
bool readMD5Anim(const char *filename)
reads in an animation sequence from an external file
Definition: MD5Model.hpp:1042
-
void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc)
binds model VBOs to attribute pointer locations
Definition: MD5Model.hpp:824
-
void animate(GLfloat dt)
advances the model forward in its animation sequence the corresponding amount of time based on frame ...
Definition: MD5Model.hpp:1225
+
bool readMD5Anim(const char *filename)
reads in an animation sequence from an external file
Definition: MD5Model.hpp:1044
+
void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc)
binds model VBOs to attribute pointer locations
Definition: MD5Model.hpp:826
+
void animate(GLfloat dt)
advances the model forward in its animation sequence the corresponding amount of time based on frame ...
Definition: MD5Model.hpp:1227
MD5Model(const MD5Model &)=delete
do not allow MD5 models to be copied
-
~MD5Model()
deallocates any used memory on the CPU and GPU
Definition: MD5Model.hpp:477
-
void drawSkeleton() const
draws the skeleton joints (as points) and bones (as lines)
Definition: MD5Model.hpp:888
+
~MD5Model()
deallocates any used memory on the CPU and GPU
Definition: MD5Model.hpp:479
+
void drawSkeleton() const
draws the skeleton joints (as points) and bones (as lines)
Definition: MD5Model.hpp:890
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17
-
stores an entire animation sequence for a given MD5 Model
Definition: MD5Model.hpp:278
-
stores state of current animation frame
Definition: MD5Model.hpp:307
-
base frame joint
Definition: MD5Model.hpp:249
-
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:257
-
bounding box containing the model during animation
Definition: MD5Model.hpp:264
-
a joint of the MD5 Skeleton
Definition: MD5Model.hpp:79
-
glm::vec3 position
position of the joint in object space
Definition: MD5Model.hpp:95
-
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:99
-
char name[256]
joint identifier
Definition: MD5Model.hpp:87
-
GLint parent
index of the parent joint on skeletal tree
Definition: MD5Model.hpp:91
-
information pertaining to each animation joint
Definition: MD5Model.hpp:227
-
mesh that comprises the model's skin
Definition: MD5Model.hpp:165
-
GLint numTriangles
number of triangles in the mesh triangle array
Definition: MD5Model.hpp:211
-
TextureMap
named entities for different texture maps applied to the model
Definition: MD5Model.hpp:185
-
@ DIFFUSE
diffuse map
Definition: MD5Model.hpp:189
-
@ SPECULAR
specular map
Definition: MD5Model.hpp:193
-
@ NORMAL
normal map
Definition: MD5Model.hpp:197
-
MD5Texture textures[4]
texture map array
Definition: MD5Model.hpp:181
-
GLint numVertices
number of vertices in the mesh vertex array
Definition: MD5Model.hpp:207
-
MD5Triangle * triangles
array triangles comprising the mesh
Definition: MD5Model.hpp:173
-
MD5Vertex * vertices
array of vertices comprising the mesh
Definition: MD5Model.hpp:169
-
GLint numWeights
number of weights in the mesh weight array
Definition: MD5Model.hpp:215
-
MD5Weight * weights
array of weights to determine vertex position based on joint positions
Definition: MD5Model.hpp:177
-
char shader[512]
base filename for all textures applied to mesh
Definition: MD5Model.hpp:220
-
texture handle for the model
Definition: MD5Model.hpp:151
-
GLuint texHandle
handle of texture stored on the GPU
Definition: MD5Model.hpp:155
-
char filename[512]
filename texture was loaded from
Definition: MD5Model.hpp:159
-
a triangle on the mesh
Definition: MD5Model.hpp:123
-
GLint index[3]
vertex indices that make up triangle
Definition: MD5Model.hpp:127
-
a vertex on the mesh
Definition: MD5Model.hpp:105
-
glm::vec2 texCoord
texture coordinate for vertex
Definition: MD5Model.hpp:109
-
GLint start
index of starting weight
Definition: MD5Model.hpp:113
-
GLint count
number of weights that determine vertex's position
Definition: MD5Model.hpp:117
-
the weight for a mesh vertex
Definition: MD5Model.hpp:133
-
GLfloat bias
contribution of the weight
Definition: MD5Model.hpp:141
-
GLint joint
index of joint the weight depends on
Definition: MD5Model.hpp:137
-
glm::vec3 position
weight's position in object space
Definition: MD5Model.hpp:145
+
stores an entire animation sequence for a given MD5 Model
Definition: MD5Model.hpp:280
+
stores state of current animation frame
Definition: MD5Model.hpp:309
+
base frame joint
Definition: MD5Model.hpp:251
+
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:259
+
bounding box containing the model during animation
Definition: MD5Model.hpp:266
+
a joint of the MD5 Skeleton
Definition: MD5Model.hpp:81
+
glm::vec3 position
position of the joint in object space
Definition: MD5Model.hpp:97
+
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:101
+
char name[256]
joint identifier
Definition: MD5Model.hpp:89
+
GLint parent
index of the parent joint on skeletal tree
Definition: MD5Model.hpp:93
+
information pertaining to each animation joint
Definition: MD5Model.hpp:229
+
mesh that comprises the model's skin
Definition: MD5Model.hpp:167
+
GLint numTriangles
number of triangles in the mesh triangle array
Definition: MD5Model.hpp:213
+
TextureMap
named entities for different texture maps applied to the model
Definition: MD5Model.hpp:187
+
@ DIFFUSE
diffuse map
Definition: MD5Model.hpp:191
+
@ SPECULAR
specular map
Definition: MD5Model.hpp:195
+
@ NORMAL
normal map
Definition: MD5Model.hpp:199
+
MD5Texture textures[4]
texture map array
Definition: MD5Model.hpp:183
+
GLint numVertices
number of vertices in the mesh vertex array
Definition: MD5Model.hpp:209
+
MD5Triangle * triangles
array triangles comprising the mesh
Definition: MD5Model.hpp:175
+
MD5Vertex * vertices
array of vertices comprising the mesh
Definition: MD5Model.hpp:171
+
GLint numWeights
number of weights in the mesh weight array
Definition: MD5Model.hpp:217
+
MD5Weight * weights
array of weights to determine vertex position based on joint positions
Definition: MD5Model.hpp:179
+
char shader[512]
base filename for all textures applied to mesh
Definition: MD5Model.hpp:222
+
texture handle for the model
Definition: MD5Model.hpp:153
+
GLuint texHandle
handle of texture stored on the GPU
Definition: MD5Model.hpp:157
+
char filename[512]
filename texture was loaded from
Definition: MD5Model.hpp:161
+
a triangle on the mesh
Definition: MD5Model.hpp:125
+
GLint index[3]
vertex indices that make up triangle
Definition: MD5Model.hpp:129
+
a vertex on the mesh
Definition: MD5Model.hpp:107
+
glm::vec2 texCoord
texture coordinate for vertex
Definition: MD5Model.hpp:111
+
GLint start
index of starting weight
Definition: MD5Model.hpp:115
+
GLint count
number of weights that determine vertex's position
Definition: MD5Model.hpp:119
+
the weight for a mesh vertex
Definition: MD5Model.hpp:135
+
GLfloat bias
contribution of the weight
Definition: MD5Model.hpp:143
+
GLint joint
index of joint the weight depends on
Definition: MD5Model.hpp:139
+
glm::vec3 position
weight's position in object space
Definition: MD5Model.hpp:147