new animation structure

remade animation controller
This commit is contained in:
devZoGok
2021-10-19 19:06:41 +03:00
parent 7f09723104
commit 46cd64db9e
11 changed files with 143 additions and 207 deletions
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+2 -4
View File
@@ -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
View File
@@ -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 &currentPos, Quaternion &currentRot, Vector3 &currentScale){
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){
+3 -3
View File
@@ -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){}
-1
View File
@@ -11,7 +11,6 @@
#include "shaderTest.h"
#include "particleEmitterTest.h"
#include "ikSolverTest.h"
#include "animationControllerTest.h"
using namespace CppUnit;
using namespace vb01;
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);