diff --git a/CMakeLists.txt b/CMakeLists.txt index 56549e9..286a67c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(render particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp model. set(model modelReader.cpp assimpModelReader.cpp vbModelReader.cpp) set(anim animationController.cpp animationChannel.cpp animation.cpp) set(armature skeleton.cpp bone.cpp ikSolver.cpp) -set(library ${render} ${math} ${model} ${utils} ${gui} ${armature} ${anim}) +set(library ${render} ${math} ${model} ${utils} ${gui} ${armature} ${assetManager} ${anim}) add_library(vb01 SHARED ${library}) target_link_libraries(vb01 glfw) @@ -29,7 +29,7 @@ target_link_libraries(vb01 freetype) set(renderTest nodeTest.cpp cameraTest.cpp shaderTest.cpp particleEmitterTest.cpp) set(armatureTest boneTest.cpp ikSolverTest.cpp) set(modelTest vbModelReaderTest.cpp) -set(animationTest animationControllerTest.cpp animationChannelTest.cpp) +set(animationTest animationChannelTest.cpp) set(test ${library} ${renderTest} ${armatureTest} ${modelTest} ${animationTest}) add_executable(vb01Tests main.cpp ${test}) diff --git a/animation.cpp b/animation.cpp index 6978860..7dbd593 100644 --- a/animation.cpp +++ b/animation.cpp @@ -13,16 +13,6 @@ namespace vb01{ void Animation::update(){ } - Animation::KeyframeGroup* Animation::getKeyframeGroup(Node *b){ - int id = -1; - for(int i = 0;i < keyframeGroups.size(); i++) - if(keyframeGroups[i].bone == b){ - id = i; - break; - } - return id > -1 ? &(keyframeGroups[id]) : nullptr; - } - KeyframeChannelType Animation::getKeyframeChannelType(string typeString){ KeyframeChannelType type; if(typeString == "pos_x") @@ -51,14 +41,22 @@ namespace vb01{ KeyframeChannel* Animation::getKeyframeChannel(Node *bone, KeyframeChannelType type){ KeyframeChannel *k = nullptr; - KeyframeGroup *group = getKeyframeGroup(bone); - for(KeyframeChannel &channel : group->keyframeChannels){ - if(channel.type == type){ + for(KeyframeChannel &channel : keyframeChannels) + if(channel.type == type && channel.bone == bone){ k = &channel; break; } - } return k; } + + vector Animation::getKeyframeChannelsByNode(Node *bone){ + vector channels; + + for(KeyframeChannel channel : keyframeChannels) + if(channel.bone == bone) + channels.push_back(channel); + + return channels; + } } diff --git a/animation.h b/animation.h index de60375..b55d045 100644 --- a/animation.h +++ b/animation.h @@ -10,56 +10,51 @@ namespace vb01{ class Animation{ public: - struct KeyframeGroup{ - struct KeyframeChannel{ - enum Type{ - POS_X, - POS_Y, - POS_Z, - ROT_W, - ROT_X, - ROT_Y, - ROT_Z, - SCALE_X, - SCALE_Y, - SCALE_Z - }; - struct Keyframe{ - enum Interpolation{CONSTANT, LINEAR, BEZIER}; + struct KeyframeChannel{ + enum Type{ + POS_X, + POS_Y, + POS_Z, + ROT_W, + ROT_X, + ROT_Y, + ROT_Z, + SCALE_X, + SCALE_Y, + SCALE_Z, + VALUE + }; + struct Keyframe{ + enum Interpolation{CONSTANT, LINEAR, BEZIER}; - float value; - int frame; - Interpolation interpolation; - }; - - Type type; - std::vector keyframes; + float value; + int frame; + Interpolation interpolation; }; + Type type; Node *bone = nullptr; - std::vector keyframeChannels; + std::vector keyframes; }; - Animation(std::string); ~Animation(); void update(); - KeyframeGroup* getKeyframeGroup(Node*); - KeyframeGroup::KeyframeChannel* getKeyframeChannel(Node*, KeyframeGroup::KeyframeChannel::Type); - static KeyframeGroup::KeyframeChannel::Type getKeyframeChannelType(std::string); - inline int getNumKeyframeGroups(){return keyframeGroups.size();} + static KeyframeChannel::Type getKeyframeChannelType(std::string); + KeyframeChannel* getKeyframeChannel(Node*, KeyframeChannel::Type); + std::vector getKeyframeChannelsByNode(Node*); + inline void addKeyframeChannel(KeyframeChannel channel){keyframeChannels.push_back(channel);} inline std::string getName(){return name;} - inline void addKeyframeGroup(KeyframeGroup k){keyframeGroups.push_back(k);} + inline const std::vector& getKeyframeChannels(){return keyframeChannels;} private: std::string name; - std::vector keyframeGroups; + std::vector keyframeChannels; }; - typedef Animation::KeyframeGroup KeyframeGroup; - typedef Animation::KeyframeGroup::KeyframeChannel KeyframeChannel; - typedef Animation::KeyframeGroup::KeyframeChannel::Type KeyframeChannelType; - typedef Animation::KeyframeGroup::KeyframeChannel::Keyframe Keyframe; - typedef Animation::KeyframeGroup::KeyframeChannel::Keyframe::Interpolation KeyframeInterpolation; + typedef Animation::KeyframeChannel KeyframeChannel; + typedef Animation::KeyframeChannel::Type KeyframeChannelType; + typedef Animation::KeyframeChannel::Keyframe Keyframe; + typedef Animation::KeyframeChannel::Keyframe::Interpolation KeyframeInterpolation; } #endif diff --git a/animationChannel.cpp b/animationChannel.cpp index c665b1d..17bb85c 100644 --- a/animationChannel.cpp +++ b/animationChannel.cpp @@ -35,31 +35,11 @@ namespace vb01{ vector keyframes; Animation *animation = controller->getAnimation(animName); - Node *controllerNode = controller->getNode(); - KeyframeGroup *startGroup = nullptr; - if(controllerNode){ - startGroup = animation->getKeyframeGroup(controllerNode); - - for(int j = 0 ; j < startGroup->keyframeChannels.size(); j++){ - KeyframeChannel ch = startGroup->keyframeChannels[j]; - - for(int k = 0; k < ch.keyframes.size(); k++) - keyframes.push_back(ch.keyframes[k]); - } - } - else{ - startGroup = animation->getKeyframeGroup((Node*)bones[0]); - for(int i = 0; i < bones.size(); i++){ - KeyframeGroup *kg = animation->getKeyframeGroup((Node*)bones[i]); - - for(int j = 0 ; j < kg->keyframeChannels.size(); j++){ - KeyframeChannel ch = kg->keyframeChannels[j]; - - for(int k = 0; k < ch.keyframes.size(); k++) - keyframes.push_back(ch.keyframes[k]); - } - } - } + const vector &keyframeChannels = animation->getKeyframeChannels(); + for(KeyframeChannel ch : keyframeChannels) + for(Keyframe k : ch.keyframes) + keyframes.push_back(k); + return keyframes; } diff --git a/animationChannelTest.cpp b/animationChannelTest.cpp index b26f561..67ec201 100644 --- a/animationChannelTest.cpp +++ b/animationChannelTest.cpp @@ -22,11 +22,9 @@ namespace vb01{ KeyframeChannel kc; kc.type = KeyframeChannel::Type::POS_X; kc.keyframes = vector({k1, k2}); - KeyframeGroup kg; - kg.bone = bone; - kg.keyframeChannels = vector({kc}); + kc.bone = bone; Animation *anim = new Animation("anim"); - anim->addKeyframeGroup(kg); + anim->addKeyframeChannel(kc); channel = new AnimationChannel(controller); controller->addAnimationChannel(channel); diff --git a/animationController.cpp b/animationController.cpp index 8223dbc..9c0d621 100644 --- a/animationController.cpp +++ b/animationController.cpp @@ -19,27 +19,41 @@ namespace vb01{ } } - void AnimationController::transform(AnimationChannel *channel){ - Animation *animation = getAnimation(channel->getAnimationName()); + Keyframe AnimationController::findKeyframe(AnimationChannel *channel, KeyframeChannel keyframeChannel, bool last){ + int pastKeyframeId = -1; + for(int i = 0; i < keyframeChannel.keyframes.size(); i++){ + Keyframe keyframe = keyframeChannel.keyframes[i]; + if(channel->getCurrentFrame() >= keyframe.frame){ + pastKeyframeId = i; + } + } + return keyframeChannel.keyframes[pastKeyframeId + (last ? 0 : 1)]; + } + void AnimationController::transform(AnimationChannel *channel){ vector transformNodes; if(node) transformNodes.push_back(node); for(Bone *channelBone : channel->getBones()) transformNodes.push_back((Node*)channelBone); + Animation *animation = getAnimation(channel->getAnimationName()); for(Node *transformNode : transformNodes){ - Animation::KeyframeGroup *keyframeGroup = animation->getKeyframeGroup(transformNode); - Vector3 pastPos, nextPos, pastScale, nextScale; - Quaternion pastRot, nextRot; - Keyframe::Interpolation interp; - float ratio; + Vector3 currentPos; + Quaternion currentRot; + Vector3 currentScale; + vector keyframeChannels = animation->getKeyframeChannelsByNode(transformNode); + for(KeyframeChannel keyframeChannel : keyframeChannels){ + Keyframe pastKeyframe = findKeyframe(channel, keyframeChannel, true); + Keyframe nextKeyframe = findKeyframe(channel, keyframeChannel, false); + int pastFrame = pastKeyframe.frame; + int nextFrame = nextKeyframe.frame; - prepareAdjacentValues(pastPos, nextPos, pastRot, nextRot, pastScale, nextScale, interp, ratio, keyframeGroup, channel); - - Vector3 currentPos = interpolate(pastPos, nextPos, interp, ratio); - Quaternion currentRot = interpolate(pastRot, nextRot, interp, ratio); - Vector3 currentScale = interpolate(pastScale, nextScale, interp, ratio); + Keyframe::Interpolation interp = pastKeyframe.interpolation; + float ratio = (float)(max(0, channel->getCurrentFrame() - pastFrame)) / (nextFrame - pastFrame); + float value = interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio); + setFrameValue(value, keyframeChannel.type, currentPos, currentRot, currentScale); + } if(node && node->getName() == transformNode->getName()){ transformNode->setPosition(currentPos); @@ -55,111 +69,57 @@ namespace vb01{ } } - void AnimationController::prepareAdjacentValues( - Vector3 &pastPos, - Vector3 &nextPos, - Quaternion &pastRot, - Quaternion &nextRot, - Vector3 &pastScale, - Vector3 &nextScale, - KeyframeInterpolation &interpMode, - float &ratio, - Animation::KeyframeGroup *keyframeGroup, - AnimationChannel *channel - ){ - - for(KeyframeChannel keyframeChannel : keyframeGroup->keyframeChannels){ - int pastKeyframeId = -1, nextKeyframeId = -1; - for(int i = 0; i < keyframeChannel.keyframes.size(); i++){ - Keyframe keyframe = keyframeChannel.keyframes[i]; - if(channel->getCurrentFrame() >= keyframe.frame){ - pastKeyframeId = i; - } - } - nextKeyframeId = pastKeyframeId + 1; - - Keyframe pastKeyframe = keyframeChannel.keyframes[pastKeyframeId]; - Keyframe nextKeyframe = keyframeChannel.keyframes[nextKeyframeId]; - int pastFrame = pastKeyframe.frame; - int nextFrame = nextKeyframe.frame; - ratio = (float)(max(0, channel->getCurrentFrame() - pastFrame)) / (nextFrame - pastFrame); - interpMode = pastKeyframe.interpolation; - - switch(keyframeChannel.type){ - case KeyframeChannel::POS_X: - pastPos.x = pastKeyframe.value; - nextPos.x = nextKeyframe.value; - break; - case KeyframeChannel::POS_Y: - pastPos.y = pastKeyframe.value; - nextPos.y = nextKeyframe.value; - break; - case KeyframeChannel::POS_Z: - pastPos.z = pastKeyframe.value; - nextPos.z = nextKeyframe.value; - break; - case KeyframeChannel::ROT_W: - pastRot.w = pastKeyframe.value; - nextRot.w = nextKeyframe.value; - break; - case KeyframeChannel::ROT_X: - pastRot.x = pastKeyframe.value; - nextRot.x = nextKeyframe.value; - break; - case KeyframeChannel::ROT_Y: - pastRot.y = pastKeyframe.value; - nextRot.y = nextKeyframe.value; - break; - case KeyframeChannel::ROT_Z: - pastRot.z = pastKeyframe.value; - nextRot.z = nextKeyframe.value; - break; - case KeyframeChannel::SCALE_X: - pastScale.x = pastKeyframe.value; - nextScale.x = nextKeyframe.value; - break; - case KeyframeChannel::SCALE_Y: - pastScale.y = pastKeyframe.value; - nextScale.y = nextKeyframe.value; - break; - case KeyframeChannel::SCALE_Z: - pastScale.z = pastKeyframe.value; - nextScale.z = nextKeyframe.value; - break; - } + void AnimationController::setFrameValue(float value, KeyframeChannelType type, Vector3 ¤tPos, Quaternion ¤tRot, Vector3 ¤tScale){ + switch(type){ + case KeyframeChannel::POS_X: + currentPos.x = value; + break; + case KeyframeChannel::POS_Y: + currentPos.y = value; + break; + case KeyframeChannel::POS_Z: + currentPos.z = value; + break; + case KeyframeChannel::ROT_W: + currentRot.w = value; + break; + case KeyframeChannel::ROT_X: + currentRot.x = value; + break; + case KeyframeChannel::ROT_Y: + currentRot.y = value; + break; + case KeyframeChannel::ROT_Z: + currentRot.z = value; + break; + case KeyframeChannel::SCALE_X: + currentScale.x = value; + break; + case KeyframeChannel::SCALE_Y: + currentScale.y = value; + break; + case KeyframeChannel::SCALE_Z: + currentScale.z = value; + break; + case KeyframeChannel::VALUE: + break; } } - Vector3 AnimationController::interpolate(Vector3 pastPos, Vector3 nextPos, Keyframe::Interpolation mode, float ratio){ - Vector3 currentPos; + float AnimationController::interpolate(float pastValue, float nextValue, Keyframe::Interpolation mode, float ratio){ + float currentValue; switch(mode){ case Keyframe::CONSTANT: - currentPos = pastPos; + currentValue = pastValue; break; case Keyframe::LINEAR: - currentPos = pastPos + (nextPos - pastPos) * ratio; + currentValue = pastValue + (nextValue - pastValue) * ratio; break; case Keyframe::BEZIER: - currentPos = pastPos + (nextPos - pastPos) * ratio; + currentValue = pastValue + (nextValue - pastValue) * ratio; break; } - return currentPos; - } - - Quaternion AnimationController::interpolate(Quaternion pastRot, Quaternion nextRot, Keyframe::Interpolation mode, float ratio){ - Quaternion currentRot; - switch(mode){ - case Keyframe::CONSTANT: - currentRot = pastRot; - break; - case Keyframe::LINEAR: - currentRot = pastRot + (nextRot - pastRot) * ratio; - break; - case Keyframe::BEZIER: - currentRot = pastRot + (nextRot - pastRot) * ratio; - break; - } - return currentRot; + return currentValue; } Animation* AnimationController::getAnimation(string name){ diff --git a/animationController.h b/animationController.h index 21b752c..9da7dc8 100644 --- a/animationController.h +++ b/animationController.h @@ -31,9 +31,9 @@ namespace vb01{ std::vector channels; void transform(AnimationChannel*); - void prepareAdjacentValues(Vector3&, Vector3&, Quaternion&, Quaternion&, Vector3&, Vector3&, Keyframe::Interpolation&, float&, KeyframeGroup*, AnimationChannel*); - Vector3 interpolate(Vector3, Vector3, Keyframe::Interpolation, float); - Quaternion interpolate(Quaternion, Quaternion, Keyframe::Interpolation, float); + void setFrameValue(float, KeyframeChannelType, Vector3&, Quaternion&, Vector3&); + Keyframe findKeyframe(AnimationChannel*, KeyframeChannel, bool); + float interpolate(float, float, Keyframe::Interpolation, float); protected: void onAnimationEnd(std::string){} void onAnimationStart(std::string){} diff --git a/main.cpp b/main.cpp index 4d474fc..24ad8ad 100755 --- a/main.cpp +++ b/main.cpp @@ -11,7 +11,6 @@ #include "shaderTest.h" #include "particleEmitterTest.h" #include "ikSolverTest.h" -#include "animationControllerTest.h" using namespace CppUnit; using namespace vb01; diff --git a/texture.vert b/texture.vert index 7b4c3d6..2a453f5 100755 --- a/texture.vert +++ b/texture.vert @@ -23,8 +23,8 @@ out vec2 texCoords; struct Bone{ float angle; - vec3 pos,trans,rotAxis,scale; - int vertGroup,parent; + vec3 pos, trans, rotAxis, scale; + int vertGroup, parent; }; uniform bool animated; diff --git a/vbModelReader.cpp b/vbModelReader.cpp index 6cf5c91..7960020 100644 --- a/vbModelReader.cpp +++ b/vbModelReader.cpp @@ -189,14 +189,12 @@ namespace vb01{ string dataLine[2]; getLineData(skeletonData[keyframeGroupStartLine], dataLine, 2); - KeyframeGroup keyframeGroup; string nodeName = dataLine[0]; Node *transformNode = nullptr; if(controller->getSkeleton()) transformNode = (Node*)controller->getSkeleton()->getBone(nodeName); if(!transformNode) transformNode = controller->getNode(); - keyframeGroup.bone = transformNode; int numKeyframeChannels = atoi(dataLine[1].c_str()); string channelData[2 * numKeyframeChannels]; @@ -211,6 +209,7 @@ namespace vb01{ keyframeChannel.type = Animation::getKeyframeChannelType(channelData[2 * k]); numTypeKeyframes[k] = atoi(channelData[2 * k + 1].c_str()); numKeyframes += numTypeKeyframes[k]; + keyframeChannel.bone = transformNode; keyframeChannels.push_back(keyframeChannel); } @@ -235,8 +234,9 @@ namespace vb01{ } } - keyframeGroup.keyframeChannels = keyframeChannels; - animation->addKeyframeGroup(keyframeGroup); + for(KeyframeChannel ch : keyframeChannels) + animation->addKeyframeChannel(ch); + keyframeGroupStartLine += numKeyframes + 1; } diff --git a/vbModelReaderTest.cpp b/vbModelReaderTest.cpp index 1c02651..d9a1444 100644 --- a/vbModelReaderTest.cpp +++ b/vbModelReaderTest.cpp @@ -82,9 +82,9 @@ namespace vb01{ skeletonData.push_back("animation: open"); skeletonData.push_back("groups: 1 "); skeletonData.push_back("opening 1 rot_w 2 rot_x 1"); - skeletonData.push_back("opening rot_w 1 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); - skeletonData.push_back("opening rot_w 0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); - skeletonData.push_back("opening rot_x 0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); + skeletonData.push_back("1 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); + skeletonData.push_back("0 10 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); + skeletonData.push_back("0 1 2 AUTO_CLAMPED 1 1 AUTO_CLAMPED 1 1 "); } void VbModelReaderTest::setupMesh(){ @@ -164,15 +164,21 @@ namespace vb01{ CPPUNIT_ASSERT(controller->getAnimation(animNames[1])); Animation *animation = controller->getAnimation(animNames[0]); - KeyframeGroup *leftBipodGroup = animation->getKeyframeGroup(skeleton->getBone("bipod.L")); - KeyframeGroup *rightBipodGroup = animation->getKeyframeGroup(skeleton->getBone("bipod.R")); - CPPUNIT_ASSERT(leftBipodGroup); - CPPUNIT_ASSERT(rightBipodGroup); - for(KeyframeChannel keyframeChannel : leftBipodGroup->keyframeChannels) + const vector &keyframeChannels = animation->getKeyframeChannels(); + vector leftBipodChannels, rightBipodChannels; + for(KeyframeChannel ch : keyframeChannels){ + if(ch.bone->getName() == "bipod.L") + leftBipodChannels.push_back(ch); + else if(ch.bone->getName() == "bipod.R") + rightBipodChannels.push_back(ch); + } + CPPUNIT_ASSERT(!leftBipodChannels.empty()); + CPPUNIT_ASSERT(!rightBipodChannels.empty()); + for(KeyframeChannel keyframeChannel : leftBipodChannels) CPPUNIT_ASSERT(keyframeChannel.keyframes.size() == 2); - for(KeyframeChannel keyframeChannel : rightBipodGroup->keyframeChannels) + for(KeyframeChannel keyframeChannel : rightBipodChannels) CPPUNIT_ASSERT(keyframeChannel.keyframes.size() == 2); - + Keyframe lastRightBipodKeyframe = animation->getKeyframeChannel(skeleton->getBone("bipod.R"), KeyframeChannelType::ROT_Y)->keyframes[1]; CPPUNIT_ASSERT(lastRightBipodKeyframe.value == 10); CPPUNIT_ASSERT(lastRightBipodKeyframe.frame == 10);