mirror of
https://github.com/ApfelTeeSaft/vb01.git
synced 2026-08-26 19:33:45 +00:00
new animation structure
remade animation controller
This commit is contained in:
+2
-2
@@ -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})
|
||||
|
||||
+12
-14
@@ -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<KeyframeChannel> Animation::getKeyframeChannelsByNode(Node *bone){
|
||||
vector<KeyframeChannel> channels;
|
||||
|
||||
for(KeyframeChannel channel : keyframeChannels)
|
||||
if(channel.bone == bone)
|
||||
channels.push_back(channel);
|
||||
|
||||
return channels;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-36
@@ -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<Keyframe> keyframes;
|
||||
float value;
|
||||
int frame;
|
||||
Interpolation interpolation;
|
||||
};
|
||||
|
||||
Type type;
|
||||
Node *bone = nullptr;
|
||||
std::vector<KeyframeChannel> keyframeChannels;
|
||||
std::vector<Keyframe> 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<KeyframeChannel> 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<KeyframeChannel>& getKeyframeChannels(){return keyframeChannels;}
|
||||
private:
|
||||
std::string name;
|
||||
std::vector<KeyframeGroup> keyframeGroups;
|
||||
std::vector<KeyframeChannel> 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
|
||||
|
||||
+5
-25
@@ -35,31 +35,11 @@ namespace vb01{
|
||||
vector<Keyframe> 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<KeyframeChannel> &keyframeChannels = animation->getKeyframeChannels();
|
||||
for(KeyframeChannel ch : keyframeChannels)
|
||||
for(Keyframe k : ch.keyframes)
|
||||
keyframes.push_back(k);
|
||||
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,9 @@ namespace vb01{
|
||||
KeyframeChannel kc;
|
||||
kc.type = KeyframeChannel::Type::POS_X;
|
||||
kc.keyframes = vector<Keyframe>({k1, k2});
|
||||
KeyframeGroup kg;
|
||||
kg.bone = bone;
|
||||
kg.keyframeChannels = vector<KeyframeChannel>({kc});
|
||||
kc.bone = bone;
|
||||
Animation *anim = new Animation("anim");
|
||||
anim->addKeyframeGroup(kg);
|
||||
anim->addKeyframeChannel(kc);
|
||||
|
||||
channel = new AnimationChannel(controller);
|
||||
controller->addAnimationChannel(channel);
|
||||
|
||||
+66
-106
@@ -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<Node*> 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<KeyframeChannel> 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){
|
||||
|
||||
@@ -31,9 +31,9 @@ namespace vb01{
|
||||
std::vector<AnimationChannel*> 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){}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "shaderTest.h"
|
||||
#include "particleEmitterTest.h"
|
||||
#include "ikSolverTest.h"
|
||||
#include "animationControllerTest.h"
|
||||
|
||||
using namespace CppUnit;
|
||||
using namespace vb01;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+4
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+16
-10
@@ -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<KeyframeChannel> &keyframeChannels = animation->getKeyframeChannels();
|
||||
vector<KeyframeChannel> 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);
|
||||
|
||||
Reference in New Issue
Block a user