mirror of
https://github.com/devZoGok/vb01.git
synced 2026-08-26 19:43:30 +00:00
animation classes refactoring
This commit is contained in:
+5
-5
@@ -14,12 +14,12 @@ namespace vb01{
|
||||
}
|
||||
|
||||
Animation::KeyframeGroup* Animation::getKeyframeGroup(Bone *b){
|
||||
int id=-1;
|
||||
for(int i=0;i<keyframeGroups.size();i++)
|
||||
if(keyframeGroups[i].bone==b){
|
||||
id=i;
|
||||
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;
|
||||
return id > -1 ? &(keyframeGroups[id]) : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-9
@@ -29,14 +29,18 @@ namespace vb01{
|
||||
|
||||
void AnimationChannel::setAnimationName(string animName){
|
||||
this->animationName = animName;
|
||||
numFrames = getMaxKeyframeNum(animName);
|
||||
}
|
||||
|
||||
int AnimationChannel::getMaxKeyframeNum(string animName){
|
||||
int maxKeyframeNum;
|
||||
|
||||
Animation *animation = controller->getAnimation(animName);
|
||||
KeyframeGroup *startGroup = animation->getKeyframeGroup(bones[0]);
|
||||
int numStartKeyframes = startGroup->keyframeChannels[0].keyframes.size();
|
||||
numFrames = startGroup->keyframeChannels[0].keyframes[numStartKeyframes - 1].frame;
|
||||
//firstFrame = startGroup->keyframeChannels[0].keyframes[0].frame;
|
||||
maxKeyframeNum = startGroup->keyframeChannels[0].keyframes[numStartKeyframes - 1].frame;
|
||||
|
||||
for(int i = 0; i < bones.size() ; i++){
|
||||
for(int i = 0; i < bones.size(); i++){
|
||||
KeyframeGroup *kg = animation->getKeyframeGroup(bones[i]);
|
||||
|
||||
for(int j = 0 ; j < kg->keyframeChannels.size(); j++){
|
||||
@@ -45,16 +49,13 @@ namespace vb01{
|
||||
for(int k = 0; k < ch.keyframes.size(); k++){
|
||||
int numKeyframes = ch.keyframes.size();
|
||||
int maxFrame = ch.keyframes[numKeyframes - 1].frame;
|
||||
int minFrame = ch.keyframes[0].frame;
|
||||
|
||||
if(numFrames < maxFrame)
|
||||
numFrames = maxFrame;
|
||||
/*
|
||||
if(firstFrame > minFrame)
|
||||
firstFrame = minFrame;
|
||||
*/
|
||||
maxKeyframeNum = maxFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxKeyframeNum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace vb01{
|
||||
inline std::string getAnimationName(){return animationName;}
|
||||
private:
|
||||
inline bool canUpdate(){return getTime() - lastUpdateTime > updateRate;}
|
||||
int getMaxKeyframeNum(std::string);
|
||||
|
||||
s64 lastUpdateTime = 0;
|
||||
int updateRate = 16;
|
||||
|
||||
+134
-90
@@ -16,99 +16,143 @@ namespace vb01{
|
||||
for(AnimationChannel *channel : channels){
|
||||
channel->update();
|
||||
|
||||
Animation *animation = skeleton->getAnimationController()->getAnimation(channel->getAnimationName());
|
||||
for(Bone *channelBone : channel->getBones()){
|
||||
Animation::KeyframeGroup *keyframeGroup = animation->getKeyframeGroup(channelBone);
|
||||
int pastKeyframeId = -1;
|
||||
|
||||
Vector3 pastPos, currentPos, nextPos, pastScale, currentScale, nextScale;
|
||||
Quaternion pastRot, currentRot, nextRot;
|
||||
|
||||
for(KeyframeChannel animChannel : keyframeGroup->keyframeChannels){
|
||||
for(int i = 0 ; i < animChannel.keyframes.size(); i++){
|
||||
Keyframe keyframe = animChannel.keyframes[i];
|
||||
if(channel->getCurrentFrame() >= keyframe.frame){
|
||||
pastKeyframeId = i;
|
||||
}
|
||||
}
|
||||
|
||||
Keyframe pastKeyframe = animChannel.keyframes[pastKeyframeId];
|
||||
Keyframe nextKeyframe = animChannel.keyframes[pastKeyframeId + 1];
|
||||
int pastFrame = pastKeyframe.frame;
|
||||
int nextFrame = nextKeyframe.frame;
|
||||
float ratio = (float)(channel->getCurrentFrame() - pastFrame) / (nextFrame - pastFrame);
|
||||
|
||||
switch(animChannel.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;
|
||||
}
|
||||
|
||||
switch(pastKeyframe.interpolation){
|
||||
case Keyframe::CONSTANT:
|
||||
currentPos = pastPos;
|
||||
currentRot = pastRot;
|
||||
currentScale = pastScale;
|
||||
break;
|
||||
case Keyframe::LINEAR:
|
||||
currentPos = pastPos + (nextPos - pastPos) * ratio;
|
||||
currentRot = pastRot + (nextRot - pastRot) * ratio;
|
||||
currentScale = pastScale + (nextScale - pastScale) * ratio;
|
||||
break;
|
||||
case Keyframe::BEZIER:
|
||||
currentPos = pastPos + (nextPos - pastPos) * ratio;
|
||||
currentRot = pastRot + (nextRot - pastRot) * ratio;
|
||||
currentScale = pastScale + (nextScale - pastScale) * ratio;
|
||||
break;
|
||||
}
|
||||
}
|
||||
swap(currentRot.y, currentRot.z);
|
||||
currentRot.z = -currentRot.z;
|
||||
|
||||
channelBone->setPosePos(currentPos);
|
||||
channelBone->setPoseRot(currentRot);
|
||||
//channelBone->setPoseScale(currentScale);
|
||||
}
|
||||
transformBones(channel);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationController::transformBones(AnimationChannel *channel){
|
||||
Animation *animation = getAnimation(channel->getAnimationName());
|
||||
|
||||
for(Bone *channelBone : channel->getBones()){
|
||||
Animation::KeyframeGroup *keyframeGroup = animation->getKeyframeGroup(channelBone);
|
||||
Vector3 pastPos, nextPos, pastScale, nextScale;
|
||||
Quaternion pastRot, nextRot;
|
||||
Keyframe::Interpolation interp;
|
||||
float ratio;
|
||||
|
||||
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);
|
||||
/*
|
||||
swap(currentRot.y, currentRot.z);
|
||||
currentRot.z = -currentRot.z;
|
||||
|
||||
//channelBone->setPoseScale(currentScale);
|
||||
*/
|
||||
channelBone->setPosePos(currentPos);
|
||||
channelBone->setPoseRot(currentRot);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationController::prepareAdjacentValues(
|
||||
Vector3 &pastPos,
|
||||
Vector3 &nextPos,
|
||||
Quaternion &pastRot,
|
||||
Quaternion &nextRot,
|
||||
Vector3 &pastScale,
|
||||
Vector3 &nextScale,
|
||||
KeyframeInterpolation &interpMode,
|
||||
float &ratio,
|
||||
Animation::KeyframeGroup *keyframeGroup,
|
||||
AnimationChannel *channel
|
||||
){
|
||||
|
||||
int pastKeyframeId = -1;
|
||||
for(KeyframeChannel animChannel : keyframeGroup->keyframeChannels){
|
||||
for(int i = 0 ; i < animChannel.keyframes.size(); i++){
|
||||
Keyframe keyframe = animChannel.keyframes[i];
|
||||
if(channel->getCurrentFrame() >= keyframe.frame){
|
||||
pastKeyframeId = i;
|
||||
}
|
||||
}
|
||||
|
||||
Keyframe pastKeyframe = animChannel.keyframes[pastKeyframeId];
|
||||
Keyframe nextKeyframe = animChannel.keyframes[pastKeyframeId + 1];
|
||||
int pastFrame = pastKeyframe.frame;
|
||||
int nextFrame = nextKeyframe.frame;
|
||||
ratio = (float)(channel->getCurrentFrame() - pastFrame) / (nextFrame - pastFrame);
|
||||
interpMode = pastKeyframe.interpolation;
|
||||
|
||||
switch(animChannel.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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 AnimationController::interpolate(Vector3 pastPos, Vector3 nextPos, Keyframe::Interpolation mode, float ratio){
|
||||
Vector3 currentPos;
|
||||
switch(mode){
|
||||
case Keyframe::CONSTANT:
|
||||
currentPos = pastPos;
|
||||
break;
|
||||
case Keyframe::LINEAR:
|
||||
currentPos = pastPos + (nextPos - pastPos) * ratio;
|
||||
break;
|
||||
case Keyframe::BEZIER:
|
||||
currentPos = pastPos + (nextPos - pastPos) * 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;
|
||||
}
|
||||
|
||||
Animation* AnimationController::getAnimation(string name){
|
||||
Animation *anim = nullptr;
|
||||
for(Animation *a : animations)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
namespace vb01{
|
||||
class Skeleton;
|
||||
class AnimationChannel;
|
||||
class Vector3;
|
||||
class Quaternion;
|
||||
|
||||
class AnimationController{
|
||||
public:
|
||||
@@ -21,6 +23,11 @@ namespace vb01{
|
||||
Skeleton *skeleton = nullptr;
|
||||
std::vector<Animation*> animations;
|
||||
std::vector<AnimationChannel*> channels;
|
||||
|
||||
void transformBones(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);
|
||||
protected:
|
||||
void onAnimationEnd(std::string){}
|
||||
void onAnimationStart(std::string){}
|
||||
|
||||
Reference in New Issue
Block a user