summaryrefslogtreecommitdiff
path: root/src/animation/FrameUpdate.cpp
diff options
context:
space:
mode:
authorclaude-bot <[email protected]>2026-07-13 12:27:07 +0000
committerclaude-bot <[email protected]>2026-07-13 12:27:07 +0000
commit9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686 (patch)
treea84756b82513739a2672db3a1f0ec579db6d18ff /src/animation/FrameUpdate.cpp
downloadre3-9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686.tar.gz
re3-9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686.zip
Import Cai1Hsu/re3 @ miami (reVC / GTA:VC decompilation)HEADmiami
Snapshot import (no upstream history) into git.ancap.in.ua/claude, per @lzcnt. Source: https://github.com/Cai1Hsu/re3 branch miami.
Diffstat (limited to 'src/animation/FrameUpdate.cpp')
-rw-r--r--src/animation/FrameUpdate.cpp668
1 files changed, 668 insertions, 0 deletions
diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp
new file mode 100644
index 0000000..d3094bb
--- /dev/null
+++ b/src/animation/FrameUpdate.cpp
@@ -0,0 +1,668 @@
+#include "common.h"
+
+#include "NodeName.h"
+#include "VisibilityPlugins.h"
+#include "AnimBlendClumpData.h"
+#include "AnimBlendAssociation.h"
+#include "RpAnimBlend.h"
+
+CAnimBlendClumpData *gpAnimBlendClump;
+
+// PS2 names without "NonSkinned"
+void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg);
+
+void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
+
+void FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg);
+
+void
+FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ RwMatrix *mat = RwFrameGetMatrix(frame->frame);
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&
+ gpAnimBlendClump->velocity2d){
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D)
+ FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(frame, arg);
+ else
+ FrameUpdateCallBackWithVelocityExtractionNonSkinned(frame, arg);
+ return;
+ }
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+ if((*node)->sequence->HasTranslation())
+ pos += vec;
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ RwMatrixSetIdentity(mat);
+ rot.Normalise();
+ rot.Get(mat);
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ mat->pos.x = pos.x;
+ mat->pos.y = pos.y;
+ mat->pos.z = pos.z;
+ mat->pos.x += frame->resetPos.x;
+ mat->pos.y += frame->resetPos.y;
+ mat->pos.z += frame->resetPos.z;
+ }
+ RwMatrixUpdate(mat);
+}
+
+void
+FrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ float transx = 0.0f, transy = 0.0f;
+ float curx = 0.0f, cury = 0.0f;
+ float endx = 0.0f, endy = 0.0f;
+ bool looped = false;
+ RwMatrix *mat = RwFrameGetMatrix(frame->frame);
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);
+ cury += vec.y;
+ if((*node)->association->HasXTranslation())
+ curx += vec.x;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ transy += vec.y;
+ if((*node)->association->HasXTranslation())
+ transx += vec.x;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);
+ endy += vec.y;
+ if((*node)->association->HasXTranslation())
+ endx += vec.x;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ RwMatrixSetIdentity(mat);
+ rot.Normalise();
+ rot.Get(mat);
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ gpAnimBlendClump->velocity2d->x = transx - curx;
+ gpAnimBlendClump->velocity2d->y = transy - cury;
+ if(looped){
+ gpAnimBlendClump->velocity2d->x += endx;
+ gpAnimBlendClump->velocity2d->y += endy;
+ }
+ mat->pos.x = pos.x - transx;
+ mat->pos.y = pos.y - transy;
+ mat->pos.z = pos.z;
+ if(mat->pos.z >= -0.8f) {
+ if(mat->pos.z < -0.4f)
+ mat->pos.z += (2.5f * mat->pos.z + 2.0f) * frame->resetPos.z;
+ else
+ mat->pos.z += frame->resetPos.z;
+ }
+ mat->pos.x += frame->resetPos.x;
+ mat->pos.y += frame->resetPos.y;
+ }
+ RwMatrixUpdate(mat);
+}
+
+// original code uses do loops?
+void
+FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ CVector trans(0.0f, 0.0f, 0.0f);
+ CVector cur(0.0f, 0.0f, 0.0f);
+ CVector end(0.0f, 0.0f, 0.0f);
+ bool looped = false;
+ RwMatrix *mat = RwFrameGetMatrix(frame->frame);
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);
+ cur += vec;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ trans += vec;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);
+ end += vec;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ RwMatrixSetIdentity(mat);
+ rot.Normalise();
+ rot.Get(mat);
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ *gpAnimBlendClump->velocity3d = trans - cur;
+ if(looped)
+ *gpAnimBlendClump->velocity3d += end;
+ mat->pos.x = (pos - trans).x + frame->resetPos.x;
+ mat->pos.y = (pos - trans).y + frame->resetPos.y;
+ mat->pos.z = (pos - trans).z + frame->resetPos.z;
+ }
+ RwMatrixUpdate(mat);
+}
+
+void
+FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ float transBlendAmount = 0.0f;
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ RpHAnimStdInterpFrame *xform = frame->hanimFrame;
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&
+ gpAnimBlendClump->velocity2d){
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D)
+ FrameUpdateCallBackWith3dVelocityExtractionSkinned(frame, arg);
+ else
+ FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);
+ return;
+ }
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ transBlendAmount += (*node)->association->blendAmount;
+ }
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+ rot += q;
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ rot.Normalise();
+ xform->q.imag.x = rot.x;
+ xform->q.imag.y = rot.y;
+ xform->q.imag.z = rot.z;
+ xform->q.real = rot.w;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ xform->t.x = transBlendAmount*pos.x;
+ xform->t.y = transBlendAmount*pos.y;
+ xform->t.z = transBlendAmount*pos.z;
+ xform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x;
+ xform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y;
+ xform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z;
+ }
+}
+
+void
+FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ float transx = 0.0f, transy = 0.0f;
+ float curx = 0.0f, cury = 0.0f;
+ float endx = 0.0f, endy = 0.0f;
+ bool looped = false;
+ RpHAnimStdInterpFrame *xform = frame->hanimFrame;
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);
+ cury += vec.y;
+ if((*node)->association->HasXTranslation())
+ curx += vec.x;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ transy += vec.y;
+ if((*node)->association->HasXTranslation())
+ transx += vec.x;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);
+ endy += vec.y;
+ if((*node)->association->HasXTranslation())
+ endx += vec.x;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ rot.Normalise();
+ xform->q.imag.x = rot.x;
+ xform->q.imag.y = rot.y;
+ xform->q.imag.z = rot.z;
+ xform->q.real = rot.w;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ gpAnimBlendClump->velocity2d->x = transx - curx;
+ gpAnimBlendClump->velocity2d->y = transy - cury;
+ if(looped){
+ gpAnimBlendClump->velocity2d->x += endx;
+ gpAnimBlendClump->velocity2d->y += endy;
+ }
+ xform->t.x = pos.x - transx;
+ xform->t.y = pos.y - transy;
+ xform->t.z = pos.z;
+ if(xform->t.z >= -0.8f) {
+ if(xform->t.z < -0.4f)
+ xform->t.z += (2.5f * xform->t.z + 2.0f) * frame->resetPos.z;
+ else
+ xform->t.z += frame->resetPos.z;
+ }
+ xform->t.x += frame->resetPos.x;
+ xform->t.y += frame->resetPos.y;
+ }
+}
+
+void
+FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ CVector trans(0.0f, 0.0f, 0.0f);
+ CVector cur(0.0f, 0.0f, 0.0f);
+ CVector end(0.0f, 0.0f, 0.0f);
+ bool looped = false;
+ RpHAnimStdInterpFrame *xform = frame->hanimFrame;
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);
+ cur += vec;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ trans += vec;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);
+ end += vec;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ rot.Normalise();
+ xform->q.imag.x = rot.x;
+ xform->q.imag.y = rot.y;
+ xform->q.imag.z = rot.z;
+ xform->q.real = rot.w;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ *gpAnimBlendClump->velocity3d = trans - cur;
+ if(looped)
+ *gpAnimBlendClump->velocity3d += end;
+ xform->t.x = (pos - trans).x + frame->resetPos.x;
+ xform->t.y = (pos - trans).y + frame->resetPos.y;
+ xform->t.z = (pos - trans).z + frame->resetPos.z;
+ }
+}
+
+void
+FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg)
+{
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity2d)
+ FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);
+}
+
+
+void
+FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ CVector trans(0.0f, 0.0f, 0.0f);
+ CVector cur(0.0f, 0.0f, 0.0f);
+ CVector end(0.0f, 0.0f, 0.0f);
+ bool looped = false;
+ RwMatrix *mat = RwFrameGetMatrix(frame->frame);
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&
+ gpAnimBlendClump->velocity2d){
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount);
+ cur += vec;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ trans += vec;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount);
+ end += vec;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ RwMatrixSetIdentity(mat);
+ rot.Normalise();
+ rot.Get(mat);
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ *gpAnimBlendClump->velocity3d = trans - cur;
+ if(looped)
+ *gpAnimBlendClump->velocity3d += end;
+ mat->pos.x = (pos - trans).x + frame->resetPos.x;
+ mat->pos.y = (pos - trans).y + frame->resetPos.y;
+ mat->pos.z = (pos - trans).z + frame->resetPos.z;
+ }
+ RwMatrixUpdate(mat);
+ }else{
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);
+ if((*node)->sequence->HasTranslation())
+ pos += vec;
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ RwMatrixSetIdentity(mat);
+ rot.Normalise();
+ rot.Get(mat);
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ mat->pos.x = pos.x;
+ mat->pos.y = pos.y;
+ mat->pos.z = pos.z;
+ mat->pos.x += frame->resetPos.x;
+ mat->pos.y += frame->resetPos.y;
+ mat->pos.z += frame->resetPos.z;
+ }
+ RwMatrixUpdate(mat);
+ }
+}
+
+void
+FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg)
+{
+ CVector vec, pos(0.0f, 0.0f, 0.0f);
+ CQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);
+ float totalBlendAmount = 0.0f;
+ CVector trans(0.0f, 0.0f, 0.0f);
+ CVector cur(0.0f, 0.0f, 0.0f);
+ CVector end(0.0f, 0.0f, 0.0f);
+ bool looped = false;
+ RpHAnimStdInterpFrame *xform = frame->hanimFrame;
+ CAnimBlendNode **node;
+ AnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;
+
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&
+ gpAnimBlendClump->velocity2d){
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->sequence->HasTranslation()){
+ if((*node)->association->HasTranslation()){
+ (*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount);
+ cur += vec;
+ }
+ }
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ bool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);
+#ifdef FIX_BUGS
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+#endif
+ rot += q;
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ if((*node)->association->HasTranslation()){
+ trans += vec;
+ looped |= nodelooped;
+ if(nodelooped){
+ (*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount);
+ end += vec;
+ }
+ }
+ }
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ rot.Normalise();
+ xform->q.imag.x = rot.x;
+ xform->q.imag.y = rot.y;
+ xform->q.imag.z = rot.z;
+ xform->q.real = rot.w;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ *gpAnimBlendClump->velocity3d = trans - cur;
+ if(looped)
+ *gpAnimBlendClump->velocity3d += end;
+ xform->t.x = (pos - trans).x + frame->resetPos.x;
+ xform->t.y = (pos - trans).y + frame->resetPos.y;
+ xform->t.z = (pos - trans).z + frame->resetPos.z;
+ }
+ }else{
+ float transBlendAmount = 0.0f;
+
+ if(updateData->foobar)
+ for(node = updateData->nodes; *node; node++)
+ if((*node)->sequence && (*node)->association->IsPartial())
+ totalBlendAmount += (*node)->association->blendAmount;
+
+ for(node = updateData->nodes; *node; node++){
+ if((*node)->sequence){
+ (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);
+ if((*node)->sequence->HasTranslation()){
+ pos += vec;
+ transBlendAmount += (*node)->association->blendAmount;
+ }
+ if(DotProduct(rot, q) < 0.0f)
+ rot -= q;
+ else
+ rot += q;
+ }
+ ++*node;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){
+ rot.Normalise();
+ xform->q.imag.x = rot.x;
+ xform->q.imag.y = rot.y;
+ xform->q.imag.z = rot.z;
+ xform->q.real = rot.w;
+ }
+
+ if((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){
+ xform->t.x = transBlendAmount*pos.x;
+ xform->t.y = transBlendAmount*pos.y;
+ xform->t.z = transBlendAmount*pos.z;
+ xform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x;
+ xform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y;
+ xform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z;
+ }
+ }
+}