12#ifndef CSCI441_MD5_MODEL_HPP
13#define CSCI441_MD5_MODEL_HPP
51#ifdef CSCI441_USE_GLEW
57#include <glm/exponential.hpp>
58#include <glm/ext/quaternion_common.hpp>
59#include <glm/ext/quaternion_float.hpp>
61#define GLM_ENABLE_EXPERIMENTAL
62#include <glm/gtx/quaternion.hpp>
87 static constexpr GLint NULL_JOINT = -1;
91 static constexpr GLshort MAX_NAME_LENGTH = 256;
95 char name[MAX_NAME_LENGTH] =
"";
99 GLint parent = NULL_JOINT;
103 glm::vec3 position = {0.0f, 0.0f, 0.0f};
107 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
126 if (
this != &OTHER) {
154 void _copyFromSrc(
const MD5Joint& src) {
155 strncpy(this->name, src.
name, MAX_NAME_LENGTH);
156 this->parent = src.
parent;
165 void _moveFromSrc(MD5Joint& src) {
169 strncpy(src.name,
"", MAX_NAME_LENGTH);
170 src.parent = NULL_JOINT;
171 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
172 src.orientation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
183 glm::vec2 texCoord = {0.0f, 0.0f};
210 if (
this != &OTHER) {
238 void _copyFromSrc(
const MD5Vertex &src) {
240 this->start = src.
start;
241 this->count = src.
count;
247 void _moveFromSrc(MD5Vertex& src) {
250 src.texCoord = glm::vec2(0.0f, 0.0f);
263 static constexpr GLshort NUM_VERTICES = 3;
267 GLint index[NUM_VERTICES] = {0};
286 if (
this != &OTHER) {
315 for (GLshort i = 0; i < NUM_VERTICES; i++) {
316 this->index[i] = src.
index[i];
323 void _moveFromSrc(MD5Triangle &src) {
326 for (GLint & i : src.index) {
339 GLint joint = MD5Joint::NULL_JOINT;
347 glm::vec3 position = {0.0f, 0.0f, 0.0f};
366 if (
this != &OTHER) {
394 void _copyFromSrc(
const MD5Weight &src) {
395 this->joint = src.
joint;
396 this->bias = src.
bias;
403 void _moveFromSrc(MD5Weight &src) {
406 src.joint = MD5Joint::NULL_JOINT;
408 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
419 static constexpr GLshort MAX_NAME_LENGTH = 512;
423 GLuint texHandle = 0;
427 char filename[MAX_NAME_LENGTH] =
"";
446 if (
this != &OTHER) {
476 strncpy(this->filename, src.
filename, MAX_NAME_LENGTH);
482 void _moveFromSrc(MD5Texture& src) {
486 strncpy(src.filename,
"", MAX_NAME_LENGTH);
497 static constexpr GLshort MAX_NAME_LENGTH = 512;
501 static constexpr GLshort NUM_TEXTURES = 4;
542 GLint numVertices = 0;
546 GLint numTriangles = 0;
550 GLint numWeights = 0;
555 char shader[MAX_NAME_LENGTH] =
"";
609 void _moveFromSrc(
MD5Mesh& src) {
619 for (GLshort i = 0; i < NUM_TEXTURES; i++) {
620 this->textures[i] = std::move( src.
textures[i] );
632 strncpy(this->shader, src.
shader, MAX_NAME_LENGTH);
633 strncpy(src.
shader,
"", MAX_NAME_LENGTH);
645 static constexpr GLshort MAX_NAME_LENGTH = 256;
649 char name[MAX_NAME_LENGTH] =
"";
653 GLint parent = MD5Joint::NULL_JOINT;
661 GLint startIndex = 0;
680 if (
this != &OTHER) {
709 strncpy(this->name, src.
name, MAX_NAME_LENGTH);
710 this->parent = src.
parent;
711 this->flags = src.
flags;
718 void _moveFromSrc(MD5JointInfo &src) {
721 strncpy(src.name,
"", MAX_NAME_LENGTH);
722 src.parent = MD5Joint::NULL_JOINT;
735 glm::vec3 position = {0.0f, 0.0f, 0.0f};
739 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
758 if (
this != &OTHER) {
794 void _moveFromSrc(MD5BaseFrameJoint &src) {
797 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
798 src.orientation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
810 glm::vec3 min = {0.0f, 0.0f, 0.0f};
814 glm::vec3 max = {0.0f, 0.0f, 0.0f};
833 if (
this != &OTHER) {
869 void _moveFromSrc(MD5BoundingBox& src) {
872 src.min = glm::vec3(0.0f, 0.0f, 0.0f);
873 src.max = glm::vec3(0.0f, 0.0f, 0.0f);
901 if(_skeletonFrames !=
nullptr) {
902 for (GLint i = 0; i < _numFrames; ++i) {
903 delete _skeletonFrames[i];
906 delete[] _skeletonFrames;
907 _skeletonFrames =
nullptr;
908 delete[] _boundingBoxes;
909 _boundingBoxes =
nullptr;
911 _numFrames = numFrames;
912 if ( _numFrames > 0 ) {
913 _skeletonFrames =
new MD5Joint*[_numFrames];
914 for (GLint i = 0; i < _numFrames; ++i) {
915 _skeletonFrames[i] =
nullptr;
935 if(_skeletonFrames !=
nullptr) {
936 for (GLint i = 0; i < _numFrames; ++i) {
937 delete _skeletonFrames[i];
938 _skeletonFrames[i] =
nullptr;
942 _numJoints = numJoints;
943 if (_numJoints > 0) {
944 if(_skeletonFrames !=
nullptr) {
945 for(GLint i = 0; i < _numFrames; ++i) {
947 _skeletonFrames[i] =
new MD5Joint[_numJoints];
961 if ( frameIndex < 0 || frameIndex >= _numFrames ) {
962 throw std::out_of_range(
"frameIndex out of range");
964 if (_skeletonFrames ==
nullptr) {
965 throw std::out_of_range(
"skeleton frames are null, setNumberOfFrames() may not have been called");
967 return _skeletonFrames[frameIndex];
979 if ( frameIndex < 0 || frameIndex >= _numFrames ) {
980 throw std::out_of_range(
"frameIndex out of range");
982 if ( jointIndex < 0 || jointIndex >= _numJoints ) {
983 throw std::out_of_range(
"jointIndex out of range");
985 if (_skeletonFrames ==
nullptr) {
986 throw std::out_of_range(
"skeleton frames are null, setNumberOfFrames() may not have been called");
988 if (_skeletonFrames[frameIndex] ==
nullptr) {
989 throw std::out_of_range(
"skeleton joints are null, setNumberOfJoints() may not have been called");
991 return _skeletonFrames[frameIndex][jointIndex];
1002 if(frameIndex < 0 || frameIndex >= _numFrames) {
1003 throw std::out_of_range(
"frameIndex out of range");
1005 if (_boundingBoxes ==
nullptr) {
1006 throw std::out_of_range(
"bounding boxes are null, setNumberOfFrames() may not have been called");
1008 return _boundingBoxes[frameIndex];
1019 if(_skeletonFrames !=
nullptr) {
1020 for (GLint i = 0; i < _numFrames; i++) {
1021 delete[] _skeletonFrames[i];
1022 _skeletonFrames[i] =
nullptr;
1025 delete[] _skeletonFrames;
1026 _skeletonFrames =
nullptr;
1028 delete[] _boundingBoxes;
1029 _boundingBoxes =
nullptr;
1066 GLint _numFrames = 0;
1071 GLint _numJoints = 0;
1076 MD5Joint** _skeletonFrames =
nullptr;
1088 this->_numFrames = src._numFrames;
1091 this->_numJoints = src._numJoints;
1097 this->_skeletonFrames = src._skeletonFrames;
1098 src._skeletonFrames =
nullptr;
1100 this->_boundingBoxes = src._boundingBoxes;
1101 src._boundingBoxes =
nullptr;
1112 GLint currFrame = 0;
1116 GLint nextFrame = 0;
1120 GLfloat lastTime = 0.0f;
1125 GLfloat maxTime = 0.0f;
1136 _copyFromSrc(OTHER);
1144 if (
this != &OTHER) {
1145 _copyFromSrc(OTHER);
1182 void _moveFromSrc(MD5AnimationState &src) {
1187 src.lastTime = 0.0f;
1234 [[maybe_unused]]
bool loadMD5Model(
const char* MD5_MESH_FILE,
const char* MD5_ANIM_FILE =
"");
1248 [[nodiscard]]
bool readMD5Model(
const char* FILENAME);
1257 [[maybe_unused]]
void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc);
1266 [[maybe_unused]]
void setActiveTextures(GLint diffuseMapActiveTexture, GLint specularMapActiveTexture, GLint normalMapActiveTexture, GLint heightMapActiveTexture);
1271 [[maybe_unused]]
void draw()
const;
1275 [[maybe_unused]]
void drawSkeleton()
const;
1283 [[nodiscard]]
bool readMD5Anim(
const char* filename);
1288 void animate(GLfloat dt);
1295 MD5Joint* _baseSkeleton =
nullptr;
1300 MD5Mesh* _meshes =
nullptr;
1305 GLint _numJoints = 0;
1310 GLint _numMeshes = 0;
1317 GLint _maxVertices = 0;
1322 GLint _maxTriangles = 0;
1327 glm::vec3* _vertexArray =
nullptr;
1332 glm::vec2* _texelArray =
nullptr;
1337 GLuint* _vertexIndicesArray =
nullptr;
1347 GLuint _vbo[2] = {0, 0};
1353 GLuint _skeletonVAO = 0;
1357 GLuint _skeletonVBO = 0;
1361 MD5Joint* _skeleton =
nullptr;
1367 MD5Animation* _animation =
nullptr;
1371 bool _isAnimated =
false;
1375 MD5AnimationState _animationInfo;
1380 GLint _diffuseActiveTexture = GL_TEXTURE0;
1384 GLint _specularActiveTexture = GL_TEXTURE1;
1388 GLint _normalActiveTexture = GL_TEXTURE2;
1392 GLint _heightActiveTexture = GL_TEXTURE3;
1400 void _prepareMesh(
const MD5Mesh* pMESH)
const;
1405 void _drawMesh(
const MD5Mesh* pMESH)
const;
1411 [[nodiscard]]
bool _checkAnimValidity()
const;
1420 static void _buildFrameSkeleton(
const MD5JointInfo* pJOINT_INFOS,
1421 const MD5BaseFrameJoint* pBASE_FRAME,
1422 const GLfloat* pANIM_FRAME_DATA,
1423 const MD5Joint* pSkeletonFrame,
1429 void _interpolateSkeletons(GLfloat interp);
1437 void _freeVertexArrays();
1447 void _moveFromSrc(MD5Model &src);
1457 _freeVertexArrays();
1465 const char* MD5_MESH_FILE,
1466 const char* MD5_ANIM_FILE
1469 if( readMD5Model(MD5_MESH_FILE) ) {
1471 if(strcmp(MD5_ANIM_FILE,
"") != 0 ) {
1473 if( !readMD5Anim(MD5_ANIM_FILE) ) {
1477 if( !isAnimated() ) {
1478 printf (
"[.MD5_ANIM_FILE]: no animation loaded.\n");
1489 const char* FILENAME
1493 GLint currentMesh = 0;
1495 GLint totalVertices = 0;
1496 GLint totalWeights = 0;
1497 GLint totalTriangles = 0;
1499 GLfloat minX = 999999, minY = 999999, minZ = 999999;
1500 GLfloat maxX = -999999, maxY = -999999, maxZ = -999999;
1502 printf(
"[.md5mesh]: about to read %s\n", FILENAME );
1504 FILE *fp = fopen(FILENAME,
"rb" );
1506 fprintf (stderr,
"[.md5mesh]: Error: couldn't open \"%s\"!\n", FILENAME);
1510 while( !feof(fp) ) {
1512 fgets( buff,
sizeof(buff), fp );
1514 if( sscanf(buff,
" MD5Version %d", &version) == 1 ) {
1515 if( version != 10 ) {
1517 fprintf (stderr,
"[.md5mesh]: Error: bad model version\n");
1521 }
else if( sscanf(buff,
" numJoints %d", &_numJoints) == 1 ) {
1522 if( _numJoints > 0 ) {
1524 _baseSkeleton =
new MD5Joint[_numJoints];
1526 }
else if( sscanf(buff,
" numMeshes %d", &_numMeshes) == 1 ) {
1527 if( _numMeshes > 0 ) {
1529 _meshes =
new MD5Mesh[_numMeshes];
1531 }
else if( strncmp(buff,
"joints {", 8) == 0 ) {
1533 for(GLint i = 0; i < _numJoints; ++i) {
1534 MD5Joint *joint = &_baseSkeleton[i];
1537 fgets( buff,
sizeof(buff), fp );
1539 if( sscanf(buff,
"%s %d ( %f %f %f ) ( %f %f %f )",
1548 }
else if( strncmp(buff,
"mesh {", 6) == 0 ) {
1549 MD5Mesh *mesh = &_meshes[currentMesh];
1550 GLint vert_index = 0;
1551 GLint tri_index = 0;
1552 GLint weight_index = 0;
1553 GLfloat floatData[4];
1556 while( buff[0] !=
'}' && !feof(fp) ) {
1558 fgets( buff,
sizeof(buff), fp );
1560 if( strstr( buff,
"shader ") ) {
1561 GLint quote = 0, j = 0;
1564 for(
unsigned long uli = 0; uli <
sizeof(buff) && (quote < 2); ++uli) {
1565 if( buff[uli] ==
'\"' )
1568 if( (quote == 1) && (buff[uli] !=
'\"') ) {
1569 mesh->
shader[j] = buff[uli];
1578 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, GL_FALSE, GL_FALSE);
1582 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, GL_FALSE, GL_FALSE );
1586 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, GL_FALSE, GL_FALSE );
1588 fprintf(stderr,
"[.md5mesh | ERROR]: Could not load diffuse map for shader %s\n", mesh->
shader);
1596 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, GL_FALSE, GL_FALSE );
1600 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, GL_FALSE, GL_FALSE );
1602 fprintf(stderr,
"[.md5mesh | ERROR]: Could not load specular map for shader %s\n", mesh->
shader);
1608 strcat(mesh->
textures[MD5Mesh::TextureMap::NORMAL].
filename,
"_local.tga");
1609 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, GL_FALSE, GL_FALSE );
1612 strcat(mesh->
textures[MD5Mesh::TextureMap::NORMAL].
filename,
"_local.png");
1613 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, GL_FALSE, GL_FALSE );
1615 fprintf(stderr,
"[.md5mesh | ERROR]: Could not load normal map for shader %s\n", mesh->
shader);
1622 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, GL_FALSE, GL_FALSE );
1626 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, GL_FALSE, GL_FALSE );
1628 fprintf(stderr,
"[.md5mesh | ERROR]: Could not load height map for shader %s\n", mesh->
shader);
1632 }
else if( sscanf(buff,
" numverts %d", &mesh->
numVertices) == 1 ) {
1642 }
else if( sscanf(buff,
" numtris %d", &mesh->
numTriangles) == 1 ) {
1652 }
else if( sscanf(buff,
" numweights %d", &mesh->
numWeights) == 1 ) {
1659 }
else if( sscanf(buff,
" vert %d ( %f %f ) %d %d",
1661 &floatData[0], &floatData[1],
1662 &intData[0], &intData[1]) == 5
1669 }
else if( sscanf(buff,
" tri %d %d %d %d",
1671 &intData[0], &intData[1], &intData[2]) == 4
1677 }
else if( sscanf(buff,
" weight %d %d %f ( %f %f %f )",
1678 &weight_index, &intData[0], &floatData[3],
1679 &floatData[0], &floatData[1], &floatData[2]) == 6
1688 if( floatData[0] < minX ) { minX = floatData[0]; }
1689 if( floatData[0] > maxX ) { maxX = floatData[0]; }
1690 if( floatData[1] < minY ) { minY = floatData[1]; }
1691 if( floatData[1] > maxY ) { maxY = floatData[1]; }
1692 if( floatData[2] < minZ ) { minZ = floatData[2]; }
1693 if( floatData[2] > maxZ ) { maxZ = floatData[2]; }
1703 _skeleton = _baseSkeleton;
1705 printf(
"[.md5mesh]: finished reading %s\n", FILENAME );
1706 printf(
"[.md5mesh]: read in %d meshes, %d joints, %d vertices, %d weights, and %d triangles\n", _numMeshes, _numJoints, totalVertices, totalWeights, totalTriangles );
1707 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) );
1714CSCI441::MD5Model::_freeModel()
1716 delete[] _baseSkeleton;
1717 if (_baseSkeleton == _skeleton) _skeleton =
nullptr;
1718 _baseSkeleton =
nullptr;
1729 for(GLint i = 0; i < _numMeshes; ++i) {
1731 _prepareMesh(&mesh);
1737CSCI441::MD5Model::_prepareMesh(
1738 const MD5Mesh *pMESH
1743 for(k = 0, i = 0; i < pMESH->numTriangles; ++i) {
1744 for(j = 0; j < 3; ++j, ++k)
1745 _vertexIndicesArray[k] = pMESH->triangles[i].index[j];
1749 for(i = 0; i < pMESH->numVertices; ++i) {
1750 glm::vec3 finalVertex = {0.0f, 0.0f, 0.0f };
1753 for(j = 0; j < pMESH->vertices[i].count; ++j) {
1754 const MD5Weight *weight = &pMESH->weights[pMESH->vertices[i].start + j];
1755 const MD5Joint *joint = &_skeleton[weight->joint];
1758 const glm::vec3 weightedVertex = glm::rotate(joint->orientation, glm::vec4(weight->position, 0.0f));
1761 finalVertex.x += (joint->position.x + weightedVertex.x) * weight->bias;
1762 finalVertex.y += (joint->position.y + weightedVertex.y) * weight->bias;
1763 finalVertex.z += (joint->position.z + weightedVertex.z) * weight->bias;
1766 _vertexArray[i].x = finalVertex.x;
1767 _vertexArray[i].y = finalVertex.y;
1768 _vertexArray[i].z = finalVertex.z;
1770 _texelArray[i].s = pMESH->vertices[i].texCoord.s;
1771 _texelArray[i].t = pMESH->vertices[i].texCoord.t;
1774 glBindVertexArray(_vao );
1776 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
1777 glBufferSubData(GL_ARRAY_BUFFER, 0,
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * pMESH->numVertices, &_vertexArray[0] );
1778 glBufferSubData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _maxVertices,
static_cast<GLsizeiptr
>(
sizeof(glm::vec2)) * pMESH->numVertices, &_texelArray[0] );
1780 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
1781 glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0,
static_cast<GLsizeiptr
>(
sizeof(GLuint)) * pMESH->numTriangles * 3, _vertexIndicesArray );
1785CSCI441::MD5Model::_drawMesh(
1786 const MD5Mesh *pMESH
1788 if (pMESH->textures[MD5Mesh::TextureMap::SPECULAR].texHandle != 0) {
1790 glActiveTexture(_specularActiveTexture);
1791 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::SPECULAR].texHandle );
1793 if (pMESH->textures[MD5Mesh::TextureMap::NORMAL].texHandle != 0) {
1795 glActiveTexture(_normalActiveTexture);
1796 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::NORMAL].texHandle );
1798 if (pMESH->textures[MD5Mesh::TextureMap::HEIGHT].texHandle != 0) {
1800 glActiveTexture(_heightActiveTexture);
1801 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::HEIGHT].texHandle );
1804 if (pMESH->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle != 0) {
1806 glActiveTexture(_diffuseActiveTexture);
1807 glBindTexture(GL_TEXTURE_2D, pMESH->textures[MD5Mesh::TextureMap::DIFFUSE].texHandle );
1809 if (_diffuseActiveTexture != GL_TEXTURE0) {
1811 glActiveTexture(GL_TEXTURE0);
1814 glBindVertexArray(_vao );
1815 glDrawElements(GL_TRIANGLES, pMESH->numTriangles * 3, GL_UNSIGNED_INT, (
void*)
nullptr );
1821 const GLuint vPosAttribLoc,
1822 const GLuint vColorAttribLoc,
1823 const GLuint vTexCoordAttribLoc
1825 _vertexArray =
new glm::vec3[_maxVertices];
1826 _texelArray =
new glm::vec2[_maxVertices];
1827 _vertexIndicesArray =
new GLuint[_maxTriangles * 3];
1829 glGenVertexArrays( 1, &_vao );
1830 glBindVertexArray(_vao );
1832 glGenBuffers(2, _vbo );
1833 glBindBuffer(GL_ARRAY_BUFFER, _vbo[0] );
1834 glBufferData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _maxVertices +
static_cast<GLsizeiptr
>(
sizeof(glm::vec2)) * _maxVertices,
nullptr, GL_DYNAMIC_DRAW );
1836 glEnableVertexAttribArray( vPosAttribLoc );
1837 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0,
static_cast<void *
>(
nullptr) );
1839 glEnableVertexAttribArray( vTexCoordAttribLoc );
1840 glVertexAttribPointer( vTexCoordAttribLoc, 2, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * _maxVertices) );
1842 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo[1] );
1843 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(GLuint)) * _maxTriangles * 3,
nullptr, GL_DYNAMIC_DRAW );
1845 printf(
"[.md5mesh]: Model VAO/VBO/IBO registered at %u/%u/%u\n", _vao, _vbo[0], _vbo[1] );
1847 glGenVertexArrays( 1, &_skeletonVAO );
1848 glBindVertexArray(_skeletonVAO );
1850 glGenBuffers( 1, &_skeletonVBO );
1851 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
1852 glBufferData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints * 3 * 2,
nullptr, GL_DYNAMIC_DRAW );
1854 glEnableVertexAttribArray( vPosAttribLoc );
1855 glVertexAttribPointer( vPosAttribLoc, 3, GL_FLOAT, GL_FALSE, 0,
static_cast<void *
>(
nullptr) );
1857 glEnableVertexAttribArray( vColorAttribLoc );
1858 glVertexAttribPointer( vColorAttribLoc, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<void *
>(
sizeof(glm::vec3) * _numJoints * 3) );
1860 printf(
"[.md5mesh]: Skeleton VAO/VBO registered at %u/%u\n", _skeletonVAO, _skeletonVBO );
1865 const GLint diffuseMapActiveTexture = GL_TEXTURE0,
1866 const GLint specularMapActiveTexture = GL_TEXTURE1,
1867 const GLint normalMapActiveTexture = GL_TEXTURE2,
1868 const GLint heightMapActiveTexture = GL_TEXTURE3
1870 _diffuseActiveTexture = diffuseMapActiveTexture;
1871 _specularActiveTexture = specularMapActiveTexture;
1872 _normalActiveTexture = normalMapActiveTexture;
1873 _heightActiveTexture = heightMapActiveTexture;
1877CSCI441::MD5Model::_freeVertexArrays()
1879 delete[] _vertexArray;
1880 _vertexArray =
nullptr;
1882 delete[] _vertexIndicesArray;
1883 _vertexIndicesArray =
nullptr;
1885 delete[] _texelArray;
1886 _texelArray =
nullptr;
1888 glDeleteVertexArrays( 1, &_vao );
1891 glDeleteBuffers(2, _vbo );
1895 glDeleteVertexArrays( 1, &_skeletonVAO );
1898 glDeleteBuffers( 1, &_skeletonVBO );
1906 glBindVertexArray(_skeletonVAO );
1907 glBindBuffer(GL_ARRAY_BUFFER, _skeletonVBO );
1909 constexpr glm::vec3 jointColor = {1.0f, 1.0f, 0.0f };
1910 constexpr glm::vec3 boneColor = {1.0f, 0.0f, 1.0f };
1913 for(GLint i = 0; i < _numJoints; ++i ) {
1914 glBufferSubData(GL_ARRAY_BUFFER, i *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)),
sizeof(glm::vec3), &(_skeleton[i].position) );
1915 glBufferSubData(GL_ARRAY_BUFFER, i *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) +
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints * 3,
sizeof(glm::vec3), &jointColor[0]);
1920 for(GLint i = 0; i < _numJoints; ++i ) {
1921 if( _skeleton[i].parent != MD5Joint::NULL_JOINT ) {
1924 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints + (i * 2) *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)),
1925 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)),
1926 &(_skeleton[_skeleton[i].parent].position)
1930 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints + (i * 2) *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) +
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints * 3,
1937 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints + (i * 2) *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) +
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)),
1938 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)),
1939 &(_skeleton[i].position)
1943 static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints + (i * 2) *
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) +
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) +
static_cast<GLsizeiptr
>(
sizeof(glm::vec3)) * _numJoints * 3,
1952 glDrawArrays(GL_POINTS, 0, _numJoints );
1955 glLineWidth( 3.0f );
1956 glDrawArrays(GL_LINES, _numJoints, numBones * 2 );
1961CSCI441::MD5Model::_checkAnimValidity()
const
1964 if( _numJoints != _animation->getNumberOfJoints() ) {
1965 fprintf(stdout,
"\n[.md5anim]: skeleton and animation do not have same number of joints. cannot apply animation to skeleton\n\n");
1968 if (_animation->getNumberOfJoints() == 0 ) {
1969 fprintf(stdout,
"\n[.md5anim]: animation has zero joints. cannot apply animation to skeleton\n\n");
1974 for(GLint i = 0; i < _numJoints; ++i) {
1976 if (_baseSkeleton[i].parent != _animation->getSkeletonFrameJoint(0, i).parent) {
1977 fprintf(stdout,
"\n[.md5anim]: skeleton and animation joints do not have same parent index. cannot apply animation to skeleton\n\n");
1982 if (strcmp (_baseSkeleton[i].name, _animation->getSkeletonFrameJoint(0, i).name) != 0) {
1983 fprintf(stdout,
"\n[.md5anim]: skeleton and animation joints do not have same name. cannot apply animation to skeleton\n\n");
1988 fprintf(stdout,
"\n[.md5anim]: skeleton and animation match. animation can be applied to skeleton\n\n");
1993CSCI441::MD5Model::_buildFrameSkeleton(
1994 const MD5JointInfo* pJOINT_INFOS,
1995 const MD5BaseFrameJoint* pBASE_FRAME,
1996 const GLfloat* pANIM_FRAME_DATA,
1997 const MD5Joint* pSkeletonFrame,
1998 const GLint NUM_JOINTS
2000 if(pJOINT_INFOS ==
nullptr
2001 || pBASE_FRAME ==
nullptr
2002 || pANIM_FRAME_DATA ==
nullptr
2003 || pSkeletonFrame ==
nullptr)
return;
2005 for(GLint i = 0; i < NUM_JOINTS; ++i) {
2006 const MD5BaseFrameJoint *baseJoint = &pBASE_FRAME[i];
2007 glm::vec3 animatedPosition = baseJoint->position;
2008 glm::quat animatedOrientation = baseJoint->orientation;
2012 if(pJOINT_INFOS[i].flags & 1 ) {
2013 animatedPosition.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2018 if(pJOINT_INFOS[i].flags & 2 ) {
2019 animatedPosition.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2024 if(pJOINT_INFOS[i].flags & 4 ) {
2025 animatedPosition.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2030 if(pJOINT_INFOS[i].flags & 8 ) {
2031 animatedOrientation.x = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2036 if(pJOINT_INFOS[i].flags & 16 ) {
2037 animatedOrientation.y = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2042 if(pJOINT_INFOS[i].flags & 32 ) {
2043 animatedOrientation.z = pANIM_FRAME_DATA[pJOINT_INFOS[i].startIndex + j];
2047 animatedOrientation.w = glm::extractRealComponent(animatedOrientation);
2052 const auto thisJoint =
const_cast<MD5Joint *
>(&pSkeletonFrame[i]);
2054 const GLint parent = pJOINT_INFOS[i].parent;
2055 thisJoint->parent = parent;
2056 strcpy (thisJoint->name, pJOINT_INFOS[i].name);
2059 if( thisJoint->parent == MD5Joint::NULL_JOINT ) {
2060 thisJoint->position = animatedPosition;
2061 thisJoint->orientation = animatedOrientation;
2063 const MD5Joint *parentJoint = &pSkeletonFrame[parent];
2064 glm::vec3 rotatedPosition = glm::rotate(parentJoint->orientation, glm::vec4(animatedPosition, 0.0f));
2067 thisJoint->position = parentJoint->position + rotatedPosition;
2070 thisJoint->orientation = glm::normalize( glm::cross(parentJoint->orientation, animatedOrientation) );
2077 const char *filename
2082 GLfloat *animFrameData =
nullptr;
2084 GLint numAnimatedComponents;
2085 GLint frameIndex, numFrames, numJoints;
2088 printf(
"[.md5anim]: about to read %s\n", filename );
2090 FILE *fp = fopen( filename,
"rb" );
2092 fprintf (stderr,
"[.md5anim]: Error: couldn't open \"%s\"!\n", filename);
2096 while( !feof(fp) ) {
2098 fgets( buff,
sizeof(buff), fp );
2100 if( sscanf(buff,
" MD5Version %d", &version) == 1 ) {
2101 if( version != 10 ) {
2103 fprintf (stderr,
"[.md5anim]: Error: bad animation version\n");
2107 }
else if( sscanf(buff,
" numFrames %d", &numFrames) == 1 ) {
2109 _animation->setNumberOfFrames(numFrames);
2110 }
else if( sscanf(buff,
" numJoints %d", &numJoints) == 1 ) {
2111 if (jointInfos !=
nullptr) {
2112 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numJoints already specified\n" );
2114 if( numJoints > 0 ) {
2115 _animation->setNumberOfJoints(numJoints);
2121 }
else if( sscanf(buff,
" frameRate %d", &_animation->frameRate) == 1 ) {
2123 }
else if( sscanf(buff,
" numAnimatedComponents %d", &numAnimatedComponents) == 1 ) {
2124 if (animFrameData !=
nullptr) {
2125 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numAnimatedComponents already specified\n" );
2127 if( numAnimatedComponents > 0 ) {
2129 animFrameData =
new GLfloat[numAnimatedComponents];
2131 }
else if( strncmp(buff,
"hierarchy {", 11) == 0 ) {
2132 if (jointInfos ==
nullptr) {
2133 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numJoints not specified prior to hierarchy\n" );
2135 for(i = 0; i < numJoints; ++i) {
2137 fgets( buff,
sizeof(buff), fp );
2140 sscanf(buff,
" %s %d %d %d",
2141 jointInfos[i].name, &jointInfos[i].parent,
2142 &jointInfos[i].flags, &jointInfos[i].startIndex);
2145 }
else if( strncmp(buff,
"bounds {", 8) == 0 ) {
2146 if (_animation->getNumberOfFrames() == 0) {
2147 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numFrames not specified prior to bounds\n" );
2149 for(i = 0; i < _animation->getNumberOfFrames(); ++i) {
2151 fgets( buff,
sizeof(buff), fp );
2154 sscanf(buff,
" ( %f %f %f ) ( %f %f %f )",
2155 &_animation->getBoundingBox(i).min[0], &_animation->getBoundingBox(i).min[1], &_animation->getBoundingBox(i).min[2],
2156 &_animation->getBoundingBox(i).max[0], &_animation->getBoundingBox(i).max[1], &_animation->getBoundingBox(i).max[2]);
2159 }
else if( strncmp(buff,
"baseframe {", 10) == 0 ) {
2160 if (baseFrame ==
nullptr) {
2161 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numJoints not specified prior to baseframe\n" );
2163 for(i = 0; i < numJoints; ++i) {
2165 fgets( buff,
sizeof(buff), fp );
2168 if( sscanf(buff,
" ( %f %f %f ) ( %f %f %f )",
2169 &baseFrame[i].position[0], &baseFrame[i].position[1], &baseFrame[i].position[2],
2170 &baseFrame[i].orientation[0], &baseFrame[i].orientation[1], &baseFrame[i].orientation[2]) == 6 ) {
2172 baseFrame[i].
orientation.w = glm::extractRealComponent(baseFrame[i].orientation);
2176 }
else if(sscanf(buff,
" frame %d", &frameIndex) == 1 ) {
2177 if (animFrameData ==
nullptr) {
2178 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numAnimatedComponents not specified prior to frame\n" );
2179 }
else if (_animation->getNumberOfFrames() == 0) {
2180 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numFrames not specified prior to frame\n" );
2181 }
else if (baseFrame ==
nullptr) {
2182 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. baseframe not specified prior to frame\n" );
2183 }
else if (jointInfos ==
nullptr) {
2184 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numJoints not specified prior to frame\n" );
2187 for(i = 0; i < numAnimatedComponents; ++i)
2188 fscanf( fp,
"%f", &animFrameData[i] );
2191 _buildFrameSkeleton(jointInfos, baseFrame, animFrameData,
2192 _animation->getSkeletonFrame(frameIndex),
2200 printf(
"[.md5anim]: finished reading %s\n", filename );
2201 printf(
"[.md5anim]: read in %d frames of %d joints with %d animated components\n", _animation->getNumberOfFrames(), _animation->getNumberOfJoints(), numAnimatedComponents );
2202 printf(
"[.md5anim]: animation's frame rate is %d\n", _animation->frameRate );
2205 delete[] animFrameData;
2207 delete[] jointInfos;
2210 _animationInfo.currFrame = 0;
2211 _animationInfo.nextFrame = 1;
2213 _animationInfo.lastTime = 0.0f;
2214 _animationInfo.maxTime = 1.0f /
static_cast<GLfloat
>(_animation->frameRate);
2217 if (_animation->getNumberOfJoints() == 0) {
2218 fprintf( stderr,
"[.md5anim]: Error: md5anim file malformed. numJoints never specified\n" );
2220 _skeleton =
new MD5Joint[_animation->getNumberOfJoints()];
2223 if( _checkAnimValidity() ) {
2233CSCI441::MD5Model::_freeAnim()
2236 _skeleton =
nullptr;
2239 _animation =
nullptr;
2242inline void CSCI441::MD5Model::_moveFromSrc(MD5Model &src) {
2243 this->_baseSkeleton = src._baseSkeleton;
2244 src._baseSkeleton =
nullptr;
2246 this->_meshes = src._meshes;
2247 src._meshes =
nullptr;
2249 this->_maxVertices = src._maxVertices;
2250 src._maxVertices = 0;
2252 this->_maxTriangles = src._maxTriangles;
2253 src._maxTriangles = 0;
2255 this->_vertexArray = src._vertexArray;
2256 src._vertexArray =
nullptr;
2258 this->_texelArray = src._texelArray;
2259 src._texelArray =
nullptr;
2261 this->_vertexIndicesArray = src._vertexIndicesArray;
2262 src._vertexIndicesArray =
nullptr;
2264 this->_vao = src._vao;
2267 this->_vbo[0] = src._vbo[0];
2268 this->_vbo[1] = src._vbo[1];
2272 this->_skeletonVAO = src._skeletonVAO;
2273 src._skeletonVAO = 0;
2275 this->_skeletonVBO = src._skeletonVBO;
2276 src._skeletonVBO = 0;
2278 this->_skeleton = src._skeleton;
2279 src._skeleton =
nullptr;
2281 this->_animation = src._animation;
2282 src._animation =
nullptr;
2284 this->_isAnimated = src._isAnimated;
2285 src._isAnimated =
false;
2287 this->_animationInfo = std::move( src._animationInfo );
2291CSCI441::MD5Model::_interpolateSkeletons(
const GLfloat interp)
2293 const MD5Joint *skeletonA = _animation->getSkeletonFrame(_animationInfo.currFrame);
2294 const MD5Joint *skeletonB = _animation->getSkeletonFrame(_animationInfo.nextFrame);
2296 for(GLint i = 0; i < _animation->getNumberOfJoints(); ++i) {
2298 _skeleton[i].parent = skeletonA[i].parent;
2301 _skeleton[i].position = glm::mix(skeletonA[i].position, skeletonB[i].position, interp);
2304 _skeleton[i].orientation = glm::slerp(skeletonA[i].orientation, skeletonB[i].orientation, interp);
2313 const GLint maxFrames = _animation->getNumberOfFrames() - 1;
2314 if (maxFrames <= 0)
return;
2316 _animationInfo.lastTime += dt;
2319 if( _animationInfo.lastTime >= _animationInfo.maxTime ) {
2320 _animationInfo.currFrame++;
2321 _animationInfo.nextFrame++;
2322 _animationInfo.lastTime = 0.0;
2324 if( _animationInfo.currFrame > maxFrames )
2325 _animationInfo.currFrame = 0;
2327 if( _animationInfo.nextFrame > maxFrames )
2328 _animationInfo.nextFrame = 0;
2332 _interpolateSkeletons( _animationInfo.lastTime *
static_cast<GLfloat
>(_animation->frameRate) );
Helper functions to work with OpenGL Textures.
stores an entire animation sequence for a given MD5 Model
Definition: MD5Model.hpp:880
MD5Animation & operator=(MD5Animation &&src) noexcept
reassign object by moving an existing object
Definition: MD5Model.hpp:1055
MD5Animation()=default
construct a default animation object
MD5Animation & operator=(const MD5Animation &OTHER)=delete
do not allow animation objects to be copied
MD5Animation(MD5Animation &&src) noexcept
construct an animation object by moving an existing object
Definition: MD5Model.hpp:1047
MD5Animation(const MD5Animation &OTHER)=delete
do not allow animation objects to be copied
GLint getNumberOfFrames() const
getter to retrieve number of frames within the animation
Definition: MD5Model.hpp:892
void setNumberOfFrames(const GLint numFrames)
sets the number of frames and allocates skeletonFrames and boundingBoxes to the associated size
Definition: MD5Model.hpp:899
const MD5Joint * getSkeletonFrame(const GLint frameIndex) const
get the skeleton for a specific animation frame
Definition: MD5Model.hpp:960
GLint frameRate
number of frames per second to draw for the animation
Definition: MD5Model.hpp:886
~MD5Animation()
deallocate animation arrays
Definition: MD5Model.hpp:1018
MD5Joint & getSkeletonFrameJoint(const GLint frameIndex, const GLint jointIndex) const
get the specific joint from a skeleton for a specific animation frame
Definition: MD5Model.hpp:978
MD5BoundingBox & getBoundingBox(const GLint frameIndex) const
get the specific bounding box for a target frame
Definition: MD5Model.hpp:1001
void setNumberOfJoints(const GLint numJoints)
set the number of joints in the skeleton of each animation frame and allocates each frame of skeleton...
Definition: MD5Model.hpp:933
GLint getNumberOfJoints() const
get the number of joints in each skeleton frame
Definition: MD5Model.hpp:925
stores a Doom3 MD5 Mesh + Animation
Definition: MD5Model.hpp:77
void draw() const
draws all the meshes that make up the model
Definition: MD5Model.hpp:1726
bool readMD5Model(const char *FILENAME)
parses md5mesh file and allocates corresponding mesh data
Definition: MD5Model.hpp:1488
bool isAnimated() const
returns if the MD5 Model has an accompanying animation
Definition: MD5Model.hpp:1240
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:1464
void setActiveTextures(GLint diffuseMapActiveTexture, GLint specularMapActiveTexture, GLint normalMapActiveTexture, GLint heightMapActiveTexture)
specify which texture targets each texture map should be bound to when rendering
Definition: MD5Model.hpp:1864
MD5Model()
initializes an empty MD5 Model
Definition: MD5Model.hpp:1197
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:2076
void allocVertexArrays(GLuint vPosAttribLoc, GLuint vColorAttribLoc, GLuint vTexCoordAttribLoc)
binds model VBOs to attribute pointer locations
Definition: MD5Model.hpp:1820
void animate(GLfloat dt)
advances the model forward in its animation sequence the corresponding amount of time based on frame ...
Definition: MD5Model.hpp:2311
MD5Model & operator=(MD5Model &&src) noexcept
do not allow MD5 models to be moved
Definition: MD5Model.hpp:1221
MD5Model(const MD5Model &)=delete
do not allow MD5 models to be copied
MD5Model(MD5Model &&src) noexcept
do not allow MD5 models to be moved
Definition: MD5Model.hpp:1215
~MD5Model()
deallocates any used memory on the CPU and GPU
Definition: MD5Model.hpp:1454
void drawSkeleton() const
draws the skeleton joints (as points) and bones (as lines)
Definition: MD5Model.hpp:1904
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17
stores state of current animation frame
Definition: MD5Model.hpp:1108
GLint currFrame
index of current frame model is in
Definition: MD5Model.hpp:1112
MD5AnimationState(MD5AnimationState &&src) noexcept
construct an object by moving an existing object
Definition: MD5Model.hpp:1153
MD5AnimationState(const MD5AnimationState &OTHER)
construct an object by copying an existing object
Definition: MD5Model.hpp:1135
MD5AnimationState()=default
construct a default object
GLint nextFrame
index of next frame model will move to
Definition: MD5Model.hpp:1116
MD5AnimationState & operator=(MD5AnimationState &&src) noexcept
reassign object by moving an existing object
Definition: MD5Model.hpp:1161
MD5AnimationState & operator=(const MD5AnimationState &OTHER)
reassign object by copying an existing object
Definition: MD5Model.hpp:1143
GLfloat lastTime
time of last frame interpolation
Definition: MD5Model.hpp:1120
GLfloat maxTime
duration of a single frame
Definition: MD5Model.hpp:1125
base frame joint
Definition: MD5Model.hpp:731
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:739
MD5BaseFrameJoint & operator=(const MD5BaseFrameJoint &OTHER)
reassign object by copying an existing object
Definition: MD5Model.hpp:757
MD5BaseFrameJoint()=default
construct a default object
MD5BaseFrameJoint(MD5BaseFrameJoint &&src) noexcept
construct object by moving an existing object
Definition: MD5Model.hpp:767
glm::vec3 position
position of the joint in object space
Definition: MD5Model.hpp:735
MD5BaseFrameJoint(const MD5BaseFrameJoint &OTHER)
construct an object by copying an existing object
Definition: MD5Model.hpp:749
MD5BaseFrameJoint & operator=(MD5BaseFrameJoint &&src) noexcept
reassign object by moving an existing object
Definition: MD5Model.hpp:775
bounding box containing the model during animation
Definition: MD5Model.hpp:806
MD5BoundingBox(const MD5BoundingBox &OTHER)
construct an object by copying an existing object
Definition: MD5Model.hpp:824
MD5BoundingBox & operator=(MD5BoundingBox &&src) noexcept
reassign object by moving an existing object
Definition: MD5Model.hpp:850
glm::vec3 min
minimum dimension bound
Definition: MD5Model.hpp:810
MD5BoundingBox(MD5BoundingBox &&src) noexcept
construct an object by moving an existing object
Definition: MD5Model.hpp:842
glm::vec3 max
maximum dimension bound
Definition: MD5Model.hpp:814
MD5BoundingBox & operator=(const MD5BoundingBox &OTHER)
reassign object by copying an existing object
Definition: MD5Model.hpp:832
MD5BoundingBox()=default
construct a default object
a joint of the MD5 Skeleton
Definition: MD5Model.hpp:83
MD5Joint(const MD5Joint &OTHER)
construct a joint object by copying an existing joint
Definition: MD5Model.hpp:117
char name[MAX_NAME_LENGTH]
joint identifier
Definition: MD5Model.hpp:95
MD5Joint(MD5Joint &&src) noexcept
construct a joint object by moving an existing object
Definition: MD5Model.hpp:135
glm::vec3 position
position of the joint in object space
Definition: MD5Model.hpp:103
MD5Joint & operator=(const MD5Joint &OTHER)
reassign an existing joint object by copying another joint object
Definition: MD5Model.hpp:125
glm::quat orientation
joint orientation expressed as a quaternion in object space
Definition: MD5Model.hpp:107
MD5Joint()=default
construct a default joint object
MD5Joint & operator=(MD5Joint &&src) noexcept
reassign an existing joint object by moving another joint object
Definition: MD5Model.hpp:143
GLint parent
index of the parent joint on skeletal tree
Definition: MD5Model.hpp:99
information pertaining to each animation joint
Definition: MD5Model.hpp:641
MD5JointInfo & operator=(MD5JointInfo &&src) noexcept
reassign object by moving an existing object
Definition: MD5Model.hpp:697
GLint startIndex
index of starting parameter
Definition: MD5Model.hpp:661
MD5JointInfo(const MD5JointInfo &OTHER)
construct a joint info object by copying an existing object
Definition: MD5Model.hpp:671
MD5JointInfo(MD5JointInfo &&src) noexcept
construct joint info object by moving an existing object
Definition: MD5Model.hpp:689
GLint parent
index of parent joint on skeletal tree
Definition: MD5Model.hpp:653
char name[MAX_NAME_LENGTH]
joint identifier
Definition: MD5Model.hpp:649
MD5JointInfo & operator=(const MD5JointInfo &OTHER)
reassign object by copying an existing object
Definition: MD5Model.hpp:679
MD5JointInfo()=default
construct a default joint info object
GLuint flags
bit flags denoted how to compute the skeleton of a frame for this joint
Definition: MD5Model.hpp:657
mesh that comprises the model's skin
Definition: MD5Model.hpp:493
GLint numTriangles
number of triangles in the mesh triangle array
Definition: MD5Model.hpp:546
MD5Texture textures[NUM_TEXTURES]
texture map array
Definition: MD5Model.hpp:517
TextureMap
named entities for different texture maps applied to the model
Definition: MD5Model.hpp:521
@ DIFFUSE
diffuse map
Definition: MD5Model.hpp:525
@ SPECULAR
specular map
Definition: MD5Model.hpp:529
@ NORMAL
normal map
Definition: MD5Model.hpp:533
MD5Mesh(MD5Mesh &&src) noexcept
construct a new mesh by moving an existing object
Definition: MD5Model.hpp:590
MD5Mesh()=default
construct a default mesh object
GLint numVertices
number of vertices in the mesh vertex array
Definition: MD5Model.hpp:542
MD5Mesh & operator=(MD5Mesh &&src) noexcept
reassign mesh object by moving an existing object
Definition: MD5Model.hpp:598
MD5Triangle * triangles
array triangles comprising the mesh
Definition: MD5Model.hpp:509
char shader[MAX_NAME_LENGTH]
base filename for all textures applied to mesh
Definition: MD5Model.hpp:555
MD5Vertex * vertices
array of vertices comprising the mesh
Definition: MD5Model.hpp:505
GLint numWeights
number of weights in the mesh weight array
Definition: MD5Model.hpp:550
~MD5Mesh()
deallocate member arrays
Definition: MD5Model.hpp:564
MD5Mesh & operator=(const MD5Mesh &OTHER)=delete
do not allow meshes to be copied
MD5Weight * weights
array of weights to determine vertex position based on joint positions
Definition: MD5Model.hpp:513
MD5Mesh(const MD5Mesh &OTHER)=delete
do not allow meshes to be copied
texture handle for the model
Definition: MD5Model.hpp:415
char filename[MAX_NAME_LENGTH]
filename texture was loaded from
Definition: MD5Model.hpp:427
MD5Texture & operator=(const MD5Texture &OTHER)
reassign texture object by copying an existing object
Definition: MD5Model.hpp:445
MD5Texture & operator=(MD5Texture &&src) noexcept
reassign texture object by moving an existing object
Definition: MD5Model.hpp:463
MD5Texture(const MD5Texture &OTHER)
construct a texture object by copying an existing object
Definition: MD5Model.hpp:437
GLuint texHandle
handle of texture stored on the GPU
Definition: MD5Model.hpp:423
MD5Texture()=default
constructs a default texture object
MD5Texture(MD5Texture &&src) noexcept
construct a texture object by moving an existing object
Definition: MD5Model.hpp:455
a triangle on the mesh
Definition: MD5Model.hpp:259
MD5Triangle & operator=(const MD5Triangle &OTHER)
reassign triangle object by copying an existing triangle
Definition: MD5Model.hpp:285
MD5Triangle(MD5Triangle &&src) noexcept
construct a triangle object by moving an existing triangle
Definition: MD5Model.hpp:295
MD5Triangle & operator=(MD5Triangle &&src) noexcept
reassign triangle object by moving an existing triangle
Definition: MD5Model.hpp:303
MD5Triangle(const MD5Triangle &OTHER)
construct a triangle by copying an existing triangle
Definition: MD5Model.hpp:277
MD5Triangle()=default
construct a default triangle object
GLint index[NUM_VERTICES]
vertex indices that make up triangle
Definition: MD5Model.hpp:267
a vertex on the mesh
Definition: MD5Model.hpp:179
MD5Vertex & operator=(const MD5Vertex &OTHER)
reassign existing vertex object by copying an existing vertex object
Definition: MD5Model.hpp:209
MD5Vertex & operator=(MD5Vertex &&src) noexcept
reassign existing vertex object by moving an existing vertex object
Definition: MD5Model.hpp:227
MD5Vertex(MD5Vertex &&src) noexcept
construct a vertex object by moving an existing vertex
Definition: MD5Model.hpp:219
glm::vec2 texCoord
texture coordinate for vertex
Definition: MD5Model.hpp:183
MD5Vertex(const MD5Vertex &OTHER)
construct a vertex object by copying an existing vertex
Definition: MD5Model.hpp:201
GLint start
index of starting weight
Definition: MD5Model.hpp:187
GLint count
number of weights that determine vertex's position
Definition: MD5Model.hpp:191
MD5Vertex()=default
construct a default vertex object
the weight for a mesh vertex
Definition: MD5Model.hpp:335
MD5Weight(MD5Weight &&src) noexcept
construct a weight object by moving an existing object
Definition: MD5Model.hpp:375
MD5Weight & operator=(MD5Weight &&src) noexcept
reassign an existing weight object by moving another
Definition: MD5Model.hpp:383
MD5Weight & operator=(const MD5Weight &OTHER)
reassign an existing weight object by copying another
Definition: MD5Model.hpp:365
MD5Weight(const MD5Weight &OTHER)
construct a weight object by copying an existing weight
Definition: MD5Model.hpp:357
GLfloat bias
contribution of the weight
Definition: MD5Model.hpp:343
GLint joint
index of joint the weight depends on
Definition: MD5Model.hpp:339
MD5Weight()=default
construct a default weight object
glm::vec3 position
weight's position in object space
Definition: MD5Model.hpp:347