mirror of
https://github.com/halpz/re3.git
synced 2025-01-28 07:30:58 +00:00
315 lines
7.3 KiB
C++
315 lines
7.3 KiB
C++
#include "common.h"
|
|
|
|
#include "AnimBlendAssociation.h"
|
|
#include "AnimBlendNode.h"
|
|
|
|
void
|
|
CAnimBlendNode::Init(void)
|
|
{
|
|
frameA = -1;
|
|
frameB = -1;
|
|
remainingTime = 0.0f;
|
|
sequence = nil;
|
|
association = nil;
|
|
}
|
|
|
|
bool
|
|
CAnimBlendNode::Update(CVector &trans, CQuaternion &rot, float weight)
|
|
{
|
|
bool looped = false;
|
|
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
rot = CQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
if(association->IsRunning()){
|
|
remainingTime -= association->timeStep;
|
|
if(remainingTime <= 0.0f)
|
|
looped = NextKeyFrame();
|
|
}
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
|
|
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
|
|
float t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
|
trans = kfB->translation + t*(kfA->translation - kfB->translation);
|
|
trans *= blend;
|
|
}
|
|
if(sequence->type & CAnimBlendSequence::KF_ROT){
|
|
rot.Slerp(kfB->rotation, kfA->rotation, theta, invSin, t);
|
|
rot *= blend;
|
|
}
|
|
}
|
|
|
|
return looped;
|
|
}
|
|
|
|
bool
|
|
CAnimBlendNode::UpdateCompressed(CVector &trans, CQuaternion &rot, float weight)
|
|
{
|
|
bool looped = false;
|
|
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
rot = CQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
if(association->IsRunning()){
|
|
remainingTime -= association->timeStep;
|
|
if(remainingTime <= 0.0f)
|
|
looped = NextKeyFrameCompressed();
|
|
}
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA);
|
|
KeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB);
|
|
float t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime();
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
|
CVector transA, transB;
|
|
kfA->GetTranslation(&transA);
|
|
kfB->GetTranslation(&transB);
|
|
trans = transB + t*(transA - transB);
|
|
trans *= blend;
|
|
}
|
|
if(sequence->type & CAnimBlendSequence::KF_ROT){
|
|
CQuaternion rotA, rotB;
|
|
kfA->GetRotation(&rotA);
|
|
kfB->GetRotation(&rotB);
|
|
rot.Slerp(rotB, rotA, theta, invSin, t);
|
|
rot *= blend;
|
|
}
|
|
}
|
|
|
|
return looped;
|
|
}
|
|
|
|
bool
|
|
CAnimBlendNode::NextKeyFrame(void)
|
|
{
|
|
bool looped;
|
|
|
|
if(sequence->numFrames <= 1)
|
|
return false;
|
|
|
|
looped = false;
|
|
frameB = frameA;
|
|
|
|
// Advance as long as we have to
|
|
while(remainingTime <= 0.0f){
|
|
frameA++;
|
|
|
|
if(frameA >= sequence->numFrames){
|
|
// reached end of animation
|
|
if(!association->IsRepeating()){
|
|
frameA--;
|
|
remainingTime = 0.0f;
|
|
return false;
|
|
}
|
|
looped = true;
|
|
frameA = 0;
|
|
}
|
|
|
|
remainingTime += sequence->GetKeyFrame(frameA)->deltaTime;
|
|
}
|
|
|
|
frameB = frameA - 1;
|
|
if(frameB < 0)
|
|
frameB += sequence->numFrames;
|
|
|
|
CalcDeltas();
|
|
return looped;
|
|
}
|
|
|
|
bool
|
|
CAnimBlendNode::NextKeyFrameCompressed(void)
|
|
{
|
|
bool looped;
|
|
|
|
if(sequence->numFrames <= 1)
|
|
return false;
|
|
|
|
looped = false;
|
|
frameB = frameA;
|
|
|
|
// Advance as long as we have to
|
|
while(remainingTime <= 0.0f){
|
|
frameA++;
|
|
|
|
if(frameA >= sequence->numFrames){
|
|
// reached end of animation
|
|
if(!association->IsRepeating()){
|
|
frameA--;
|
|
remainingTime = 0.0f;
|
|
return false;
|
|
}
|
|
looped = true;
|
|
frameA = 0;
|
|
}
|
|
|
|
remainingTime += sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime();
|
|
}
|
|
|
|
frameB = frameA - 1;
|
|
if(frameB < 0)
|
|
frameB += sequence->numFrames;
|
|
|
|
CalcDeltasCompressed();
|
|
return looped;
|
|
}
|
|
|
|
// Set animation to time t
|
|
bool
|
|
CAnimBlendNode::FindKeyFrame(float t)
|
|
{
|
|
if(sequence->numFrames < 1)
|
|
return false;
|
|
|
|
frameA = 0;
|
|
frameB = frameA;
|
|
|
|
if(sequence->numFrames == 1){
|
|
remainingTime = 0.0f;
|
|
}else{
|
|
// advance until t is between frameB and frameA
|
|
while (t > sequence->GetKeyFrame(++frameA)->deltaTime) {
|
|
t -= sequence->GetKeyFrame(frameA)->deltaTime;
|
|
if (frameA + 1 >= sequence->numFrames) {
|
|
// reached end of animation
|
|
if (!association->IsRepeating()) {
|
|
CalcDeltas();
|
|
remainingTime = 0.0f;
|
|
return false;
|
|
}
|
|
frameA = 0;
|
|
}
|
|
frameB = frameA;
|
|
}
|
|
|
|
remainingTime = sequence->GetKeyFrame(frameA)->deltaTime - t;
|
|
}
|
|
|
|
CalcDeltas();
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
CAnimBlendNode::SetupKeyFrameCompressed(void)
|
|
{
|
|
if(sequence->numFrames < 1)
|
|
return false;
|
|
|
|
frameA = 1;
|
|
frameB = 0;
|
|
|
|
if(sequence->numFrames == 1){
|
|
frameA = 0;
|
|
remainingTime = 0.0f;
|
|
}else
|
|
remainingTime = sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime();
|
|
|
|
CalcDeltasCompressed();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::CalcDeltas(void)
|
|
{
|
|
if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
|
|
return;
|
|
KeyFrame *kfA = sequence->GetKeyFrame(frameA);
|
|
KeyFrame *kfB = sequence->GetKeyFrame(frameB);
|
|
float cos = DotProduct(kfA->rotation, kfB->rotation);
|
|
if(cos > 1.0f)
|
|
cos = 1.0f;
|
|
theta = Acos(cos);
|
|
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::CalcDeltasCompressed(void)
|
|
{
|
|
if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
|
|
return;
|
|
KeyFrameCompressed *kfA = sequence->GetKeyFrameCompressed(frameA);
|
|
KeyFrameCompressed *kfB = sequence->GetKeyFrameCompressed(frameB);
|
|
CQuaternion rotA, rotB;
|
|
kfA->GetRotation(&rotA);
|
|
kfB->GetRotation(&rotB);
|
|
float cos = DotProduct(rotA, rotB);
|
|
if(cos < 0.0f){
|
|
rotB *= -1.0f;
|
|
kfB->SetRotation(rotB);
|
|
}
|
|
cos = DotProduct(rotA, rotB);
|
|
if(cos > 1.0f)
|
|
cos = 1.0f;
|
|
theta = Acos(cos);
|
|
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
|
|
{
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
|
|
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
|
|
float t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
|
trans = kfB->translation + t*(kfA->translation - kfB->translation);
|
|
trans *= blend;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::GetCurrentTranslationCompressed(CVector &trans, float weight)
|
|
{
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA);
|
|
KeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB);
|
|
float t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime();
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
|
CVector transA, transB;
|
|
kfA->GetTranslation(&transA);
|
|
kfB->GetTranslation(&transB);
|
|
trans = transB + t*(transA - transB);
|
|
trans *= blend;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::GetEndTranslation(CVector &trans, float weight)
|
|
{
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTrans *kf = (KeyFrameTrans*)sequence->GetKeyFrame(sequence->numFrames-1);
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS)
|
|
trans = kf->translation * blend;
|
|
}
|
|
}
|
|
|
|
void
|
|
CAnimBlendNode::GetEndTranslationCompressed(CVector &trans, float weight)
|
|
{
|
|
trans = CVector(0.0f, 0.0f, 0.0f);
|
|
|
|
float blend = association->GetBlendAmount(weight);
|
|
if(blend > 0.0f){
|
|
KeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(sequence->numFrames-1);
|
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
|
CVector pos;
|
|
kf->GetTranslation(&pos);
|
|
trans = pos * blend;
|
|
}
|
|
}
|
|
}
|