12#ifndef CSCI441_MD5_MODEL_TYPES_HPP
13#define CSCI441_MD5_MODEL_TYPES_HPP
48#ifdef CSCI441_USE_GLEW
54#include <glm/ext/quaternion_float.hpp>
59namespace CSCI441_INTERNAL {
71 static constexpr GLshort MAX_NAME_LENGTH = 512;
79 char filename[MAX_NAME_LENGTH] =
"";
84 MD5Texture() =
default;
89 MD5Texture(
const MD5Texture &OTHER) {
97 MD5Texture& operator=(
const MD5Texture &OTHER) {
107 MD5Texture(MD5Texture&& src)
noexcept {
115 MD5Texture& operator=(MD5Texture&& src)
noexcept {
126 void _copyFromSrc(
const MD5Texture &src) {
127 this->texHandle = src.texHandle;
128 strncpy(this->filename, src.filename, MAX_NAME_LENGTH);
129 this->filename[ strlen(src.filename) ] =
'\0';
135 void _moveFromSrc(MD5Texture& src) {
139 strncpy(src.filename,
"", MAX_NAME_LENGTH);
140 src.filename[0] =
'\0';
145 struct MD5MaterialShader {
149 static constexpr GLshort MAX_NAME_LENGTH = 512;
153 static constexpr GLshort NUM_TEXTURES = 4;
157 char name[MAX_NAME_LENGTH] =
"";
161 MD5Texture textures[NUM_TEXTURES];
165 GLuint displacementScale = 1;
187 MD5MaterialShader() =
default;
188 MD5MaterialShader(
const MD5MaterialShader &OTHER) {
191 MD5MaterialShader& operator=(
const MD5MaterialShader &OTHER) {
192 if (
this != &OTHER) {
197 MD5MaterialShader(MD5MaterialShader&& src)
noexcept {
200 MD5MaterialShader& operator=(MD5MaterialShader&& src)
noexcept {
207 void _copyFromSrc(
const MD5MaterialShader &src) {
208 for (GLshort i = 0; i < NUM_TEXTURES; i++) {
209 this->textures[i] = src.textures[i];
211 strncpy(this->name, src.name, MAX_NAME_LENGTH);
212 this->name[ strlen(src.name) ] =
'\0';
214 void _moveFromSrc(MD5MaterialShader &src) {
215 for (GLshort i = 0; i < NUM_TEXTURES; i++) {
216 this->textures[i] = std::move( src.textures[i] );
218 strncpy(this->name, src.name, MAX_NAME_LENGTH);
219 this->name[ strlen(src.name) ] =
'\0';
220 strncpy(src.name,
"", MAX_NAME_LENGTH);
235 static constexpr GLint NULL_JOINT = -1;
239 static constexpr GLshort MAX_NAME_LENGTH = 256;
243 char name[MAX_NAME_LENGTH] =
"";
247 GLint parent = NULL_JOINT;
251 glm::vec3 position = {0.0f, 0.0f, 0.0f};
255 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
260 MD5Joint() =
default;
265 MD5Joint(
const MD5Joint &OTHER) {
273 MD5Joint& operator=(
const MD5Joint &OTHER) {
274 if (
this != &OTHER) {
283 MD5Joint(MD5Joint&& src)
noexcept {
291 MD5Joint& operator=(MD5Joint&& src)
noexcept {
302 void _copyFromSrc(
const MD5Joint& src) {
303 strncpy(this->name, src.name, MAX_NAME_LENGTH);
304 this->name[ strlen(src.name) ] =
'\0';
305 this->parent = src.parent;
306 this->position = src.position;
307 this->orientation = src.orientation;
314 void _moveFromSrc(MD5Joint& src) {
318 strncpy(src.name,
"", MAX_NAME_LENGTH);
320 src.parent = NULL_JOINT;
321 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
322 src.orientation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
333 glm::vec2 texCoord = {0.0f, 0.0f};
346 MD5Vertex() =
default;
351 MD5Vertex(
const MD5Vertex &OTHER) {
359 MD5Vertex& operator=(
const MD5Vertex &OTHER) {
360 if (
this != &OTHER) {
369 MD5Vertex(MD5Vertex&& src)
noexcept {
377 MD5Vertex& operator=(MD5Vertex&& src)
noexcept {
388 void _copyFromSrc(
const MD5Vertex &src) {
389 this->texCoord = src.texCoord;
390 this->start = src.start;
391 this->count = src.count;
397 void _moveFromSrc(MD5Vertex& src) {
400 src.texCoord = glm::vec2(0.0f, 0.0f);
413 static constexpr GLshort NUM_VERTICES = 3;
417 GLint index[NUM_VERTICES] = {0};
422 MD5Triangle() =
default;
427 MD5Triangle(
const MD5Triangle &OTHER) {
435 MD5Triangle& operator=(
const MD5Triangle &OTHER) {
436 if (
this != &OTHER) {
445 MD5Triangle(MD5Triangle&& src)
noexcept {
453 MD5Triangle& operator=(MD5Triangle&& src)
noexcept {
464 void _copyFromSrc(
const MD5Triangle &src) {
465 for (GLshort i = 0; i < NUM_VERTICES; i++) {
466 this->index[i] = src.index[i];
473 void _moveFromSrc(MD5Triangle &src) {
476 for (GLint & i : src.index) {
489 GLint joint = MD5Joint::NULL_JOINT;
497 glm::vec3 position = {0.0f, 0.0f, 0.0f};
502 MD5Weight() =
default;
507 MD5Weight(
const MD5Weight &OTHER) {
515 MD5Weight& operator=(
const MD5Weight &OTHER) {
516 if (
this != &OTHER) {
525 MD5Weight(MD5Weight&& src)
noexcept {
533 MD5Weight& operator=(MD5Weight&& src)
noexcept {
544 void _copyFromSrc(
const MD5Weight &src) {
545 this->joint = src.joint;
546 this->bias = src.bias;
547 this->position = src.position;
553 void _moveFromSrc(MD5Weight &src) {
556 src.joint = MD5Joint::NULL_JOINT;
558 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
570 MD5Vertex* vertices =
nullptr;
574 MD5Triangle* triangles =
nullptr;
578 MD5Weight* weights =
nullptr;
580 MD5MaterialShader* shader =
nullptr;
585 GLint numVertices = 0;
589 GLint numTriangles = 0;
593 GLint numWeights = 0;
615 MD5Mesh(
const MD5Mesh &OTHER) =
delete;
620 MD5Mesh& operator=(
const MD5Mesh &OTHER) =
delete;
626 MD5Mesh(MD5Mesh&& src)
noexcept {
634 MD5Mesh& operator=(MD5Mesh&& src)
noexcept {
645 void _moveFromSrc(MD5Mesh& src) {
646 this->vertices = src.vertices;
647 src.vertices =
nullptr;
649 this->triangles = src.triangles;
650 src.triangles =
nullptr;
652 this->weights = src.weights;
653 src.weights =
nullptr;
655 this->shader = src.shader;
656 src.shader =
nullptr;
658 this->numVertices = src.numVertices;
661 this->numTriangles = src.numTriangles;
662 src.numTriangles = 0;
664 this->numWeights = src.numWeights;
675 struct MD5JointInfo {
679 static constexpr GLshort MAX_NAME_LENGTH = 256;
683 char name[MAX_NAME_LENGTH] =
"";
687 GLint parent = MD5Joint::NULL_JOINT;
695 GLint startIndex = 0;
700 MD5JointInfo() =
default;
705 MD5JointInfo(
const MD5JointInfo& OTHER) {
713 MD5JointInfo& operator=(
const MD5JointInfo& OTHER) {
714 if (
this != &OTHER) {
723 MD5JointInfo(MD5JointInfo&& src)
noexcept {
731 MD5JointInfo& operator=(MD5JointInfo&& src)
noexcept {
742 void _copyFromSrc(
const MD5JointInfo &src) {
743 strncpy(this->name, src.name, MAX_NAME_LENGTH);
744 this->name[ strlen(src.name) ] =
'\0';
745 this->parent = src.parent;
746 this->flags = src.flags;
747 this->startIndex = src.startIndex;
753 void _moveFromSrc(MD5JointInfo &src) {
756 strncpy(src.name,
"", MAX_NAME_LENGTH);
758 src.parent = MD5Joint::NULL_JOINT;
767 struct MD5BaseFrameJoint {
771 glm::vec3 position = {0.0f, 0.0f, 0.0f};
775 glm::quat orientation = {0.0f, 0.0f, 0.0f, 0.0f};
780 MD5BaseFrameJoint() =
default;
785 MD5BaseFrameJoint(
const MD5BaseFrameJoint& OTHER) {
793 MD5BaseFrameJoint& operator=(
const MD5BaseFrameJoint &OTHER) {
794 if (
this != &OTHER) {
803 MD5BaseFrameJoint(MD5BaseFrameJoint&& src)
noexcept {
811 MD5BaseFrameJoint& operator=(MD5BaseFrameJoint&& src)
noexcept {
822 void _copyFromSrc(
const MD5BaseFrameJoint &src) {
823 this->position = src.position;
824 this->orientation = src.orientation;
830 void _moveFromSrc(MD5BaseFrameJoint &src) {
833 src.position = glm::vec3(0.0f, 0.0f, 0.0f);
834 src.orientation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
842 struct MD5BoundingBox {
846 glm::vec3 min = {0.0f, 0.0f, 0.0f};
850 glm::vec3 max = {0.0f, 0.0f, 0.0f};
855 MD5BoundingBox() =
default;
860 MD5BoundingBox(
const MD5BoundingBox &OTHER) {
868 MD5BoundingBox& operator=(
const MD5BoundingBox &OTHER) {
869 if (
this != &OTHER) {
878 MD5BoundingBox(MD5BoundingBox&& src)
noexcept {
886 MD5BoundingBox& operator=(MD5BoundingBox&& src)
noexcept {
897 void _copyFromSrc(
const MD5BoundingBox& src) {
905 void _moveFromSrc(MD5BoundingBox& src) {
908 src.min = glm::vec3(0.0f, 0.0f, 0.0f);
909 src.max = glm::vec3(0.0f, 0.0f, 0.0f);
928 [[nodiscard]] GLint getNumberOfFrames()
const {
return _numFrames; }
935 void setNumberOfFrames(
const GLint numFrames) {
937 if(_skeletonFrames !=
nullptr) {
938 for (GLint i = 0; i < _numFrames; ++i) {
939 delete _skeletonFrames[i];
942 delete[] _skeletonFrames;
943 _skeletonFrames =
nullptr;
944 delete[] _boundingBoxes;
945 _boundingBoxes =
nullptr;
947 _numFrames = numFrames;
948 if ( _numFrames > 0 ) {
949 _skeletonFrames =
new MD5Joint*[_numFrames];
950 for (GLint i = 0; i < _numFrames; ++i) {
951 _skeletonFrames[i] =
nullptr;
953 _boundingBoxes =
new MD5BoundingBox[_numFrames];
961 [[nodiscard]] GLint getNumberOfJoints()
const {
return _numJoints; }
969 void setNumberOfJoints(
const GLint numJoints) {
971 if(_skeletonFrames !=
nullptr) {
972 for (GLint i = 0; i < _numFrames; ++i) {
973 delete _skeletonFrames[i];
974 _skeletonFrames[i] =
nullptr;
978 _numJoints = numJoints;
979 if (_numJoints > 0) {
980 if(_skeletonFrames !=
nullptr) {
981 for(GLint i = 0; i < _numFrames; ++i) {
983 _skeletonFrames[i] =
new MD5Joint[_numJoints];
996 [[nodiscard]]
const MD5Joint* getSkeletonFrame(
const GLint frameIndex)
const {
997 if ( frameIndex < 0 || frameIndex >= _numFrames ) {
998 throw std::out_of_range(
"frameIndex out of range");
1000 if (_skeletonFrames ==
nullptr) {
1001 throw std::out_of_range(
"skeleton frames are null, setNumberOfFrames() may not have been called");
1003 return _skeletonFrames[frameIndex];
1014 [[nodiscard]] MD5Joint& getSkeletonFrameJoint(
const GLint frameIndex,
const GLint jointIndex)
const {
1015 if ( frameIndex < 0 || frameIndex >= _numFrames ) {
1016 throw std::out_of_range(
"frameIndex out of range");
1018 if ( jointIndex < 0 || jointIndex >= _numJoints ) {
1019 throw std::out_of_range(
"jointIndex out of range");
1021 if (_skeletonFrames ==
nullptr) {
1022 throw std::out_of_range(
"skeleton frames are null, setNumberOfFrames() may not have been called");
1024 if (_skeletonFrames[frameIndex] ==
nullptr) {
1025 throw std::out_of_range(
"skeleton joints are null, setNumberOfJoints() may not have been called");
1027 return _skeletonFrames[frameIndex][jointIndex];
1037 [[nodiscard]] MD5BoundingBox& getBoundingBox(
const GLint frameIndex)
const {
1038 if(frameIndex < 0 || frameIndex >= _numFrames) {
1039 throw std::out_of_range(
"frameIndex out of range");
1041 if (_boundingBoxes ==
nullptr) {
1042 throw std::out_of_range(
"bounding boxes are null, setNumberOfFrames() may not have been called");
1044 return _boundingBoxes[frameIndex];
1050 MD5Animation() =
default;
1055 if(_skeletonFrames !=
nullptr) {
1056 for (GLint i = 0; i < _numFrames; i++) {
1057 delete[] _skeletonFrames[i];
1058 _skeletonFrames[i] =
nullptr;
1061 delete[] _skeletonFrames;
1062 _skeletonFrames =
nullptr;
1064 delete[] _boundingBoxes;
1065 _boundingBoxes =
nullptr;
1072 MD5Animation(
const MD5Animation& OTHER) =
delete;
1077 MD5Animation& operator=(
const MD5Animation& OTHER) =
delete;
1083 MD5Animation(MD5Animation&& src)
noexcept {
1091 MD5Animation& operator=(MD5Animation&& src)
noexcept {
1102 GLint _numFrames = 0;
1107 GLint _numJoints = 0;
1112 MD5Joint** _skeletonFrames =
nullptr;
1117 MD5BoundingBox* _boundingBoxes =
nullptr;
1123 void _moveFromSrc(MD5Animation &src) {
1124 this->_numFrames = src._numFrames;
1127 this->_numJoints = src._numJoints;
1130 this->frameRate = src.frameRate;
1133 this->_skeletonFrames = src._skeletonFrames;
1134 src._skeletonFrames =
nullptr;
1136 this->_boundingBoxes = src._boundingBoxes;
1137 src._boundingBoxes =
nullptr;
1144 struct MD5AnimationState {
1148 GLint currFrame = 0;
1152 GLint nextFrame = 0;
1156 GLfloat lastTime = 0.0f;
1161 GLfloat maxTime = 0.0f;
1166 MD5AnimationState() =
default;
1171 MD5AnimationState(
const MD5AnimationState &OTHER) {
1172 _copyFromSrc(OTHER);
1179 MD5AnimationState& operator=(
const MD5AnimationState &OTHER) {
1180 if (
this != &OTHER) {
1181 _copyFromSrc(OTHER);
1189 MD5AnimationState(MD5AnimationState&& src)
noexcept {
1197 MD5AnimationState& operator=(MD5AnimationState&& src)
noexcept {
1208 void _copyFromSrc(
const MD5AnimationState &src) {
1209 this->currFrame = src.currFrame;
1210 this->nextFrame = src.nextFrame;
1211 this->lastTime = src.lastTime;
1212 this->maxTime = src.maxTime;
1218 void _moveFromSrc(MD5AnimationState &src) {
1223 src.lastTime = 0.0f;