diff --git a/CMakeLists.txt b/CMakeLists.txt index 0748dc9..3f84b2f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(utils util.cpp) set(math quaternion.cpp vector.cpp matrix.cpp ray.cpp) set(render waterPlane.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(model modelReader.cpp assimpModelReader.cpp vbModelReader.cpp) -set(anim animationChannel.cpp animation.cpp) +set(anim animationController.cpp animationChannel.cpp animation.cpp) set(armature skeleton.cpp bone.cpp) add_library(vb01 SHARED main.cpp ${render} ${math} ${model} ${utils} ${gui} ${armature} ${anim}) diff --git a/animation.h b/animation.h index 0e6aee5..0825399 100644 --- a/animation.h +++ b/animation.h @@ -23,14 +23,14 @@ namespace vb01{ SCALE_Y, SCALE_Z }; - enum Interpolation{CONSTANT,LINEAR,BEZIER}; + enum Interpolation{CONSTANT, LINEAR, BEZIER}; Type type; Interpolation interpolation; float value; int frame; }; - Bone *bone=nullptr; + Bone *bone = nullptr; std::vector keyframes; }; diff --git a/animationChannel.cpp b/animationChannel.cpp index e69de29..6e74fe3 100644 --- a/animationChannel.cpp +++ b/animationChannel.cpp @@ -0,0 +1,28 @@ +#include "animationChannel.h" +#include "animationController.h" +#include "animation.h" + +using namespace std; + +namespace vb01{ + AnimationChannel::AnimationChannel(AnimationController *controller){ + this->controller = controller; + } + + AnimationChannel::~AnimationChannel(){ + } + + void AnimationChannel::setAnimationName(string animName){ + this->animationName = animName; + + Animation *animation = controller->getAnimation(animName); + Animation::KeyframeGroup *startGroup = animation->getKeyframeGroup(bones[0]); + int maxStartFrame = startGroup->keyframes[startGroup->keyframes.size() - 1].frame; + for(int i = 0; i < bones.size() ; i++){ + Animation::KeyframeGroup *group = animation->getKeyframeGroup(bones[i]); + int maxFrame = group->keyframes[group->keyframes.size() - 1].frame; + if(maxStartFrame < maxFrame) + maxStartFrame = maxFrame; + } + } +} diff --git a/animationChannel.h b/animationChannel.h index 6c87cd9..14c836d 100644 --- a/animationChannel.h +++ b/animationChannel.h @@ -1,13 +1,36 @@ #ifndef ANIMATION_CHANNEL_H #define ANIMATION_CHANNEL_H +#include +#include + namespace vb01{ + class AnimationController; + class Bone; + class AnimationChannel{ public: - AnimationChannel(); + AnimationChannel(AnimationController*); ~AnimationChannel(); - void update(); + void setAnimationName(std::string name); + inline std::vector getBones(){return bones;} + inline void addBone(Bone *bone){bones.push_back(bone);} + inline void removeAllBones(){bones.clear();} + inline void setSpeed(float speed){this->speed = speed;} + inline float getSpeed(){return speed;} + inline int getCurrentFrame(){return currentFrame;} + inline void setCurrentFrame(int frame){this->currentFrame = frame;} + inline int getNumFrames(){return numFrames;} + inline void setLoop(bool loop){this->loop = loop;} + inline bool isLoop(){return loop;} + inline std::string getAnimationName(){return animationName;} private: + AnimationController *controller = nullptr; + float speed = 1.f; + int currentFrame = 0, numFrames; + bool loop = false; + std::string animationName; + std::vector bones; }; } diff --git a/animationController.cpp b/animationController.cpp index 68ca9d0..0a555d8 100644 --- a/animationController.cpp +++ b/animationController.cpp @@ -1,12 +1,96 @@ #include "animationController.h" +#include "animationChannel.h" +#include "skeleton.h" + +using namespace std; namespace vb01{ - AnimationController::AnimationController(){ + AnimationController::AnimationController(Skeleton *skeleton){ + this->skeleton = skeleton; } AnimationController::~AnimationController(){ } void AnimationController::update(){ + for(AnimationChannel *channel : channels){ + Animation *animation = skeleton->getAnimationController()->getAnimation(channel->getAnimationName()); + for(Bone *channelBone : channel->getBones()){ + Animation::KeyframeGroup *keyframeGroup = animation->getKeyframeGroup(channelBone); + int keyframeId = -1; + for(int i = 0 ; i < keyframeGroup->keyframes.size(); i++){ + Animation::KeyframeGroup::Keyframe keyframe = keyframeGroup->keyframes[i]; + if(keyframe.frame > channel->getCurrentFrame()){ + keyframeId = i; + break; + } + } + + + Animation::KeyframeGroup::Keyframe pastKeyframe = keyframeGroup->keyframes[keyframeId - 1]; + int pastFrame = pastKeyframe.frame; + int nextFrame = keyframeGroup->keyframes[keyframeId].frame; + float ratio = (float)(channel->getCurrentFrame() - pastFrame) / (nextFrame - pastFrame); + + switch(pastKeyframe.interpolation){ + case Animation::KeyframeGroup::Keyframe::CONSTANT: + break; + case Animation::KeyframeGroup::Keyframe::LINEAR: + break; + case Animation::KeyframeGroup::Keyframe::BEZIER: + break; + } + } + } + } + + void AnimationController::applyBoneTransforms(Animation::KeyframeGroup *keyframeGroup){ + Bone *bone = keyframeGroup->bone; + Vector3 pos, scale; + Quaternion rot; + for(Animation::KeyframeGroup::Keyframe keyframe : keyframeGroup->keyframes){ + switch(keyframe.type){ + case Animation::KeyframeGroup::Keyframe::POS_X: + pos.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::POS_Y: + pos.y = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::POS_Z: + pos.z = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::ROT_W: + rot.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::ROT_X: + rot.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::ROT_Y: + rot.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::ROT_Z: + rot.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::SCALE_X: + scale.x = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::SCALE_Y: + scale.y = keyframe.value; + break; + case Animation::KeyframeGroup::Keyframe::SCALE_Z: + scale.z = keyframe.value; + break; + } + } + } + + Animation* AnimationController::getAnimation(string name){ + Animation *anim = nullptr; + for(Animation *a : animations) + if(a->getName() == name){ + anim = a; + break; + } + return anim; } } diff --git a/animationController.h b/animationController.h index 8d5e6c4..3f7ca8c 100644 --- a/animationController.h +++ b/animationController.h @@ -1,15 +1,28 @@ #ifndef ANIMATION_CONTROLLER_H #define ANIMATION_CONTROLLER_H -#include +#include +#include +#include "animation.h" namespace vb01{ + class Skeleton; + class AnimationChannel; + class AnimationController{ public: - AnimationController(); + AnimationController(Skeleton*); ~AnimationController(); void update(); + Animation* getAnimation(std::string); + inline void addAnimation(Animation *anim){animations.push_back(anim);} + inline void addAnimationChannel(AnimationChannel *channel){channels.push_back(channel);} private: + void applyBoneTransforms(Animation::KeyframeGroup*); + + Skeleton *skeleton = nullptr; + std::vector animations; + std::vector channels; protected: void onAnimationEnd(std::string){} void onAnimationStart(std::string){} diff --git a/skeleton.cpp b/skeleton.cpp index f03360f..0546149 100644 --- a/skeleton.cpp +++ b/skeleton.cpp @@ -1,5 +1,6 @@ #include"skeleton.h" #include"animation.h" +#include"animationController.h" #include"box.h" using namespace std; @@ -7,6 +8,7 @@ using namespace std; namespace vb01{ Skeleton::Skeleton(string name){ this->name=name; + controller = new AnimationController(this); } void Skeleton::update(){ @@ -31,13 +33,4 @@ namespace vb01{ return bone; } - Animation* Skeleton::getAnimation(string name){ - Animation *anim=nullptr; - for(Animation *a : animations) - if(a->getName()==name){ - anim=a; - break; - } - return anim; - } } diff --git a/skeleton.h b/skeleton.h index 37366db..9986ae2 100644 --- a/skeleton.h +++ b/skeleton.h @@ -7,6 +7,7 @@ namespace vb01{ class Animation; + class AnimationController; class Skeleton{ public: @@ -14,8 +15,7 @@ namespace vb01{ void update(); void addBone(Bone*,Bone*); Bone* getBone(std::string); - Animation* getAnimation(std::string); - inline void addAnimation(Animation *anim){animations.push_back(anim);} + inline AnimationController* getAnimationController(){return controller;} inline Bone* getBone(int i){return bones[i];} inline Bone* getRootBone(){return bones[0];} inline std::vector& getBones(){return bones;} @@ -24,7 +24,7 @@ namespace vb01{ private: std::string name; std::vector bones; - std::vector animations; + AnimationController *controller = nullptr; }; } diff --git a/vbModelReader.cpp b/vbModelReader.cpp index b38cf10..003b754 100644 --- a/vbModelReader.cpp +++ b/vbModelReader.cpp @@ -6,6 +6,7 @@ #include"bone.h" #include"model.h" #include"animation.h" +#include"animationController.h" #include #include @@ -137,13 +138,13 @@ namespace vb01{ if(preColon == "animationName"){ string postColon = l.substr(colonId + 2, string::npos); animName = postColon; - skeleton->addAnimation(new Animation(animName)); + skeleton->getAnimationController()->addAnimation(new Animation(animName)); continue; } Bone *b = skeleton->getBone(preColon); if(b){ animBone = b; - Animation *anim = skeleton->getAnimation(animName); + Animation *anim = skeleton->getAnimationController()->getAnimation(animName); Animation::KeyframeGroup *group = anim->getKeyframeGroup(animBone); if(!group){ Animation::KeyframeGroup kg; @@ -183,7 +184,7 @@ namespace vb01{ keyframe.interpolation = interp; keyframe.value = value; keyframe.frame = frame; - skeleton->getAnimation(animName)->getKeyframeGroup(animBone)->keyframes.push_back(keyframe); + skeleton->getAnimationController()->getAnimation(animName)->getKeyframeGroup(animBone)->keyframes.push_back(keyframe); } } }