Files
vb01/bone.cpp
T
2022-03-11 07:57:01 +02:00

164 lines
3.9 KiB
C++

#include "bone.h"
#include "skeleton.h"
using namespace std;
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;
}
void Bone::lookAt(Vector3 newDir, Vector3 newUp){
Node::lookAt(newDir, newUp);
updateBoneInfo();
}
void Bone::updateBoneInfo(){
for(int i = 0; i < 3; i++)
this->initAxis[i] = globalAxis[i];
restPos = pos;
restRot = orientation;
restScale = scale;
}
void Bone::onAttached(){
Node::onAttached();
updateBoneInfo();
}
Vector3 Bone::getBoneSpaceRestPos(Bone *bone){
Bone *rootBone = skeleton->getRootBone();
Vector3 modelSpacePos = Vector3::VEC_ZERO;
vector<Node*> boneHierarchy = getAncestors(bone);
while(!boneHierarchy.empty()){
int id = boneHierarchy.size() - 1;
Bone *curBone = ((Bone*)boneHierarchy[id]);
Bone *par = (Bone*)curBone->getParent();
Vector3 axis[]{
curBone != rootBone? par->getInitAxis(0) : Vector3::VEC_I,
curBone != rootBone? par->getInitAxis(1) : Vector3::VEC_J,
curBone != rootBone? par->getInitAxis(2) : Vector3::VEC_K
};
Vector3 rPos = (curBone == bone ? Vector3::VEC_ZERO : curBone->getRestPos());
modelSpacePos = modelSpacePos + axis[0] * rPos.x + axis[1] * rPos.y + axis[2] * rPos.z;
boneHierarchy.pop_back();
}
return modelSpacePos;
}
Vector3 Bone::getModelSpacePos(){
Node *modelNode = skeleton->getRootBone()->getParent();
Vector3 modelSpacePos = modelNode->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_ZERO));
return modelSpacePos;
}
void Bone::setPosePos(Vector3 p){
this->posePos = p;
setPosition(restPos);
Vector3 parentSpacePosePos = parent->globalToLocalPosition(localToGlobalPosition(p));
setPosition(parentSpacePosePos);
}
void Bone::setPoseRot(Quaternion r){
this->poseRot = r;
Vector3 rotAxis = r.getAxis();
rotAxis =
parent->globalToLocalPosition(localToGlobalPosition(rotAxis)) -
parent->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_ZERO));
Quaternion parentSpacePoseRot = Quaternion(r.getAngle(), rotAxis);
setOrientation(parentSpacePoseRot * restRot);
}
void Bone::setPoseScale(Vector3 s){
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);
}
float Bone::getDriverValue(Driver::VariableType type){
float driverValue;
switch(type){
case Driver::POS_X:
driverValue = posePos.x;
break;
case Driver::POS_Y:
driverValue = posePos.y;
break;
case Driver::POS_Z:
driverValue = posePos.z;
break;
case Driver::ROT_W:
driverValue = poseRot.w;
break;
case Driver::ROT_X:
driverValue = poseRot.x;
break;
case Driver::ROT_Y:
driverValue = poseRot.y;
break;
case Driver::ROT_Z:
driverValue = poseRot.z;
break;
case Driver::SCALE_X:
driverValue = poseScale.x;
break;
case Driver::SCALE_Y:
driverValue = poseScale.y;
break;
case Driver::SCALE_Z:
driverValue = poseScale.z;
break;
}
return driverValue;
}
}