first animatable object interface iteration

This commit is contained in:
devZoGok
2021-10-19 19:06:41 +03:00
parent 2ae7f2efdd
commit 53bf4f41bd
19 changed files with 174 additions and 139 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ set(utils util.cpp)
set(math quaternion.cpp vector.cpp matrix.cpp ray.cpp)
set(render 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 animationController.cpp animationChannel.cpp animation.cpp)
set(anim animationController.cpp animationChannel.cpp animation.cpp animatable.cpp)
set(armature skeleton.cpp bone.cpp ikSolver.cpp)
set(library ${render} ${math} ${model} ${utils} ${gui} ${armature} ${assetManager} ${anim})
+13
View File
@@ -0,0 +1,13 @@
#include "animatable.h"
#include "animationController.h"
namespace vb01{
Animatable::Animatable(AnimationController *controller){
this->animationController = controller;
}
void Animatable::update(){
if(animationController)
animationController->update();
}
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef ANIMATABLE_H
#define ANIMATABLE_H
#include "animation.h"
namespace vb01{
class AnimationController;
class Animatable{
public:
enum Type{NODE, BONE};
Animatable(AnimationController*);
void update();
virtual void animate(float, KeyframeChannel){}
inline AnimationController *getAnimationController(){return animationController;}
inline Type getType(){return type;}
private:
AnimationController *animationController = nullptr;
protected:
Type type;
};
}
#endif
+4 -4
View File
@@ -38,11 +38,11 @@ namespace vb01{
return type;
}
KeyframeChannel* Animation::getKeyframeChannel(Node *bone, KeyframeChannelType type){
KeyframeChannel* Animation::getKeyframeChannel(Animatable *animatable, KeyframeChannelType type){
KeyframeChannel *k = nullptr;
for(KeyframeChannel &channel : keyframeChannels)
if(channel.type == type && channel.bone == bone){
if(channel.type == type && channel.animatable == animatable){
k = &channel;
break;
}
@@ -50,11 +50,11 @@ namespace vb01{
return k;
}
vector<KeyframeChannel> Animation::getKeyframeChannelsByNode(Node *bone){
vector<KeyframeChannel> Animation::getKeyframeChannelsByAnimatable(Animatable *animatable){
vector<KeyframeChannel> channels;
for(KeyframeChannel channel : keyframeChannels)
if(channel.bone == bone)
if(channel.animatable == animatable)
channels.push_back(channel);
return channels;
+4 -5
View File
@@ -5,8 +5,7 @@
#include <vector>
namespace vb01{
class Bone;
class Node;
class Animatable;
class Animation{
public:
@@ -33,7 +32,7 @@ namespace vb01{
};
Type type;
Node *bone = nullptr;
Animatable *animatable = nullptr;
std::vector<Keyframe> keyframes;
};
@@ -41,8 +40,8 @@ namespace vb01{
~Animation();
void update();
static KeyframeChannel::Type getKeyframeChannelType(std::string);
KeyframeChannel* getKeyframeChannel(Node*, KeyframeChannel::Type);
std::vector<KeyframeChannel> getKeyframeChannelsByNode(Node*);
KeyframeChannel* getKeyframeChannel(Animatable*, KeyframeChannel::Type);
std::vector<KeyframeChannel> getKeyframeChannelsByAnimatable(Animatable*);
inline void addKeyframeChannel(KeyframeChannel channel){keyframeChannels.push_back(channel);}
inline std::string getName(){return name;}
inline const std::vector<KeyframeChannel>& getKeyframeChannels(){return keyframeChannels;}
+4 -4
View File
@@ -17,9 +17,9 @@ namespace vb01{
~AnimationChannel();
void update();
void setAnimationName(std::string name);
inline std::vector<Bone*> getBones(){return bones;}
inline void addBone(Bone *bone){bones.push_back(bone);}
inline void removeAllBones(){bones.clear();}
inline std::vector<Animatable*> getAnimatables(){return animatables;}
inline void addAnimatable(Animatable *animatable){animatables.push_back(animatable);}
inline void removeAllBones(){animatables.clear();}
inline void setUpdateRate(float updateRate){this->updateRate = updateRate;}
inline int getUpdateRate(){return updateRate;}
inline int getFirstFrame(){return firstFrame;}
@@ -43,7 +43,7 @@ namespace vb01{
int firstFrame = 0, currentFrame = 1, numFrames = 0;
bool loop = false, forward = true;
std::string animationName;
std::vector<Bone*> bones;
std::vector<Animatable*> animatables;
friend class AnimationChannelTest;
friend class AnimationControllerTest;
+2 -2
View File
@@ -22,14 +22,14 @@ namespace vb01{
KeyframeChannel kc;
kc.type = KeyframeChannel::Type::POS_X;
kc.keyframes = vector<Keyframe>({k1, k2});
kc.bone = bone;
kc.animatable = bone;
Animation *anim = new Animation("anim");
anim->addKeyframeChannel(kc);
channel = new AnimationChannel(controller);
controller->addAnimationChannel(channel);
controller->addAnimation(anim);
channel->addBone(bone);
channel->addAnimatable(bone);
channel->setAnimationName("anim");
}
+4 -76
View File
@@ -31,91 +31,19 @@ namespace vb01{
}
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){
Vector3 currentPos;
Quaternion currentRot;
Vector3 currentScale;
bool objectNode = node && node->getName() == transformNode->getName();
if(objectNode){
currentPos = transformNode->getPosition();
currentRot = transformNode->getOrientation();
currentScale = transformNode->getScale();
}
else{
Bone *channelBone = (Bone*)transformNode;
currentPos = channelBone->getPosePos();
currentRot = channelBone->getPoseRot();
currentScale = channelBone->getPoseScale();
}
vector<KeyframeChannel> keyframeChannels = animation->getKeyframeChannelsByNode(transformNode);
for(Animatable *animatable : channel->getAnimatables()){
vector<KeyframeChannel> keyframeChannels = animation->getKeyframeChannelsByAnimatable(animatable);
for(KeyframeChannel keyframeChannel : keyframeChannels){
Keyframe pastKeyframe = findKeyframe(channel, keyframeChannel, true);
Keyframe nextKeyframe = findKeyframe(channel, keyframeChannel, false);
int pastFrame = pastKeyframe.frame;
int nextFrame = nextKeyframe.frame;
Keyframe::Interpolation interp = pastKeyframe.interpolation;
float ratio = (float)(max(0, channel->getCurrentFrame() - pastFrame)) / (nextFrame - pastFrame);
Keyframe::Interpolation interp = pastKeyframe.interpolation;
float value = interpolate(pastKeyframe.value, nextKeyframe.value, interp, ratio);
setFrameValue(value, keyframeChannel.type, currentPos, currentRot, currentScale);
animatable->animate(value, keyframeChannel);
}
if(objectNode){
transformNode->setPosition(currentPos);
transformNode->setOrientation(currentRot);
transformNode->setScale(currentScale);
}
else{
Bone *channelBone = (Bone*)transformNode;
channelBone->setPosePos(currentPos);
channelBone->setPoseRot(currentRot);
channelBone->setPoseScale(currentScale);
}
}
}
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;
}
}
+1 -7
View File
@@ -10,6 +10,7 @@ namespace vb01{
class AnimationChannel;
class Vector3;
class Quaternion;
class Animatable;
class AnimationController{
public:
@@ -20,18 +21,11 @@ namespace vb01{
inline std::vector<Animation*> getAnimations(){return animations;}
inline void addAnimation(Animation *anim){animations.push_back(anim);}
inline void addAnimationChannel(AnimationChannel *channel){channels.push_back(channel);}
inline void setSkeleton(Skeleton *sk){this->skeleton = sk;}
inline void setNode(Node *node){this->node = node;}
inline Skeleton* getSkeleton(){return skeleton;}
inline Node* getNode(){return node;}
private:
Skeleton *skeleton = nullptr;
Node *node = nullptr;
std::vector<Animation*> animations;
std::vector<AnimationChannel*> channels;
void transform(AnimationChannel*);
void setFrameValue(float, KeyframeChannelType, Vector3&, Quaternion&, Vector3&);
Keyframe findKeyframe(AnimationChannel*, KeyframeChannel, bool);
float interpolate(float, float, Keyframe::Interpolation, float);
protected:
+41
View File
@@ -7,6 +7,7 @@ namespace vb01{
Bone::Bone(string name, float length, Vector3 pos, Quaternion rot, Vector3 scale) : Node(pos, rot, scale, name){
this->name = name;
this->length = length;
Animatable::type = Animatable::BONE;
}
void Bone::lookAt(Vector3 newDir, Vector3 newUp){
@@ -77,4 +78,44 @@ namespace vb01{
this->poseScale = s;
//setScale(restScale+poseScale);
}
void Bone::animate(float value, KeyframeChannel keyframeChannel){
Vector3 newPos = getPosePos(), newScale = getPoseScale();
Quaternion newRot = getPoseRot();
switch(keyframeChannel.type){
case KeyframeChannel::POS_X:
newPos.x = value;
break;
case KeyframeChannel::POS_Y:
newPos.y = value;
break;
case KeyframeChannel::POS_Z:
newPos.z = value;
break;
case KeyframeChannel::ROT_W:
newRot.w = value;
break;
case KeyframeChannel::ROT_X:
newRot.x = value;
break;
case KeyframeChannel::ROT_Y:
newRot.y = value;
break;
case KeyframeChannel::ROT_Z:
newRot.z = value;
break;
case KeyframeChannel::SCALE_X:
newScale.x = value;
break;
case KeyframeChannel::SCALE_Y:
newScale.y = value;
break;
case KeyframeChannel::SCALE_Z:
newScale.z = value;
break;
}
setPosePos(newPos);
setPoseRot(newRot);
setPoseScale(newScale);
}
}
+3 -2
View File
@@ -1,8 +1,8 @@
#ifndef BONE_H
#define BONE_H
#include"node.h"
#include<string>
#include "node.h"
#include <string>
namespace vb01{
class Skeleton;
@@ -34,6 +34,7 @@ namespace vb01{
inline Vector3 getPoseScale(){return poseScale;}
private:
void updateBoneInfo();
void animate(float, KeyframeChannel);
float length;
Bone *ikTarget = nullptr;
+2 -2
View File
@@ -24,7 +24,7 @@ namespace vb01{
Vector3 shapeKeyOffsets[100];
};
Mesh(Vertex*, unsigned int*, int, std::string *vg = nullptr, int = 0, std::string *sk = nullptr, int = 0, std::string = "");
Mesh(Vertex*, u32*, int, std::string *vg = nullptr, int = 0, std::string *sk = nullptr, int = 0, std::string = "");
~Mesh();
void construct();
virtual void update();
@@ -45,7 +45,7 @@ namespace vb01{
inline Skeleton* getSkeleton(){return skeleton;}
inline std::string* getVertexGroups(){return vertexGroups;}
inline int getNumVertexGroups(){return numVertexGroups;}
inline unsigned int* getIndices(){return indices;}
inline u32* getIndices(){return indices;}
private:
void initMesh();
void initFramebuffer();
+43 -6
View File
@@ -15,14 +15,12 @@ using namespace std;
using namespace glm;
namespace vb01{
Node::Node(Vector3 pos, Quaternion orientation, Vector3 scale, string name, AnimationController *controller){
Node::Node(Vector3 pos, Quaternion orientation, Vector3 scale, string name, AnimationController *controller) : Animatable(controller){
this->pos = pos;
this->scale = scale;
this->orientation = orientation;
this->name = name;
this->controller = controller;
if(this->controller)
this->controller->setNode(this);
Animatable::type = Animatable::NODE;
globalAxis[0] = Vector3::VEC_I;
globalAxis[1] = Vector3::VEC_J;
@@ -56,8 +54,7 @@ namespace vb01{
c->update();
for(ParticleEmitter *p : emitters)
p->update();
if(controller)
controller->update();
Animatable::update();
}
}
@@ -312,4 +309,44 @@ namespace vb01{
this->orientation = q;
updateAxis();
}
void Node::animate(float value, KeyframeChannel keyframeChannel){
Vector3 newPos = pos, newScale = scale;
Quaternion newRot = orientation;
switch(keyframeChannel.type){
case KeyframeChannel::POS_X:
newPos.x = value;
break;
case KeyframeChannel::POS_Y:
newPos.y = value;
break;
case KeyframeChannel::POS_Z:
newPos.z = value;
break;
case KeyframeChannel::ROT_W:
newRot.w = value;
break;
case KeyframeChannel::ROT_X:
newRot.x = value;
break;
case KeyframeChannel::ROT_Y:
newRot.y = value;
break;
case KeyframeChannel::ROT_Z:
newRot.z = value;
break;
case KeyframeChannel::SCALE_X:
newScale.x = value;
break;
case KeyframeChannel::SCALE_Y:
newScale.y = value;
break;
case KeyframeChannel::SCALE_Z:
newScale.z = value;
break;
}
setPosition(newPos);
setOrientation(newRot);
setScale(newScale);
}
}
+6 -5
View File
@@ -4,6 +4,7 @@
#include "quaternion.h"
#include "vector.h"
#include "root.h"
#include "animatable.h"
#include <vector>
#include <string>
@@ -16,7 +17,7 @@ namespace vb01{
class Text;
class AnimationController;
class Node{
class Node : public Animatable{
public:
struct Transform{
Vector3 position = Vector3::VEC_ZERO, scale = Vector3::VEC_IJK;
@@ -65,14 +66,14 @@ namespace vb01{
inline bool isVisible(){return visible;}
inline std::string getName(){return name;}
inline void setVisible(bool v){this->visible = v;}
inline AnimationController* getAnimationController(){return controller;}
private:
void adjustUp(Vector3);
void adjustDir(Vector3);
Quaternion adjustRot(std::vector<Node*>, Quaternion, bool);
AnimationController *controller = nullptr;
protected:
void updateShaders();
Quaternion adjustRot(std::vector<Node*>, Quaternion, bool);
protected:
virtual void animate(float, KeyframeChannel);
bool visible = true;
Vector3 pos, scale, globalAxis[3];
-1
View File
@@ -13,7 +13,6 @@ namespace vb01{
Skeleton::Skeleton(AnimationController *controller, string name){
this->name = name;
this->controller = controller;
this->controller->setSkeleton(this);
}
void Skeleton::update(){
+3 -3
View File
@@ -1,9 +1,9 @@
#ifndef SKELETON_H
#define SKELETON_H
#include<vector>
#include<string>
#include"bone.h"
#include <vector>
#include <string>
#include "bone.h"
namespace vb01{
class Animation;
+13 -18
View File
@@ -150,8 +150,6 @@ namespace vb01{
yAxis.z = -yAxis.z;
swap(zAxis.y, zAxis.z);
zAxis.z = -zAxis.z;
/*
*/
}
else
pos = pos + Vector3(0, ((Bone*)parent)->getLength(), 0);
@@ -172,33 +170,27 @@ namespace vb01{
}
}
void VbModelReader::readAnimations(AnimationController *controller, vector<string> &skeletonData, int numAnimations){
void VbModelReader::readAnimations(Animatable *animatable, vector<string> &animationData, int numAnimations){
int animStartLine = 0;
for(int i = 0; i < numAnimations; i++){
string animLine = skeletonData[animStartLine];
string animLine = animationData[animStartLine];
currentAnim = animLine.substr(animLine.find_first_of(':') + 2);
string groupsLine = skeletonData[animStartLine + 1];
string groupsLine = animationData[animStartLine + 1];
Animation *animation = new Animation(currentAnim);
AnimationController *controller = (animatable ? animatable->getAnimationController() : currentSkeleton->getAnimationController());
controller->addAnimation(animation);
int numKeyframeGroups = atoi(groupsLine.substr(groupsLine.find_first_of(':') + 2).c_str());
int keyframeGroupStartLine = animStartLine + 2;
for(int j = 0; j < numKeyframeGroups; j++){
string dataLine[2];
getLineData(skeletonData[keyframeGroupStartLine], dataLine, 2);
string nodeName = dataLine[0];
Node *transformNode = nullptr;
if(controller->getSkeleton())
transformNode = (Node*)controller->getSkeleton()->getBone(nodeName);
if(!transformNode)
transformNode = controller->getNode();
getLineData(animationData[keyframeGroupStartLine], dataLine, 2);
int numKeyframeChannels = atoi(dataLine[1].c_str());
string channelData[2 * numKeyframeChannels];
getLineData(skeletonData[keyframeGroupStartLine], channelData, 2 * numKeyframeChannels, 2);
getLineData(animationData[keyframeGroupStartLine], channelData, 2 * numKeyframeChannels, 2);
vector<KeyframeChannel> keyframeChannels;
int numTypeKeyframes[numKeyframeChannels];
@@ -209,7 +201,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;
keyframeChannel.animatable = (animatable ? animatable : currentSkeleton->getBone(dataLine[0]));
keyframeChannels.push_back(keyframeChannel);
}
@@ -217,7 +209,7 @@ namespace vb01{
int keyframeStartLine = keyframeGroupStartLine + 1;
int currentChannel = 0, numCurrentTypeKeyframes = 0;
for(int k = 0; k < numKeyframes; k++){
string keyframeLine = skeletonData[keyframeStartLine + k];
string keyframeLine = animationData[keyframeStartLine + k];
string keyframeData[9];
getLineData(keyframeLine, keyframeData, 9);
@@ -258,15 +250,18 @@ namespace vb01{
AnimationController *controller = new AnimationController();
Skeleton *skeleton = new Skeleton(controller, name);
currentSkeleton = skeleton;
vector<string> skeletonSubData = vector<string>(skeletonData.begin() + boneStartLine, skeletonData.begin() + boneStartLine + numBones);
createBones(skeleton, skeletonSubData);
skeletonSubData.clear();
skeletonSubData = vector<string>(skeletonData.begin() + (boneStartLine + numBones + 1), skeletonData.end());
readAnimations(controller, skeletonSubData, numAnimations);
readAnimations(nullptr, skeletonSubData, numAnimations);
skeletonSubData.clear();
currentSkeleton = nullptr;
return skeleton;
}
@@ -441,7 +436,7 @@ namespace vb01{
int numAnimLineId = shapeKeyStartLine + numShapes * (1 + numVertices);
int numAnimations = atoi(meshData[numAnimLineId].substr(meshData[numAnimLineId].find_first_of(':') + 1).c_str());
meshSubData = vector<string>(meshData.begin() + (numAnimLineId + 1), meshData.end());
readAnimations(controller, meshSubData, numAnimations);
readAnimations(node, meshSubData, numAnimations);
meshSubData.clear();
string skeletonLine = meshData[5];
+2 -1
View File
@@ -25,7 +25,7 @@ namespace vb01{
void connectNodes();
void createBones(Skeleton*, std::vector<std::string>&);
void readAnimations(AnimationController*, std::vector<std::string>&, int);
void readAnimations(Animatable*, std::vector<std::string>&, int);
Skeleton* readSkeleton(std::vector<std::string>&);
void readVertices(std::vector<Vector3>&, std::vector<Vector3>&, std::vector<float>&, std::vector<std::string>&, int);
void readFaces(std::vector<Vector3>&, std::vector<Vector3>&, std::vector<u32>&, std::vector<float>&, std::vector<std::string>&, int, Mesh::Vertex*, u32*);
@@ -36,6 +36,7 @@ namespace vb01{
void readLights(std::vector<std::string>&);
std::map<std::string, std::string> relationships;
Skeleton *currentSkeleton = nullptr;
std::vector<Skeleton*> skeletons;
std::vector<Mesh*> meshes;
std::vector<Node*> nodes;
+3 -2
View File
@@ -167,9 +167,10 @@ namespace vb01{
const vector<KeyframeChannel> &keyframeChannels = animation->getKeyframeChannels();
vector<KeyframeChannel> leftBipodChannels, rightBipodChannels;
for(KeyframeChannel ch : keyframeChannels){
if(ch.bone->getName() == "bipod.L")
vb01::Bone *bone = (vb01::Bone*)ch.animatable;
if(bone->getName() == "bipod.L")
leftBipodChannels.push_back(ch);
else if(ch.bone->getName() == "bipod.R")
else if(bone->getName() == "bipod.R")
rightBipodChannels.push_back(ch);
}
CPPUNIT_ASSERT(!leftBipodChannels.empty());