From 8936266dcb163c6718df75833950fa2028b69fe7 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Wed, 9 Mar 2022 21:04:45 +0200 Subject: [PATCH] reading animations --- CMakeLists.txt | 2 +- animatable.cpp | 9 +++++++ animatable.h | 5 +++- animationChannel.cpp | 3 +++ bone.h | 1 - keyframeChannel.cpp | 21 ++++++++++++++++ keyframeChannel.h | 1 + light.cpp | 2 +- light.h | 2 +- material.h | 53 +++++++++++++++++---------------------- mesh.cpp | 2 +- mesh.h | 2 +- node.cpp | 3 +-- node.h | 2 -- texture.cpp | 8 +++--- texture.h | 4 +-- vbModelReader.cpp | 2 +- xmlModelReader.cpp | 59 +++++++++++++++++++++++++++++++++++++++----- xmlModelReader.h | 7 +++++- 19 files changed, 132 insertions(+), 56 deletions(-) create mode 100644 animatable.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4528392..1cb5d69 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(GUI text.cpp) set(UTILS util.cpp) set(MATH quaternion.cpp vector.cpp matrix.cpp ray.cpp) set(RENDER lineRenderer.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp) -set(ANIM animationController.cpp animationChannel.cpp animation.cpp animatable.h keyframeChannel.cpp driver.cpp) +set(ANIM animationController.cpp animationChannel.cpp animation.cpp animatable.cpp keyframeChannel.cpp driver.cpp) set(ARMATURE skeleton.cpp bone.cpp ikSolver.cpp) set(ASSET_READERS abstractAssetReader.cpp imageReader.cpp fontReader.cpp modelReader.cpp assimpModelReader.cpp vbModelReader.cpp xmlModelReader.cpp) set(ASSET_MANAGER assetManager.cpp textAsset.h imageAsset.h modelAsset.h fontAsset.h) diff --git a/animatable.cpp b/animatable.cpp new file mode 100644 index 0000000..4aa647b --- /dev/null +++ b/animatable.cpp @@ -0,0 +1,9 @@ +#include "animatable.h" + +namespace vb01{ + using namespace std; + + Animatable::Animatable(string name){ + this->name = name; + } +} diff --git a/animatable.h b/animatable.h index b4efcb8..27a06d7 100644 --- a/animatable.h +++ b/animatable.h @@ -6,8 +6,11 @@ namespace vb01{ class Animatable{ public: - Animatable(){} + Animatable(std::string = ""); virtual void animate(float, KeyframeChannel){} + inline std::string getName(){return name;} + protected: + std::string name; }; } diff --git a/animationChannel.cpp b/animationChannel.cpp index 4bd8968..22d14c7 100644 --- a/animationChannel.cpp +++ b/animationChannel.cpp @@ -35,6 +35,7 @@ namespace vb01{ Animation *animation = controller->getAnimation(animName); const vector &keyframeChannels = animation->getKeyframeChannels(); + for(KeyframeChannel ch : keyframeChannels) for(Keyframe k : ch.keyframes) keyframes.push_back(k); @@ -48,6 +49,7 @@ namespace vb01{ for(int i = 0; i < keyframes.size(); i++){ int curFrameNum = keyframes[i].frame; + if(maxKeyframeNum < curFrameNum) maxKeyframeNum = curFrameNum; } @@ -61,6 +63,7 @@ namespace vb01{ for(int i = 0; i < keyframes.size(); i++){ int curFrameNum = keyframes[i].frame; + if(minKeyframeNum > curFrameNum) minKeyframeNum = curFrameNum; } diff --git a/bone.h b/bone.h index 9542e7e..92b65fa 100644 --- a/bone.h +++ b/bone.h @@ -27,7 +27,6 @@ namespace vb01{ inline void setIkFromTail(bool ikFromTail){this->ikFromTail = ikFromTail;} inline void setSkeleton(Skeleton *sk){this->skeleton = sk;} inline Vector3 getInitAxis(int i){return initAxis[i];} - inline std::string getName(){return name;} inline Vector3 getRestPos(){return restPos;} inline Quaternion getRestRot(){return restRot;} inline Vector3 getRestScale(){return restScale;} diff --git a/keyframeChannel.cpp b/keyframeChannel.cpp index eca1306..b0ef84d 100644 --- a/keyframeChannel.cpp +++ b/keyframeChannel.cpp @@ -5,6 +5,7 @@ using namespace std; namespace vb01{ float KeyframeChannel::interpolate(Keyframe pastKeyframe, Keyframe nextKeyframe, float ratio){ float currentValue; + switch(pastKeyframe.interpolation){ case Keyframe::CONSTANT: currentValue = pastKeyframe.value; @@ -17,12 +18,14 @@ namespace vb01{ currentValue = interpolateBezier(points, ratio); break; } + return currentValue; } float KeyframeChannel::interpolateBezier(vector points, float ratio){ int numPoints = points.size(); vector newPoints; + for(int i = 0; i < numPoints - 1; i++) newPoints.push_back(points[i] + (points[i + 1] - points[i]) * ratio); @@ -34,6 +37,7 @@ namespace vb01{ KeyframeChannelType KeyframeChannel::getKeyframeChannelType(string typeString){ KeyframeChannelType type; + if(typeString == "pos_x") type = KeyframeChannelType::POS_X; else if(typeString == "pos_y") @@ -66,17 +70,34 @@ namespace vb01{ type = KeyframeChannelType::SHAPE_KEY_VALUE; else if(typeString == "shape_key_max") type = KeyframeChannelType::SHAPE_KEY_MAX; + return type; } + Keyframe::Interpolation KeyframeChannel::getKeyframeInterpolationType(string interpString){ + Keyframe::Interpolation interpolation; + + if(interpString == "BEZIER") + interpolation = Keyframe::Interpolation::BEZIER; + else if(interpString == "LINEAR") + interpolation = Keyframe::Interpolation::LINEAR; + else if(interpString == "CONSTANT") + interpolation = Keyframe::Interpolation::CONSTANT; + + return interpolation; + } + Keyframe KeyframeChannel::findKeyframe(float time, KeyframeChannel keyframeChannel, bool last){ int pastKeyframeId = -1; + for(int i = 0; i < keyframeChannel.keyframes.size(); i++){ Keyframe keyframe = keyframeChannel.keyframes[i]; + if(time >= keyframe.frame){ pastKeyframeId = i; } } + return keyframeChannel.keyframes[pastKeyframeId + (last ? 0 : 1)]; } diff --git a/keyframeChannel.h b/keyframeChannel.h index 07f475a..47b046e 100644 --- a/keyframeChannel.h +++ b/keyframeChannel.h @@ -68,6 +68,7 @@ namespace vb01{ std::vector keyframes; static float interpolateBezier(std::vector, float); + static Keyframe::Interpolation getKeyframeInterpolationType(std::string); static KeyframeChannel::Type getKeyframeChannelType(std::string); static float interpolate(Keyframe, Keyframe, float); static Keyframe findKeyframe(float, KeyframeChannel, bool); diff --git a/light.cpp b/light.cpp index 7dd4e7c..7f28421 100755 --- a/light.cpp +++ b/light.cpp @@ -15,7 +15,7 @@ using namespace glm; using namespace std; namespace vb01{ - Light::Light(Type t){ + Light::Light(Type t, string name) : Animatable(name){ this->type = t; initDepthMap(); diff --git a/light.h b/light.h index 2eeb20c..fb517b8 100755 --- a/light.h +++ b/light.h @@ -17,7 +17,7 @@ namespace vb01{ public: enum Type{POINT, DIRECTIONAL, SPOT, AMBIENT}; - Light(Type); + Light(Type, std::string = ""); ~Light(); void update(); inline void setNode(Node *node){this->node = node;} diff --git a/material.h b/material.h index 8642645..1db4513 100755 --- a/material.h +++ b/material.h @@ -15,6 +15,21 @@ namespace vb01{ class Material : public Animatable{ public: struct Uniform : public Animatable{ + enum Type{ + INT, + BOOL, + FLOAT, + VECTOR_2, + VECTOR_3, + VECTOR_4, + TEXTURE + }; + + Uniform(std::string name, Type type) : Animatable(name){ + this->name = name; + this->type = type; + } + void animate(float val, KeyframeChannel channel){ switch(channel.type){ case KeyframeChannel::UNIFORM_1: @@ -32,16 +47,6 @@ namespace vb01{ } } - enum Type{ - INT, - BOOL, - FLOAT, - VECTOR_2, - VECTOR_3, - VECTOR_4, - TEXTURE - }; - std::string name; Type type; @@ -55,10 +60,8 @@ namespace vb01{ struct IntUniform : public Uniform{ int value; - IntUniform(std::string name, int value){ - this->name = name; + IntUniform(std::string name, int value) : Uniform(name, Uniform::INT){ this->value = value; - this->type = Uniform::INT; } void animateComponent1(float val){value = (int)val;} @@ -67,10 +70,8 @@ namespace vb01{ struct BoolUniform : public Uniform{ bool value; - BoolUniform(std::string name, bool value){ - this->name = name; + BoolUniform(std::string name, bool value) : Uniform(name, Uniform::BOOL){ this->value = value; - this->type = Uniform::BOOL; } void animateComponent1(float val){value = (bool)val;} @@ -79,10 +80,8 @@ namespace vb01{ struct FloatUniform : public Uniform{ float value; - FloatUniform(std::string name, float value){ - this->name = name; + FloatUniform(std::string name, float value) : Uniform(name, Uniform::FLOAT){ this->value = value; - this->type = Uniform::FLOAT; } void animateComponent1(float val){value = val;} @@ -91,10 +90,8 @@ namespace vb01{ struct Vector2Uniform : public Uniform{ Vector2 value; - Vector2Uniform(std::string name, Vector2 value){ - this->name = name; + Vector2Uniform(std::string name, Vector2 value) : Uniform(name, Uniform::VECTOR_2){ this->value = value; - this->type = Uniform::VECTOR_2; } void animateComponent1(float val){value.x = val;} @@ -105,10 +102,8 @@ namespace vb01{ struct Vector3Uniform : public Uniform{ Vector3 value; - Vector3Uniform(std::string name, Vector3 value){ - this->name = name; + Vector3Uniform(std::string name, Vector3 value) : Uniform(name, Uniform::VECTOR_3){ this->value = value; - this->type = Uniform::VECTOR_3; } void animateComponent1(float val){value.x = val;} @@ -121,10 +116,8 @@ namespace vb01{ struct Vector4Uniform : public Uniform{ Vector4 value; - Vector4Uniform(std::string name, Vector4 value){ - this->name = name; + Vector4Uniform(std::string name, Vector4 value) : Uniform(name, Uniform::VECTOR_4){ this->value = value; - this->type = Uniform::VECTOR_4; } void animateComponent1(float val){value.x = val;} @@ -140,11 +133,9 @@ namespace vb01{ Texture *value = nullptr; bool animatable = false; - TextureUniform(std::string name, Texture *value, bool animatable){ - this->name = name; + TextureUniform(std::string name, Texture *value, bool animatable) : Uniform(name, Uniform::TEXTURE){ this->value = value; this->animatable = animatable; - this->type = Uniform::TEXTURE; } }; diff --git a/mesh.cpp b/mesh.cpp index 5089644..3c95ac1 100755 --- a/mesh.cpp +++ b/mesh.cpp @@ -33,7 +33,7 @@ namespace vb01{ Mesh::Mesh(){} - Mesh::Mesh(Vertex *vertices, unsigned int *indices, int numTris, string *vertexGroups, int numVertexGroups, ShapeKey *shapeKeys, int numShapeKeys, string name) : Animatable(){ + Mesh::Mesh(Vertex *vertices, unsigned int *indices, int numTris, string *vertexGroups, int numVertexGroups, ShapeKey *shapeKeys, int numShapeKeys, string name){ this->vertices = vertices; this->indices = indices; this->numTris = numTris; diff --git a/mesh.h b/mesh.h index 61dcb6f..4ffe853 100755 --- a/mesh.h +++ b/mesh.h @@ -14,7 +14,7 @@ namespace vb01{ class Texture; class Skeleton; - class Mesh : public Animatable{ + class Mesh{ public: struct ShapeKey : public Animatable{ std::string name; diff --git a/node.cpp b/node.cpp index ce4e36c..b55ea71 100755 --- a/node.cpp +++ b/node.cpp @@ -16,11 +16,10 @@ using namespace std; using namespace glm; namespace vb01{ - Node::Node(Vector3 pos, Quaternion orientation, Vector3 scale, string name) : Animatable(){ + Node::Node(Vector3 pos, Quaternion orientation, Vector3 scale, string name) : Animatable(name){ this->pos = pos; this->scale = scale; this->orientation = orientation; - this->name = name; globalAxis[0] = Vector3::VEC_I; globalAxis[1] = Vector3::VEC_J; diff --git a/node.h b/node.h index c9325c5..4d4e370 100755 --- a/node.h +++ b/node.h @@ -64,7 +64,6 @@ namespace vb01{ inline int getNumChildren(){return children.size();} inline Quaternion getOrientation(){return orientation;} inline bool isVisible(){return visible;} - inline std::string getName(){return name;} inline void setVisible(bool v){this->visible = v;} inline void addDriver(Driver *d){drivers.push_back(d);} private: @@ -87,7 +86,6 @@ namespace vb01{ std::vector lights; std::vector texts; std::vector skeletons; - std::string name; Node *parent = nullptr; }; } diff --git a/texture.cpp b/texture.cpp index d48a8d9..cf0f311 100755 --- a/texture.cpp +++ b/texture.cpp @@ -15,7 +15,7 @@ using namespace std; namespace vb01{ - Texture::Texture(int width, int height, bool shadowMap){ + Texture::Texture(int width, int height, bool shadowMap) : Animatable(){ this->width = width; this->height = height; texture = new u32; @@ -42,7 +42,7 @@ namespace vb01{ } } - Texture::Texture(string paths[], int numPaths, bool cubemap, int mipmapLevel, bool flip){ + Texture::Texture(string paths[], int numPaths, bool cubemap, int mipmapLevel, bool flip, string name) : Animatable(name){ this->cubemap = cubemap; this->paths = new string[numPaths]; @@ -86,7 +86,7 @@ namespace vb01{ } } - Texture::Texture(int width, bool depth, int mipmapLevel){ + Texture::Texture(int width, bool depth, int mipmapLevel, string name) : Animatable(name){ this->width = width; this->mipmapLevel = mipmapLevel; this->cubemap = true; @@ -127,7 +127,7 @@ namespace vb01{ glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } - Texture::Texture(FT_Face face){ + Texture::Texture(FT_Face face) : Animatable(){ texture = new u32; glGenTextures(1, &texture[0]); diff --git a/texture.h b/texture.h index d9cbe9c..9eb6588 100755 --- a/texture.h +++ b/texture.h @@ -14,8 +14,8 @@ namespace vb01{ public: ~Texture(); Texture(int, int, bool = true); - Texture(std::string[], int, bool, int = 0, bool = false); - Texture(int, bool = true, int = 0); + Texture(std::string[], int, bool, int = 0, bool = false, std::string = ""); + Texture(int, bool = true, int = 0, std::string = ""); Texture(FT_Face); void select(int = 0, int = 0); void update(int = 0); diff --git a/vbModelReader.cpp b/vbModelReader.cpp index 7a28804..d66b82a 100644 --- a/vbModelReader.cpp +++ b/vbModelReader.cpp @@ -596,7 +596,7 @@ namespace vb01{ float outerAngle = atof(lightData[7].substr(lightData[7].find_first_of(':') + 2).c_str()); float innerAngle = atof(lightData[8].substr(lightData[8].find_first_of(':') + 2).c_str()); - Light *light = new Light(type); + Light *light = new Light(type, name); light->setColor(color); light->setOuterAngle(outerAngle); light->setInnerAngle(innerAngle); diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index 05d83c2..b87ff20 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -2,8 +2,11 @@ #include "mesh.h" #include "skeleton.h" #include "bone.h" +#include "animation.h" #include "vector.h" #include "animationController.h" +#include "animatable.h" +#include "keyframeChannel.h" #include @@ -152,6 +155,51 @@ namespace vb01{ return mesh; } + Animation* XmlModelReader::processAnimation(XMLElement *animationEl, vector animatables){ + string name = animationEl->Attribute("name"); + Animation *animation = new Animation(name); + + for(XMLElement *channelEl = animationEl->FirstChildElement("channel"); channelEl; channelEl = channelEl->NextSiblingElement()){ + vector keyframes; + + for(XMLElement *keyframeEl = channelEl->FirstChildElement("keyframe"); keyframeEl; keyframeEl = keyframeEl->NextSiblingElement()){ + string interpString = keyframeEl->Attribute("interpolation"); + Keyframe::Interpolation interpolation = KeyframeChannel::getKeyframeInterpolationType(interpString); + float frame = atof(keyframeEl->Attribute("frame")); + float value = atof(keyframeEl->Attribute("value")); + float leftFrame = atof(keyframeEl->Attribute("lefthandleframe")); + float leftValue = atof(keyframeEl->Attribute("lefthandlevalue")); + float rightFrame = atof(keyframeEl->Attribute("righthandleframe")); + float rightValue = atof(keyframeEl->Attribute("righthandlevalue")); + keyframes.push_back(KeyframeChannel::createKeyframe(interpolation, value, frame, leftValue, leftFrame, rightValue, rightFrame)); + } + + string typeStr = channelEl->Attribute("type"); + KeyframeChannel::Type type = KeyframeChannel::getKeyframeChannelType(typeStr); + Animatable *animatable; + string name = channelEl->Attribute("name"); + + for(Animatable *an : animatables) + if(an->getName() == name){ + animatable = an; + break; + } + + KeyframeChannel channel = KeyframeChannel::createKeyframeChannel(type, animatable, keyframes); + animation->addKeyframeChannel(channel); + } + + return animation; + } + + void XmlModelReader::processAnimations(XMLElement *animContainer, vector animatables){ + AnimationController *animController = AnimationController::getSingleton(); + const char *animTag = "animation"; + + for(XMLElement *animEl = animContainer->FirstChildElement(animTag); animEl && strcmp(animEl->Name(), animTag) == 0; animEl = animEl->NextSiblingElement()) + animController->addAnimation(processAnimation(animEl, animatables)); + } + Skeleton* XmlModelReader::processSkeleton(Node *root, XMLElement *skeletonEl){ XMLElement *rootBoneEl = skeletonEl->FirstChildElement("bone"); Bone *rootBone = (Bone*)processNode(root, rootBoneEl, true); @@ -164,6 +212,8 @@ namespace vb01{ for(Node *bone : bones) skeleton->addBone((Bone*)bone, (Bone*)bone->getParent()); + processAnimations(skeletonEl, vector(bones.begin(), bones.end())); + return skeleton; } @@ -186,14 +236,9 @@ namespace vb01{ float eps = pow(10, -2); - for(int i = 0; i < 9; i++){ + for(int i = 0; i < 9; i++) if(fabs(components[i]) < eps) components[i] = 0; - } - /* - else if(fabs(components[i]) > 1.0) - components[i] = 1.0; - */ Vector3 head = Vector3(components[0], components[1], components[2]); Vector3 xAxis = Vector3(components[3], components[4], components[5]); @@ -239,6 +284,8 @@ namespace vb01{ XMLElement *lightTag = xmlEl->FirstChildElement("light"); + processAnimations(xmlEl, vector{node}); + const char *tagName = (bone ? "bone" : "node"); for(XMLElement *el = xmlEl->FirstChildElement(tagName); el; el = el->NextSiblingElement()) diff --git a/xmlModelReader.h b/xmlModelReader.h index a556515..2ddd7ed 100644 --- a/xmlModelReader.h +++ b/xmlModelReader.h @@ -3,6 +3,8 @@ #include "modelReader.h" +#include + namespace tinyxml2{ class XMLElement; } @@ -11,7 +13,8 @@ namespace vb01{ class Node; class Mesh; class Skeleton; - class Bone; + class Animatable; + class Animation; class XmlModelReader : public ModelReader{ public: @@ -19,6 +22,8 @@ namespace vb01{ private: Node* processNode(Node*, tinyxml2::XMLElement*, bool = false); Mesh* processMesh(tinyxml2::XMLElement*); + Animation* processAnimation(tinyxml2::XMLElement*, std::vector); + void processAnimations(tinyxml2::XMLElement*, std::vector); Skeleton* processSkeleton(Node*, tinyxml2::XMLElement*); }; }