summaryrefslogtreecommitdiffstats
path: root/src/animation
diff options
context:
space:
mode:
Diffstat (limited to 'src/animation')
-rw-r--r--src/animation/AnimBlendAssocGroup.cpp49
-rw-r--r--src/animation/AnimBlendAssocGroup.h4
-rw-r--r--src/animation/AnimBlendAssociation.cpp38
-rw-r--r--src/animation/AnimBlendAssociation.h22
-rw-r--r--src/animation/AnimBlendClumpData.cpp1
-rw-r--r--src/animation/AnimBlendClumpData.h7
-rw-r--r--src/animation/AnimBlendHierarchy.cpp57
-rw-r--r--src/animation/AnimBlendHierarchy.h4
-rw-r--r--src/animation/AnimBlendNode.cpp46
-rw-r--r--src/animation/AnimBlendNode.h2
-rw-r--r--src/animation/AnimBlendSequence.cpp19
-rw-r--r--src/animation/AnimBlendSequence.h7
-rw-r--r--src/animation/AnimManager.cpp453
-rw-r--r--src/animation/AnimManager.h31
-rw-r--r--src/animation/AnimationId.h14
-rw-r--r--src/animation/Bones.cpp73
-rw-r--r--src/animation/Bones.h38
-rw-r--r--src/animation/CutsceneMgr.cpp28
-rw-r--r--src/animation/CutsceneMgr.h1
-rw-r--r--src/animation/FrameUpdate.cpp16
-rw-r--r--src/animation/RpAnimBlend.cpp101
-rw-r--r--src/animation/RpAnimBlend.h5
22 files changed, 675 insertions, 341 deletions
diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp
index 5a6d10b4..c6a166c2 100644
--- a/src/animation/AnimBlendAssocGroup.cpp
+++ b/src/animation/AnimBlendAssocGroup.cpp
@@ -4,16 +4,22 @@
#include "General.h"
#include "RwHelper.h"
+#include "ModelIndices.h"
#include "ModelInfo.h"
#include "AnimManager.h"
#include "RpAnimBlend.h"
#include "AnimBlendAssociation.h"
#include "AnimBlendAssocGroup.h"
+//--MIAMI: file done
+
CAnimBlendAssocGroup::CAnimBlendAssocGroup(void)
{
+ animBlock = nil;
assocList = nil;
numAssociations = 0;
+ firstAnimId = 0;
+ groupId = -1;
}
CAnimBlendAssocGroup::~CAnimBlendAssocGroup(void)
@@ -44,6 +50,7 @@ CAnimBlendAssocGroup::GetAnimation(const char *name)
for(i = 0; i < numAssociations; i++)
if(!CGeneral::faststricmp(assocList[i].hierarchy->name, name))
return &assocList[i];
+ debug("\n\nCan't find the fucking animation %s\n\n\n", name);
return nil;
}
@@ -103,6 +110,15 @@ GetModelFromName(const char *name)
{
int i;
CBaseModelInfo *mi;
+ char playername[32];
+
+ if(strncasecmp(name, "CSplay", 6) == 0 &&
+ strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetName(), "ig", 2) == 0){
+ strcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetName());
+ playername[0] = 'C';
+ playername[1] = 'S';
+ name = playername;
+ }
for(i = 0; i < MODELINFOSIZE; i++){
mi = CModelInfo::GetModelInfo(i);
@@ -119,8 +135,7 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
int i;
CAnimBlock *animBlock;
- if(assocList)
- DestroyAssociations();
+ DestroyAssociations();
animBlock = CAnimManager::GetAnimationBlock(name);
assocList = new CAnimBlendAssociation[animBlock->numAnims];
@@ -129,17 +144,18 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
for(i = 0; i < animBlock->numAnims; i++){
CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i);
CBaseModelInfo *model = GetModelFromName(anim->name);
- assert(model);
- printf("Associated anim %s with model %s\n", anim->name, model->GetName());
- RpClump *clump = (RpClump*)model->CreateInstance();
-#ifdef PED_SKIN
- if(IsClumpSkinned(clump))
- RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
-#endif
- RpAnimBlendClumpInit(clump);
- assocList[i].Init(clump, anim);
- RpClumpDestroy(clump);
- assocList[i].animId = i;
+ if(model){
+ debug("Associated anim %s with model %s\n", anim->name, model->GetName());
+ RpClump *clump = (RpClump*)model->CreateInstance();
+ RpAnimBlendClumpInit(clump);
+ assocList[i].Init(clump, anim);
+ if(IsClumpSkinned(clump))
+ RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
+ RpClumpDestroy(clump);
+ assocList[i].animId = firstAnimId + i;
+ assocList[i].groupId = groupId;
+ }else
+ debug("\n\nCANNOT FIND MODELINFO WITH NAME %s\n\n\n", anim->name);
}
numAssociations = animBlock->numAnims;
}
@@ -149,10 +165,8 @@ void
CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs)
{
int i;
- CAnimBlock *animBlock;
- if(assocList)
- DestroyAssociations();
+ DestroyAssociations();
animBlock = CAnimManager::GetAnimationBlock(blockName);
assocList = new CAnimBlendAssociation[numAssocs];
@@ -160,7 +174,8 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump,
numAssociations = 0;
for(i = 0; i < numAssocs; i++){
assocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock));
- assocList[i].animId = i;
+ assocList[i].animId = firstAnimId + i;
+ assocList[i].groupId = groupId;
}
numAssociations = numAssocs;
}
diff --git a/src/animation/AnimBlendAssocGroup.h b/src/animation/AnimBlendAssocGroup.h
index aa58b0d3..86f0ca18 100644
--- a/src/animation/AnimBlendAssocGroup.h
+++ b/src/animation/AnimBlendAssocGroup.h
@@ -1,12 +1,16 @@
#pragma once
class CAnimBlendAssociation;
+struct CAnimBlock;
class CAnimBlendAssocGroup
{
public:
+ CAnimBlock *animBlock;
CAnimBlendAssociation *assocList;
int32 numAssociations;
+ int32 firstAnimId;
+ int32 groupId; // id of self in ms_aAnimAssocGroups
CAnimBlendAssocGroup(void);
~CAnimBlendAssocGroup(void);
diff --git a/src/animation/AnimBlendAssociation.cpp b/src/animation/AnimBlendAssociation.cpp
index 8c99b694..9a29601b 100644
--- a/src/animation/AnimBlendAssociation.cpp
+++ b/src/animation/AnimBlendAssociation.cpp
@@ -7,8 +7,11 @@
#include "AnimBlendAssociation.h"
#include "RwHelper.h"
+//--MIAMI: file done
+
CAnimBlendAssociation::CAnimBlendAssociation(void)
{
+ groupId = -1;
nodes = nil;
blendAmount = 1.0f;
blendDelta = 0.0f;
@@ -54,8 +57,8 @@ CAnimBlendAssociation::AllocateAnimBlendNodeArray(int n)
void
CAnimBlendAssociation::FreeAnimBlendNodeArray(void)
{
- assert(nodes != nil);
- RwFreeAlign(nodes);
+ if(nodes)
+ RwFreeAlign(nodes);
}
void
@@ -75,7 +78,10 @@ CAnimBlendAssociation::Init(RpClump *clump, CAnimBlendHierarchy *hier)
// NB: This is where the order of nodes is defined
for(i = 0; i < hier->numSequences; i++){
CAnimBlendSequence *seq = &hier->sequences[i];
- frame = RpAnimBlendClumpFindFrame(clump, seq->name);
+ if(seq->boneTag == -1)
+ frame = RpAnimBlendClumpFindFrame(clump, seq->name);
+ else
+ frame = RpAnimBlendClumpFindBone(clump, seq->boneTag);
if(frame && seq->numFrames > 0)
nodes[frame - clumpData->frames].sequence = seq;
}
@@ -90,6 +96,7 @@ CAnimBlendAssociation::Init(CAnimBlendAssociation &assoc)
numNodes = assoc.numNodes;
flags = assoc.flags;
animId = assoc.animId;
+ groupId = assoc.groupId;
AllocateAnimBlendNodeArray(numNodes);
for(i = 0; i < numNodes; i++){
nodes[i] = assoc.nodes[i];
@@ -129,9 +136,15 @@ CAnimBlendAssociation::SetCurrentTime(float time)
if(!IsRepeating())
return;
CAnimManager::UncompressAnimation(hierarchy);
- for(i = 0; i < numNodes; i++)
- if(nodes[i].sequence)
- nodes[i].FindKeyFrame(currentTime);
+ if(hierarchy->compressed2){
+ for(i = 0; i < numNodes; i++)
+ if(nodes[i].sequence)
+ nodes[i].SetupKeyFrameCompressed();
+ }else{
+ for(i = 0; i < numNodes; i++)
+ if(nodes[i].sequence)
+ nodes[i].FindKeyFrame(currentTime);
+ }
}
void
@@ -147,13 +160,23 @@ CAnimBlendAssociation::Start(float time)
SetCurrentTime(time);
}
+void
+CAnimBlendAssociation::UpdateTimeStep(float timeDelta, float relSpeed)
+{
+ if(IsRunning())
+ timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
+}
+
bool
CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
{
if(!IsRunning())
return true;
+ if(currentTime >= hierarchy->totalLength){
+ flags &= ~ASSOC_RUNNING;
+ return true;
+ }
- timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
currentTime += timeStep;
if(currentTime >= hierarchy->totalLength){
@@ -163,7 +186,6 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
currentTime -= hierarchy->totalLength;
else{
currentTime = hierarchy->totalLength;
- flags &= ~ASSOC_RUNNING;
if(flags & ASSOC_FADEOUTWHENDONE){
flags |= ASSOC_DELETEFADEDOUT;
blendDelta = -4.0f;
diff --git a/src/animation/AnimBlendAssociation.h b/src/animation/AnimBlendAssociation.h
index d0c60a88..7efd8099 100644
--- a/src/animation/AnimBlendAssociation.h
+++ b/src/animation/AnimBlendAssociation.h
@@ -12,12 +12,12 @@ enum {
ASSOC_PARTIAL = 0x10,
ASSOC_MOVEMENT = 0x20, // ???
ASSOC_HAS_TRANSLATION = 0x40,
- ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void)
- ASSOC_FLAG_XPRESS = 0x100, // only used by xpress scratch, see CPed::Chat(void)
- ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void)
- ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played
- ASSOC_FRONTAL = 0x800, // anims that we fall to front
- ASSOC_HAS_X_TRANSLATION = 0x1000, // for 2d velocity extraction
+ ASSOC_HAS_X_TRANSLATION = 0x80, // for 2d velocity extraction
+ ASSOC_WALK = 0x100, // for CPed::PlayFootSteps(void)
+ ASSOC_FLAG_XPRESS = 0x200, // only used by xpress scratch, see CPed::Chat(void)
+ ASSOC_NOWALK = 0x400, // see CPed::PlayFootSteps(void)
+ ASSOC_BLOCK = 0x800, // unused in assoc description, blocks other anims from being played
+ ASSOC_FRONTAL = 0x1000, // anims that we fall to front
};
// Anim hierarchy associated with a clump
@@ -35,7 +35,8 @@ public:
CAnimBlendLink link;
- int numNodes; // taken from CAnimBlendClumpData::numFrames
+ int16 numNodes; // taken from CAnimBlendClumpData::numFrames
+ int16 groupId; // ID of CAnimBlendAssocGroup this is in
// NB: Order of these depends on order of nodes in Clump this was built from
CAnimBlendNode *nodes;
CAnimBlendHierarchy *hierarchy;
@@ -44,8 +45,8 @@ public:
float currentTime;
float speed;
float timeStep;
- int32 animId;
- int32 flags;
+ int16 animId;
+ int16 flags;
int32 callbackType;
void (*callback)(CAnimBlendAssociation*, void*);
void *callbackArg;
@@ -73,6 +74,7 @@ public:
void SetCurrentTime(float time);
void SyncAnimation(CAnimBlendAssociation *other);
void Start(float time);
+ void UpdateTimeStep(float timeDelta, float relSpeed);
bool UpdateTime(float timeDelta, float relSpeed);
bool UpdateBlend(float timeDelta);
@@ -84,5 +86,3 @@ public:
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
}
};
-
-VALIDATE_SIZE(CAnimBlendAssociation, 0x40);
diff --git a/src/animation/AnimBlendClumpData.cpp b/src/animation/AnimBlendClumpData.cpp
index d40e8357..5f7491fe 100644
--- a/src/animation/AnimBlendClumpData.cpp
+++ b/src/animation/AnimBlendClumpData.cpp
@@ -3,6 +3,7 @@
#include "AnimBlendClumpData.h"
#include "RwHelper.h"
+//--MIAMI: file done
CAnimBlendClumpData::CAnimBlendClumpData(void)
{
diff --git a/src/animation/AnimBlendClumpData.h b/src/animation/AnimBlendClumpData.h
index 5c511ab8..b953ee88 100644
--- a/src/animation/AnimBlendClumpData.h
+++ b/src/animation/AnimBlendClumpData.h
@@ -11,6 +11,7 @@ struct AnimBlendFrameData
IGNORE_TRANSLATION = 4,
VELOCITY_EXTRACTION = 8,
VELOCITY_EXTRACTION_3D = 0x10,
+ UPDATE_KEYFRAMES = 0x20,
};
uint8 flag;
@@ -35,9 +36,6 @@ class CAnimBlendClumpData
public:
CAnimBlendLink link;
int32 numFrames;
-#ifdef PED_SKIN
- int32 modelNumber; // doesn't seem to be used
-#endif
CVector *velocity;
// order of frames is determined by RW hierarchy
AnimBlendFrameData *frames;
@@ -50,6 +48,3 @@ public:
#endif
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
};
-#ifndef PED_SKIN
-VALIDATE_SIZE(CAnimBlendClumpData, 0x14);
-#endif
diff --git a/src/animation/AnimBlendHierarchy.cpp b/src/animation/AnimBlendHierarchy.cpp
index feeaca3d..7388352f 100644
--- a/src/animation/AnimBlendHierarchy.cpp
+++ b/src/animation/AnimBlendHierarchy.cpp
@@ -2,6 +2,9 @@
#include "AnimBlendSequence.h"
#include "AnimBlendHierarchy.h"
+#include "AnimManager.h"
+
+//--MIAMI: file done
CAnimBlendHierarchy::CAnimBlendHierarchy(void)
{
@@ -15,9 +18,10 @@ CAnimBlendHierarchy::CAnimBlendHierarchy(void)
void
CAnimBlendHierarchy::Shutdown(void)
{
+ CAnimManager::RemoveFromUncompressedCache(this);
RemoveAnimSequences();
+ totalLength = 0.0f;
compressed = 0;
- linkPtr = nil;
}
void
@@ -30,15 +34,44 @@ void
CAnimBlendHierarchy::CalcTotalTime(void)
{
int i, j;
- float totalTime = 0.0f;
+
+ totalLength = 0.0f;
for(i = 0; i < numSequences; i++){
- float seqTime = 0.0f;
- for(j = 0; j < sequences[i].numFrames; j++)
- seqTime += sequences[i].GetKeyFrame(j)->deltaTime;
- totalTime = Max(totalTime, seqTime);
+#ifdef FIX_BUGS
+ if(sequences[i].numFrames == 0)
+ continue;
+#endif
+
+ totalLength = Max(totalLength, sequences[i].GetKeyFrame(sequences[i].numFrames-1)->deltaTime);
+ for(j = sequences[i].numFrames-1; j > 0; j--){
+ KeyFrame *kf1 = sequences[i].GetKeyFrame(j);
+ KeyFrame *kf2 = sequences[i].GetKeyFrame(j-1);
+ kf1->deltaTime -= kf2->deltaTime;
+ }
+ }
+}
+
+void
+CAnimBlendHierarchy::CalcTotalTimeCompressed(void)
+{
+ int i, j;
+
+ totalLength = 0.0f;
+
+ for(i = 0; i < numSequences; i++){
+#ifdef FIX_BUGS
+ if(sequences[i].numFrames == 0)
+ continue;
+#endif
+
+ totalLength = Max(totalLength, sequences[i].GetKeyFrameCompressed(sequences[i].numFrames-1)->deltaTime/60.0f);
+ for(j = sequences[i].numFrames-1; j > 0; j--){
+ KeyFrame *kf1 = sequences[i].GetKeyFrameCompressed(j);
+ KeyFrame *kf2 = sequences[i].GetKeyFrameCompressed(j-1);
+ kf1->deltaTime -= kf2->deltaTime;
+ }
}
- totalLength = totalTime;
}
void
@@ -53,17 +86,19 @@ CAnimBlendHierarchy::RemoveQuaternionFlips(void)
void
CAnimBlendHierarchy::RemoveAnimSequences(void)
{
- if(sequences)
- delete[] sequences;
+ delete[] sequences;
+ sequences = nil;
numSequences = 0;
}
void
CAnimBlendHierarchy::Uncompress(void)
{
- if(totalLength == 0.0f)
- CalcTotalTime();
compressed = 0;
+ if(totalLength == 0.0f){
+ RemoveQuaternionFlips();
+ CalcTotalTime();
+ }
}
void
diff --git a/src/animation/AnimBlendHierarchy.h b/src/animation/AnimBlendHierarchy.h
index 0144108d..45c9217e 100644
--- a/src/animation/AnimBlendHierarchy.h
+++ b/src/animation/AnimBlendHierarchy.h
@@ -11,7 +11,8 @@ public:
char name[24];
CAnimBlendSequence *sequences;
int16 numSequences;
- int16 compressed; // not really used
+ bool compressed; // not really used
+ bool compressed2; // not really used
float totalLength;
CLink<CAnimBlendHierarchy*> *linkPtr;
@@ -19,6 +20,7 @@ public:
void Shutdown(void);
void SetName(char *name);
void CalcTotalTime(void);
+ void CalcTotalTimeCompressed(void);
void RemoveQuaternionFlips(void);
void RemoveAnimSequences(void);
void Uncompress(void);
diff --git a/src/animation/AnimBlendNode.cpp b/src/animation/AnimBlendNode.cpp
index df6cd1d5..4186e994 100644
--- a/src/animation/AnimBlendNode.cpp
+++ b/src/animation/AnimBlendNode.cpp
@@ -3,6 +3,8 @@
#include "AnimBlendAssociation.h"
#include "AnimBlendNode.h"
+//--MIAMI: file done
+
void
CAnimBlendNode::Init(void)
{
@@ -92,7 +94,9 @@ CAnimBlendNode::FindKeyFrame(float t)
frameA = 0;
frameB = frameA;
- if(sequence->numFrames >= 2){
+ if(sequence->numFrames == 1){
+ remainingTime = 0.0f;
+ }else{
frameA++;
// advance until t is between frameB and frameA
@@ -101,8 +105,11 @@ CAnimBlendNode::FindKeyFrame(float t)
frameB = frameA++;
if(frameA >= sequence->numFrames){
// reached end of animation
- if(!association->IsRepeating())
+ if(!association->IsRepeating()){
+ CalcDeltas();
+ remainingTime = 0.0f;
return false;
+ }
frameA = 0;
frameB = 0;
}
@@ -115,6 +122,25 @@ CAnimBlendNode::FindKeyFrame(float t)
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)->deltaTime/60.0f;
+
+ CalcDeltasCompressed();
+ return true;
+}
+
void
CAnimBlendNode::CalcDeltas(void)
{
@@ -130,6 +156,20 @@ CAnimBlendNode::CalcDeltas(void)
}
void
+CAnimBlendNode::CalcDeltasCompressed(void)
+{
+ if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
+ return;
+ KeyFrame *kfA = sequence->GetKeyFrameCompressed(frameA);
+ KeyFrame *kfB = sequence->GetKeyFrameCompressed(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::GetCurrentTranslation(CVector &trans, float weight)
{
trans = CVector(0.0f, 0.0f, 0.0f);
@@ -138,7 +178,7 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
if(blend > 0.0f){
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
- float t = (kfA->deltaTime - remainingTime)/kfA->deltaTime;
+ 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;
diff --git a/src/animation/AnimBlendNode.h b/src/animation/AnimBlendNode.h
index 89924d6a..9446e1ae 100644
--- a/src/animation/AnimBlendNode.h
+++ b/src/animation/AnimBlendNode.h
@@ -22,7 +22,9 @@ public:
bool Update(CVector &trans, CQuaternion &rot, float weight);
bool NextKeyFrame(void);
bool FindKeyFrame(float t);
+ bool SetupKeyFrameCompressed(void);
void CalcDeltas(void);
+ void CalcDeltasCompressed(void);
void GetCurrentTranslation(CVector &trans, float weight);
void GetEndTranslation(CVector &trans, float weight);
};
diff --git a/src/animation/AnimBlendSequence.cpp b/src/animation/AnimBlendSequence.cpp
index 4578ec50..b04d6b41 100644
--- a/src/animation/AnimBlendSequence.cpp
+++ b/src/animation/AnimBlendSequence.cpp
@@ -2,6 +2,8 @@
#include "AnimBlendSequence.h"
+//--MIAMI: file done
+
CAnimBlendSequence::CAnimBlendSequence(void)
{
type = 0;
@@ -17,6 +19,8 @@ CAnimBlendSequence::~CAnimBlendSequence(void)
{
if(keyFrames)
RwFree(keyFrames);
+ if(keyFramesCompressed)
+ RwFree(keyFramesCompressed);
}
void
@@ -26,18 +30,21 @@ CAnimBlendSequence::SetName(char *name)
}
void
-CAnimBlendSequence::SetNumFrames(int numFrames, bool translation)
+CAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compressed)
{
- int sz;
-
if(translation){
- sz = sizeof(KeyFrameTrans);
type |= KF_ROT | KF_TRANS;
+ if(compressed)
+ keyFramesCompressed = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
+ else
+ keyFrames = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
}else{
- sz = sizeof(KeyFrame);
type |= KF_ROT;
+ if(compressed)
+ keyFramesCompressed = RwMalloc(sizeof(KeyFrame) * numFrames);
+ else
+ keyFrames = RwMalloc(sizeof(KeyFrame) * numFrames);
}
- keyFrames = RwMalloc(sz * numFrames);
this->numFrames = numFrames;
}
diff --git a/src/animation/AnimBlendSequence.h b/src/animation/AnimBlendSequence.h
index 44ac8886..6d8c98aa 100644
--- a/src/animation/AnimBlendSequence.h
+++ b/src/animation/AnimBlendSequence.h
@@ -33,13 +33,18 @@ public:
CAnimBlendSequence(void);
virtual ~CAnimBlendSequence(void);
void SetName(char *name);
- void SetNumFrames(int numFrames, bool translation);
+ void SetNumFrames(int numFrames, bool translation, bool compressed);
void RemoveQuaternionFlips(void);
KeyFrame *GetKeyFrame(int n) {
return type & KF_TRANS ?
&((KeyFrameTrans*)keyFrames)[n] :
&((KeyFrame*)keyFrames)[n];
}
+ KeyFrame *GetKeyFrameCompressed(int n) {
+ return type & KF_TRANS ?
+ &((KeyFrameTrans*)keyFramesCompressed)[n] :
+ &((KeyFrame*)keyFramesCompressed)[n];
+ }
bool HasTranslation(void) { return !!(type & KF_TRANS); }
// TODO? these are unused
// void Uncompress(void);
diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp
index 8fb1576c..c6f84871 100644
--- a/src/animation/AnimManager.cpp
+++ b/src/animation/AnimManager.cpp
@@ -10,6 +10,9 @@
#include "AnimBlendAssociation.h"
#include "AnimBlendAssocGroup.h"
#include "AnimManager.h"
+#include "Streaming.h"
+
+//--MIAMI: code done (except for pointless TODO)
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
@@ -78,13 +81,13 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_IDLE, ASSOC_REPEAT },
{ ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@@ -260,13 +263,13 @@ char const *aStdAnimations[] = {
"bomber",
"WEAPON_hgun_rload",
"WEAPON_AK_rload",
- "FPS_PUNCH",
- "FPS_BAT",
- "FPS_UZI",
- "FPS_PUMP",
- "FPS_AK",
- "FPS_M16",
- "FPS_ROCKET",
+// "FPS_PUNCH",
+// "FPS_BAT",
+// "FPS_UZI",
+// "FPS_PUMP",
+// "FPS_AK",
+// "FPS_M16",
+// "FPS_ROCKET",
"FIGHTIDLE",
"FIGHT2IDLE",
"FIGHTsh_F",
@@ -410,6 +413,13 @@ char const *aPlayerBBBatAnimations[] = {
"IDLE_STANCE",
"walk_start",
};
+char const *aPlayerChainsawAnimations[] = {
+ "walk_csaw",
+ "run_csaw",
+ "run_csaw",
+ "IDLE_csaw",
+ "walk_start_csaw",
+};
char const *aShuffleAnimations[] = {
"WALK_shuffle",
"RUN_civi",
@@ -446,6 +456,12 @@ char const *aOldFatAnimations[] = {
"woman_runpanic",
"idle_stance",
};
+char const *aJoggerAnimations[] = {
+ "JOG_maleA",
+ "run_civi",
+ "sprint_civi",
+ "idle_stance",
+};
char const *aStdWomanAnimations[] = {
"woman_walknorm",
"woman_run",
@@ -470,14 +486,20 @@ char const *aSexyWomanAnimations[] = {
"woman_runpanic",
"woman_idlestance",
};
+char const *aFatWomanAnimations[] = {
+ "walk_fat",
+ "woman_run",
+ "woman_runpanic",
+ "woman_idlestance",
+};
char const *aOldWomanAnimations[] = {
"woman_walkold",
"woman_run",
"woman_runpanic",
"woman_idlestance",
};
-char const *aFatWomanAnimations[] = {
- "walk_fat",
+char const *aJoggerWomanAnimations[] = {
+ "JOG_maleB",
"woman_run",
"woman_runpanic",
"woman_idlestance",
@@ -488,22 +510,28 @@ char const *aPanicChunkyAnimations[] = {
"woman_runpanic",
"idle_stance",
};
+char const *aSkateAnimations[] = {
+ "skate_run",
+ "skate_sprint",
+ "skate_sprint",
+ "skate_idle",
+};
char const *aPlayerStrafeBackAnimations[] = {
- "walk_player_back",
- "run_player_back",
- "run_player_back",
+ "walk_back",
+ "run_back",
+ "run_back",
"IDLE_STANCE",
"walk_start_back",
};
char const *aPlayerStrafeLeftAnimations[] = {
- "walk_player_left",
+ "walk_left",
"run_left",
"run_left",
"IDLE_STANCE",
"walk_start_left",
};
char const *aPlayerStrafeRightAnimations[] = {
- "walk_player_right",
+ "walk_right",
"run_right",
"run_right",
"IDLE_STANCE",
@@ -530,6 +558,28 @@ char const *aRocketStrafeRightAnimations[] = {
"idle_rocket",
"walkst_rocket_right",
};
+char const *aChainsawStrafeBackAnimations[] = {
+ "walk_csaw_back",
+ "run_csaw_back",
+ "run_csaw_back",
+ "idle_csaw",
+ "walkst_csaw_back",
+};
+char const *aChainsawStrafeLeftAnimations[] = {
+ "walk_csaw_left",
+ "run_csaw_left",
+ "run_csaw_left",
+ "idle_csaw",
+ "walkst_csaw_left",
+};
+char const *aChainsawStrafeRightAnimations[] = {
+ "walk_csaw_right",
+ "run_csaw_right",
+ "run_csaw_right",
+ "idle_csaw",
+ "walkst_csaw_right",
+};
+
const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = {
{ "man", "ped", MI_COP, 173, aStdAnimations, aStdAnimDescs },
{ "player", "ped", MI_COP, 5, aPlayerAnimations, aStdAnimDescs },
@@ -537,25 +587,32 @@ const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_
{ "player1armed", "ped", MI_COP, 5, aPlayer1ArmedAnimations, aStdAnimDescs },
{ "player2armed", "ped", MI_COP, 5, aPlayer2ArmedAnimations, aStdAnimDescs },
{ "playerBBBat", "ped", MI_COP, 5, aPlayerBBBatAnimations, aStdAnimDescs },
+ { "playercsaw", "ped", MI_COP, 5, aPlayerChainsawAnimations, aStdAnimDescs },
{ "shuffle", "ped", MI_COP, 4, aShuffleAnimations, aStdAnimDescs },
{ "oldman", "ped", MI_COP, 4, aOldAnimations, aStdAnimDescs },
{ "gang1", "ped", MI_COP, 4, aGang1Animations, aStdAnimDescs },
{ "gang2", "ped", MI_COP, 4, aGang2Animations, aStdAnimDescs },
{ "fatman", "ped", MI_COP, 4, aFatAnimations, aStdAnimDescs },
{ "oldfatman", "ped", MI_COP, 4, aOldFatAnimations, aStdAnimDescs },
+ { "jogger", "ped", MI_COP, 4, aJoggerAnimations, aStdAnimDescs },
{ "woman", "ped", MI_COP, 4, aStdWomanAnimations, aStdAnimDescs },
{ "shopping", "ped", MI_COP, 4, aWomanShopAnimations, aStdAnimDescs },
{ "busywoman", "ped", MI_COP, 4, aBusyWomanAnimations, aStdAnimDescs },
{ "sexywoman", "ped", MI_COP, 4, aSexyWomanAnimations, aStdAnimDescs },
- { "oldwoman", "ped", MI_COP, 4, aOldWomanAnimations, aStdAnimDescs },
{ "fatwoman", "ped", MI_COP, 4, aFatWomanAnimations, aStdAnimDescs },
+ { "oldwoman", "ped", MI_COP, 4, aOldWomanAnimations, aStdAnimDescs },
+ { "jogwoman", "ped", MI_COP, 4, aJoggerWomanAnimations, aStdAnimDescs },
{ "panicchunky", "ped", MI_COP, 4, aPanicChunkyAnimations, aStdAnimDescs },
+ { "skate", "ped", MI_COP, 4, aSkateAnimations, aStdAnimDescs },
{ "playerback", "ped", MI_COP, 5, aPlayerStrafeBackAnimations, aStdAnimDescs },
{ "playerleft", "ped", MI_COP, 5, aPlayerStrafeLeftAnimations, aStdAnimDescsSide },
{ "playerright", "ped", MI_COP, 5, aPlayerStrafeRightAnimations, aStdAnimDescsSide },
{ "rocketback", "ped", MI_COP, 5, aRocketStrafeBackAnimations, aStdAnimDescs },
{ "rocketleft", "ped", MI_COP, 5, aRocketStrafeLeftAnimations, aStdAnimDescsSide },
{ "rocketright", "ped", MI_COP, 5, aRocketStrafeRightAnimations, aStdAnimDescsSide },
+ { "csawback", "ped", MI_COP, 5, aChainsawStrafeBackAnimations, aStdAnimDescs },
+ { "csawleft", "ped", MI_COP, 5, aChainsawStrafeLeftAnimations, aStdAnimDescsSide },
+ { "csawright", "ped", MI_COP, 5, aChainsawStrafeRightAnimations, aStdAnimDescsSide },
};
void
@@ -564,8 +621,6 @@ CAnimManager::Initialise(void)
ms_numAnimations = 0;
ms_numAnimBlocks = 0;
ms_animCache.Init(25);
-
-// dumpanimdata();
}
void
@@ -573,31 +628,48 @@ CAnimManager::Shutdown(void)
{
int i;
- ms_animCache.Shutdown();
+ for(i = 0; i < NUMANIMBLOCKS; i++)
+ CStreaming::RemoveAnim(i);
for(i = 0; i < ms_numAnimations; i++)
ms_aAnimations[i].Shutdown();
+ ms_animCache.Shutdown();
+
delete[] ms_aAnimAssocGroups;
}
void
CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)
{
- if(!hier->compressed){
- if(hier->linkPtr){
- hier->linkPtr->Remove();
- ms_animCache.head.Insert(hier->linkPtr);
- }
+ if(hier->compressed2){
+ if(hier->totalLength == 0.0f)
+ hier->CalcTotalTimeCompressed();
}else{
- CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
- if(link == nil){
- ms_animCache.tail.prev->item->RemoveUncompressedData();
- ms_animCache.Remove(ms_animCache.tail.prev);
- link = ms_animCache.Insert(hier);
+ if(!hier->compressed){
+ if(hier->linkPtr){
+ hier->linkPtr->Remove();
+ ms_animCache.head.Insert(hier->linkPtr);
+ }
+ }else{
+ CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
+ if(link == nil){
+ ms_animCache.tail.prev->item->RemoveUncompressedData();
+ ms_animCache.Remove(ms_animCache.tail.prev);
+ link = ms_animCache.Insert(hier);
+ }
+ hier->linkPtr = link;
+ hier->Uncompress();
}
- hier->linkPtr = link;
- hier->Uncompress();
+ }
+}
+
+void
+CAnimManager::RemoveFromUncompressedCache(CAnimBlendHierarchy *hier)
+{
+ if(hier->linkPtr){
+ ms_animCache.Remove(hier->linkPtr);
+ hier->linkPtr = nil;
}
}
@@ -612,6 +684,73 @@ CAnimManager::GetAnimationBlock(const char *name)
return nil;
}
+int32
+CAnimManager::GetAnimationBlockIndex(const char *name)
+{
+ int i;
+
+ for(i = 0; i < ms_numAnimBlocks; i++)
+ if(strcasecmp(ms_aAnimBlocks[i].name, name) == 0)
+ return i;
+ return -1;
+}
+
+int32
+CAnimManager::RegisterAnimBlock(const char *name)
+{
+ CAnimBlock *animBlock = GetAnimationBlock(name);
+ if(animBlock == nil){
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, name, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = 0;
+ assert(animBlock->refCount == 0);
+ }
+ return animBlock - ms_aAnimBlocks;
+}
+
+int32
+CAnimManager::GetNumRefsToAnimBlock(int32 block)
+{
+ return ms_aAnimBlocks[block].refCount;
+}
+
+void
+CAnimManager::AddAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount++;
+}
+
+void
+CAnimManager::RemoveAnimBlockRefWithoutDelete(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+}
+
+void
+CAnimManager::RemoveAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+ if(ms_aAnimBlocks[block].refCount == 0)
+ CStreaming::RemoveAnim(block);
+}
+
+void
+CAnimManager::RemoveAnimBlock(int32 block)
+{
+ int i;
+ CAnimBlock *animblock;
+
+ animblock = &ms_aAnimBlocks[block];
+ debug("Removing ANIMS %s\n", animblock->name);
+ for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++)
+ if(ms_aAnimAssocGroups[i].animBlock == animblock)
+ ms_aAnimAssocGroups[i].DestroyAssociations();
+ for(i = 0; i < animblock->numAnims; i++)
+ ms_aAnimations[animblock->firstIndex + i].Shutdown();
+ animblock->isLoaded = false;
+ animblock->refCount = 0;
+}
+
CAnimBlendHierarchy*
CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
{
@@ -619,7 +758,7 @@ CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];
for(i = 0; i < animBlock->numAnims; i++){
- if(!CGeneral::faststricmp(hier->name, name))
+ if(strcasecmp(hier->name, name) == 0)
return hier;
hier++;
}
@@ -740,23 +879,32 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a
void
CAnimManager::LoadAnimFiles(void)
{
- int i, j;
-
LoadAnimFile("ANIM\\PED.IFP");
-
- // Create all assoc groups
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
+ CreateAnimAssocGroups();
+}
+
+void
+CAnimManager::CreateAnimAssocGroups(void)
+{
+ int i, j;
+
for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){
+ CAnimBlock *block = GetAnimationBlock(ms_aAnimAssocDefinitions[i].blockName);
+ if(block == nil || !block->isLoaded || ms_aAnimAssocGroups[i].assocList)
+ continue;
+
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex);
RpClump *clump = (RpClump*)mi->CreateInstance();
RpAnimBlendClumpInit(clump);
CAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i];
const AnimAssocDefinition *def = &ms_aAnimAssocDefinitions[i];
+ group->groupId = i;
+ group->firstAnimId = def->animDescs[0].animId;
group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims);
for(j = 0; j < group->numAssociations; j++)
group->GetAnimation(j)->flags |= def->animDescs[j].flags;
#ifdef PED_SKIN
- // forgot on xbox/android
if(IsClumpSkinned(clump))
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
#endif
@@ -767,15 +915,16 @@ CAnimManager::LoadAnimFiles(void)
void
CAnimManager::LoadAnimFile(const char *filename)
{
- int fd;
- fd = CFileMgr::OpenFile(filename, "rb");
- assert(fd > 0);
- LoadAnimFile(fd, true);
- CFileMgr::CloseFile(fd);
+ RwStream *stream;
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
+ assert(stream);
+ LoadAnimFile(stream, true);
+ RwStreamClose(stream, nil);
}
+//--MIAMI: done (except maybe implement some unimplemented compression?)
void
-CAnimManager::LoadAnimFile(int fd, bool compress)
+CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32])
{
#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)
struct IfpHeader {
@@ -783,127 +932,122 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
uint32 size;
};
IfpHeader anpk, info, name, dgan, cpan, anim;
- int numANPK;
char buf[256];
- int i, j, k, l;
+ int j, k, l;
float *fbuf = (float*)buf;
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- if(strncmp(anpk.ident, "ANLF", 4) == 0){
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, buf, anpk.size);
- numANPK = *(int*)buf;
- }else if(strncmp(anpk.ident, "ANPK", 4) == 0){
- CFileMgr::Seek(fd, -8, 1);
- numANPK = 1;
+ // block name
+ RwStreamRead(stream, &anpk, sizeof(IfpHeader));
+ ROUNDSIZE(anpk.size);
+ RwStreamRead(stream, &info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ CAnimBlock *animBlock = GetAnimationBlock(buf+4);
+ if(animBlock){
+ if(animBlock->numAnims == 0){
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
+ }
+ }else{
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
}
- for(i = 0; i < numANPK; i++){
- // block name
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
- strncpy(animBlock->name, buf+4, 24);
- animBlock->numAnims = *(int*)buf;
+ debug("Loading ANIMS %s\n", animBlock->name);
+ animBlock->isLoaded = true;
- animBlock->firstIndex = ms_numAnimations;
+ int animIndex = animBlock->firstIndex;
+ for(j = 0; j < animBlock->numAnims; j++){
+ assert(animIndex < ARRAY_SIZE(ms_aAnimations));
+ CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
+
+ // animation name
+ RwStreamRead(stream, &name, sizeof(IfpHeader));
+ ROUNDSIZE(name.size);
+ RwStreamRead(stream, buf, name.size);
+ hier->SetName(buf);
- for(j = 0; j < animBlock->numAnims; j++){
- CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++];
+ // TODO(MIAMI)? some unused crap here
+ hier->compressed = false;
+ hier->compressed2 = false;
- // animation name
- CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader));
- ROUNDSIZE(name.size);
- CFileMgr::Read(fd, buf, name.size);
- hier->SetName(buf);
+ // DG info has number of nodes/sequences
+ RwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader));
+ ROUNDSIZE(dgan.size);
+ RwStreamRead(stream, (char*)&info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ hier->numSequences = *(int*)buf;
+ hier->sequences = new CAnimBlendSequence[hier->numSequences];
- // DG info has number of nodes/sequences
- CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader));
+ CAnimBlendSequence *seq = hier->sequences;
+ for(k = 0; k < hier->numSequences; k++, seq++){
+ // Each node has a name and key frames
+ RwStreamRead(stream, &cpan, sizeof(IfpHeader));
ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- hier->numSequences = *(int*)buf;
- hier->sequences = new CAnimBlendSequence[hier->numSequences];
-
- CAnimBlendSequence *seq = hier->sequences;
- for(k = 0; k < hier->numSequences; k++, seq++){
- // Each node has a name and key frames
- CFileMgr::Read(fd, (char*)&cpan, sizeof(IfpHeader));
- ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&anim, sizeof(IfpHeader));
- ROUNDSIZE(anim.size);
- CFileMgr::Read(fd, buf, anim.size);
- int numFrames = *(int*)(buf+28);
+ RwStreamRead(stream, &anim, sizeof(IfpHeader));
+ ROUNDSIZE(anim.size);
+ RwStreamRead(stream, buf, anim.size);
+ int numFrames = *(int*)(buf+28);
#ifdef PED_SKIN
- if(anim.size == 44)
- seq->SetBoneTag(*(int*)(buf+40));
+ if(anim.size == 44)
+ seq->SetBoneTag(*(int*)(buf+40));
#endif
- seq->SetName(buf);
- if(numFrames == 0)
- continue;
-
- CFileMgr::Read(fd, (char*)&info, sizeof(info));
- if(strncmp(info.ident, "KR00", 4) == 0){
- seq->SetNumFrames(numFrames, false);
- KeyFrame *kf = seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x14);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->deltaTime = fbuf[4]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRT0", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x20);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- kf->deltaTime = fbuf[7]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRTS", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x2C);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- // scaling ignored
- kf->deltaTime = fbuf[10]; // absolute time here
- }
- }
+ seq->SetName(buf);
+ if(numFrames == 0)
+ continue;
- // convert absolute time to deltas
- for(l = seq->numFrames-1; l > 0; l--){
- KeyFrame *kf1 = seq->GetKeyFrame(l);
- KeyFrame *kf2 = seq->GetKeyFrame(l-1);
- kf1->deltaTime -= kf2->deltaTime;
+ RwStreamRead(stream, &info, sizeof(info));
+ if(strncmp(info.ident, "KR00", 4) == 0){
+ seq->SetNumFrames(numFrames, false, false);
+ KeyFrame *kf = seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x14);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->deltaTime = fbuf[4]; // absolute time here
+ }
+ }else if(strncmp(info.ident, "KRT0", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x20);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ kf->deltaTime = fbuf[7]; // absolute time here
+ }
+ }else if(strncmp(info.ident, "KRTS", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x2C);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ // scaling ignored
+ kf->deltaTime = fbuf[10]; // absolute time here
}
}
-
- hier->RemoveQuaternionFlips();
- if(compress)
- hier->RemoveUncompressedData();
- else
- hier->CalcTotalTime();
}
+
+ hier->RemoveQuaternionFlips();
+ hier->CalcTotalTime();
}
+ if(animIndex > ms_numAnimations)
+ ms_numAnimations = animIndex;
}
void
@@ -913,5 +1057,6 @@ CAnimManager::RemoveLastAnimFile(void)
ms_numAnimBlocks--;
ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;
for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++)
- ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences();
+ ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].Shutdown();
+ ms_aAnimBlocks[ms_numAnimBlocks].isLoaded = false;
}
diff --git a/src/animation/AnimManager.h b/src/animation/AnimManager.h
index de15602c..96239cda 100644
--- a/src/animation/AnimManager.h
+++ b/src/animation/AnimManager.h
@@ -11,37 +11,48 @@ enum AssocGroupId
ASSOCGRP_PLAYER1ARMED,
ASSOCGRP_PLAYER2ARMED,
ASSOCGRP_PLAYERBBBAT,
+ ASSOCGRP_PLAYERCHAINSAW,
ASSOCGRP_SHUFFLE,
ASSOCGRP_OLD,
ASSOCGRP_GANG1,
ASSOCGRP_GANG2,
ASSOCGRP_FAT,
ASSOCGRP_OLDFAT,
+ ASSOCGRP_JOGGER,
ASSOCGRP_WOMAN,
ASSOCGRP_WOMANSHOP,
ASSOCGRP_BUSYWOMAN,
ASSOCGRP_SEXYWOMAN,
- ASSOCGRP_OLDWOMAN,
ASSOCGRP_FATWOMAN,
+ ASSOCGRP_OLDWOMAN,
+ ASSOCGRP_JOGWOMAN,
ASSOCGRP_PANICCHUNKY,
+ ASSOCGRP_SKATE,
ASSOCGRP_PLAYERBACK,
ASSOCGRP_PLAYERLEFT,
ASSOCGRP_PLAYERRIGHT,
ASSOCGRP_ROCKETBACK,
ASSOCGRP_ROCKETLEFT,
ASSOCGRP_ROCKETRIGHT,
+ ASSOCGRP_CHAINSAWBACK,
+ ASSOCGRP_CHAINSAWLEFT,
+ ASSOCGRP_CHAINSAWRIGHT,
- NUM_ANIM_ASSOC_GROUPS
+ NUM_ANIM_ASSOC_GROUPS // should be 61 in the end
};
class CAnimBlendAssociation;
class CAnimBlendAssocGroup;
+#define MAX_ANIMBLOCK_NAME 20
+
// A block of hierarchies
struct CAnimBlock
{
- char name[24];
- int32 firstIndex;
+ char name[MAX_ANIMBLOCK_NAME];
+ bool isLoaded;
+ int16 refCount;
+ int32 firstIndex; // first animtion in ms_aAnimations
int32 numAnims;
};
@@ -75,7 +86,16 @@ public:
static void Initialise(void);
static void Shutdown(void);
static void UncompressAnimation(CAnimBlendHierarchy *anim);
+ static void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier);
+ static CAnimBlock *GetAnimationBlock(int32 block) { return &ms_aAnimBlocks[block]; }
static CAnimBlock *GetAnimationBlock(const char *name);
+ static int32 GetAnimationBlockIndex(const char *name);
+ static int32 RegisterAnimBlock(const char *name);
+ static int32 GetNumRefsToAnimBlock(int32 block);
+ static void AddAnimBlockRef(int32 block);
+ static void RemoveAnimBlockRefWithoutDelete(int32 block);
+ static void RemoveAnimBlockRef(int32 block);
+ static void RemoveAnimBlock(int32 block);
static CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock);
static CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; }
static const char *GetAnimGroupName(AssocGroupId groupId);
@@ -87,6 +107,7 @@ public:
static CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta);
static void LoadAnimFiles(void);
static void LoadAnimFile(const char *filename);
- static void LoadAnimFile(int fd, bool compress);
+ static void LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32] = nil);
+ static void CreateAnimAssocGroups(void);
static void RemoveLastAnimFile(void);
};
diff --git a/src/animation/AnimationId.h b/src/animation/AnimationId.h
index 82fed8bd..37979ae0 100644
--- a/src/animation/AnimationId.h
+++ b/src/animation/AnimationId.h
@@ -61,13 +61,13 @@ enum AnimationId
ANIM_BOMBER,
ANIM_HGUN_RELOAD,
ANIM_AK_RELOAD,
- ANIM_FPS_PUNCH,
- ANIM_FPS_BAT,
- ANIM_FPS_UZI,
- ANIM_FPS_PUMP,
- ANIM_FPS_AK,
- ANIM_FPS_M16,
- ANIM_FPS_ROCKET,
+// ANIM_FPS_PUNCH,
+// ANIM_FPS_BAT,
+// ANIM_FPS_UZI,
+// ANIM_FPS_PUMP,
+// ANIM_FPS_AK,
+// ANIM_FPS_M16,
+// ANIM_FPS_ROCKET,
ANIM_FIGHT_IDLE,
ANIM_FIGHT2_IDLE,
ANIM_FIGHT_SH_F,
diff --git a/src/animation/Bones.cpp b/src/animation/Bones.cpp
index 1608449d..87f3b6e7 100644
--- a/src/animation/Bones.cpp
+++ b/src/animation/Bones.cpp
@@ -2,26 +2,29 @@
#include "PedModelInfo.h"
#include "Bones.h"
-#ifdef PED_SKIN
-
int
ConvertPedNode2BoneTag(int node)
{
switch(node){
- case PED_TORSO: return BONE_waist;
- case PED_MID: return BONE_torso; // this is what Xbox/Mobile use
- // return BONE_mid; // this is what PS2/PC use
- case PED_HEAD: return BONE_head;
- case PED_UPPERARML: return BONE_upperarml;
- case PED_UPPERARMR: return BONE_upperarmr;
- case PED_HANDL: return BONE_Lhand;
- case PED_HANDR: return BONE_Rhand;
- case PED_UPPERLEGL: return BONE_upperlegl;
- case PED_UPPERLEGR: return BONE_upperlegr;
- case PED_FOOTL: return BONE_footl;
- case PED_FOOTR: return BONE_footr;
- case PED_LOWERLEGR: return BONE_lowerlegl;
+ case PED_MID: return BONE_spine1;
+ case PED_HEAD: return BONE_head;
+ case PED_UPPERARML: return BONE_l_upperarm;
+ case PED_UPPERARMR: return BONE_r_upperarm;
+ case PED_HANDL: return BONE_l_hand;
+ case PED_HANDR: return BONE_r_hand;
+ case PED_UPPERLEGL: return BONE_l_thigh;
+ case PED_UPPERLEGR: return BONE_r_thigh;
+ case PED_FOOTL: return BONE_l_foot;
+ case PED_FOOTR: return BONE_r_foot;
+ case PED_LOWERLEGR: return BONE_r_calf;
+ case PED_LOWERLEGL: return BONE_l_calf;
+ case PED_FOREARML: return BONE_l_forearm;
+ case PED_FOREARMR: return BONE_r_forearm;
+ case PED_CLAVICLEL: return BONE_l_clavicle;
+ case PED_CLAVICLER: return BONE_r_clavicle;
+ case PED_NECK: return BONE_neck;
}
+ assert(0 && "this node has no bone");
return -1;
}
@@ -29,24 +32,28 @@ const char*
ConvertBoneTag2BoneName(int tag)
{
switch(tag){
- case BONE_waist: return "Swaist";
- case BONE_upperlegr: return "Supperlegr";
- case BONE_lowerlegr: return "Slowerlegr";
- case BONE_footr: return "Sfootr";
- case BONE_upperlegl: return "Supperlegl";
- case BONE_lowerlegl: return "Slowerlegl";
- case BONE_footl: return "Sfootl";
- case BONE_mid: return "Smid";
- case BONE_torso: return "Storso";
- case BONE_head: return "Shead";
- case BONE_upperarmr: return "Supperarmr";
- case BONE_lowerarmr: return "Slowerarmr";
- case BONE_Rhand: return "SRhand";
- case BONE_upperarml: return "Supperarml";
- case BONE_lowerarml: return "Slowerarml";
- case BONE_Lhand: return "SLhand";
+ case BONE_root: return "Root";
+ case BONE_pelvis: return "Pelvis";
+ case BONE_spine: return "Spine";
+ case BONE_spine1: return "Spine1";
+ case BONE_neck: return "Neck";
+ case BONE_head: return "Head";
+ case BONE_r_clavicle: return "Bip01 R Clavicle";
+ case BONE_r_upperarm: return "R UpperArm";
+ case BONE_r_forearm: return "R Forearm";
+ case BONE_r_hand: return "R Hand";
+ case BONE_r_finger: return "R Fingers";
+ case BONE_l_clavicle: return "Bip01 L Clavicle";
+ case BONE_l_upperarm: return "L UpperArm";
+ case BONE_l_forearm: return "L Forearm";
+ case BONE_l_hand: return "L Hand";
+ case BONE_l_finger: return "L Fingers";
+ case BONE_l_thigh: return "L Thigh";
+ case BONE_l_calf: return "L Calf";
+ case BONE_l_foot: return "L Foot";
+ case BONE_r_thigh: return "R Thigh";
+ case BONE_r_calf: return "R Calf";
+ case BONE_r_foot: return "R Foot";
}
return nil;
}
-
-#endif
diff --git a/src/animation/Bones.h b/src/animation/Bones.h
index 38d91ba3..e133fd7f 100644
--- a/src/animation/Bones.h
+++ b/src/animation/Bones.h
@@ -2,22 +2,28 @@
enum BoneTag
{
- BONE_waist,
- BONE_upperlegr,
- BONE_lowerlegr,
- BONE_footr,
- BONE_upperlegl,
- BONE_lowerlegl,
- BONE_footl,
- BONE_mid,
- BONE_torso,
- BONE_head,
- BONE_upperarmr,
- BONE_lowerarmr,
- BONE_Rhand,
- BONE_upperarml,
- BONE_lowerarml,
- BONE_Lhand,
+ BONE_root = 0,
+ BONE_pelvis = 1,
+ BONE_spine = 2,
+ BONE_spine1 = 3,
+ BONE_neck = 4,
+ BONE_head = 5,
+ BONE_l_clavicle = 31,
+ BONE_l_upperarm = 32,
+ BONE_l_forearm = 33,
+ BONE_l_hand = 34,
+ BONE_l_finger = 35,
+ BONE_r_clavicle = 21,
+ BONE_r_upperarm = 22,
+ BONE_r_forearm = 23,
+ BONE_r_hand = 24,
+ BONE_r_finger = 25,
+ BONE_l_thigh = 41,
+ BONE_l_calf = 42,
+ BONE_l_foot = 43,
+ BONE_r_thigh = 51,
+ BONE_r_calf = 52,
+ BONE_r_foot = 53,
};
int ConvertPedNode2BoneTag(int node);
diff --git a/src/animation/CutsceneMgr.cpp b/src/animation/CutsceneMgr.cpp
index 0db54c4b..035c2b49 100644
--- a/src/animation/CutsceneMgr.cpp
+++ b/src/animation/CutsceneMgr.cpp
@@ -16,7 +16,6 @@
#include "World.h"
#include "PlayerPed.h"
#include "Wanted.h"
-#include "CutsceneHead.h"
#include "RpAnimBlend.h"
#include "ModelIndices.h"
#include "TempColModels.h"
@@ -185,23 +184,28 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
CGame::DrasticTidyUpMemory(true);
strcpy(ms_cutsceneName, szCutsceneName);
- file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
+
+ RwStream *stream;
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
+ assert(stream);
// Load animations
sprintf(gString, "%s.IFP", szCutsceneName);
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
CStreaming::MakeSpaceFor(size << 11);
CStreaming::ImGonnaUseStreamingMemory();
- CFileMgr::Seek(file, offset << 11, SEEK_SET);
- CAnimManager::LoadAnimFile(file, false);
+ RwStreamSkip(stream, offset << 11);
+ CAnimManager::LoadAnimFile(stream, false);
ms_cutsceneAssociations.CreateAssociations(szCutsceneName);
CStreaming::IHaveUsedStreamingMemory();
ms_animLoaded = true;
} else {
ms_animLoaded = false;
}
+ RwStreamClose(stream, nil);
// Load camera data
+ file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
sprintf(gString, "%s.DAT", szCutsceneName);
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
CFileMgr::Seek(file, offset << 11, SEEK_SET);
@@ -235,16 +239,6 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
}
void
-CCutsceneMgr::SetHeadAnim(const char *animName, CObject *pObject)
-{
- CCutsceneHead *pCutsceneHead = (CCutsceneHead*)pObject;
- char szAnim[CUTSCENENAMESIZE * 2];
-
- sprintf(szAnim, "%s_%s", ms_cutsceneName, animName);
- pCutsceneHead->PlayAnimation(szAnim);
-}
-
-void
CCutsceneMgr::FinishCutscene()
{
CCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f;
@@ -302,11 +296,7 @@ CCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject)
CCutsceneHead *
CCutsceneMgr::AddCutsceneHead(CObject *pObject, int modelId)
{
- CCutsceneHead *pHead = new CCutsceneHead(pObject);
- pHead->SetModelIndex(modelId);
- CWorld::Add(pHead);
- ms_pCutsceneObjects[ms_numCutsceneObjs++] = pHead;
- return pHead;
+ return nil;
}
CCutsceneObject *
diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h
index bfdcdb57..18eff0e5 100644
--- a/src/animation/CutsceneMgr.h
+++ b/src/animation/CutsceneMgr.h
@@ -41,7 +41,6 @@ public:
static void Shutdown(void);
static void LoadCutsceneData(const char *szCutsceneName);
static void FinishCutscene(void);
- static void SetHeadAnim(const char *animName, CObject *pObject);
static void SetupCutsceneToStart(void);
static void SetCutsceneAnim(const char *animName, CObject *pObject);
static CCutsceneHead *AddCutsceneHead(CObject *pObject, int modelId);
diff --git a/src/animation/FrameUpdate.cpp b/src/animation/FrameUpdate.cpp
index 8697e7c6..03e67017 100644
--- a/src/animation/FrameUpdate.cpp
+++ b/src/animation/FrameUpdate.cpp
@@ -6,6 +6,8 @@
#include "AnimBlendAssociation.h"
#include "RpAnimBlend.h"
+//--MIAMI: file done
+
CAnimBlendClumpData *gpAnimBlendClump;
// PS2 names without "NonSkinned"
@@ -17,7 +19,6 @@ void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);
-
void
FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg)
{
@@ -227,8 +228,6 @@ FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame,
RwMatrixUpdate(mat);
}
-#ifdef PED_SKIN
-
void
FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)
{
@@ -258,11 +257,9 @@ FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)
(*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;
@@ -318,11 +315,9 @@ FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void
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;
@@ -440,4 +435,9 @@ FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, vo
}
}
-#endif
+void
+FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg)
+{
+ if(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity)
+ FrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);
+}
diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp
index be70ad66..8671e95d 100644
--- a/src/animation/RpAnimBlend.cpp
+++ b/src/animation/RpAnimBlend.cpp
@@ -9,9 +9,9 @@
#include "AnimBlendHierarchy.h"
#include "AnimBlendAssociation.h"
#include "RpAnimBlend.h"
-#ifdef PED_SKIN
#include "PedModelInfo.h"
-#endif
+
+//--MIAMI: file done
RwInt32 ClumpOffset;
@@ -141,7 +141,6 @@ FrameInitCBskin(AnimBlendFrameData *frameData, void*)
frameData->flag = 0;
}
-#ifdef PED_SKIN
void
RpAnimBlendClumpInitSkinned(RpClump *clump)
{
@@ -155,7 +154,7 @@ RpAnimBlendClumpInitSkinned(RpClump *clump)
RpAnimBlendAllocateData(clump);
clumpData = *RPANIMBLENDCLUMPDATA(clump);
- atomic = IsClumpSkinned(clump);
+ atomic = GetFirstAtomic(clump);
assert(atomic);
skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));
assert(skin);
@@ -175,7 +174,6 @@ RpAnimBlendClumpInitSkinned(RpClump *clump)
clumpData->ForAllFrames(FrameInitCBskin, nil);
clumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION;
}
-#endif
void
RpAnimBlendClumpInitNotSkinned(RpClump *clump)
@@ -199,11 +197,9 @@ RpAnimBlendClumpInitNotSkinned(RpClump *clump)
void
RpAnimBlendClumpInit(RpClump *clump)
{
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
RpAnimBlendClumpInitSkinned(clump);
else
-#endif
RpAnimBlendClumpInitNotSkinned(clump);
}
@@ -363,7 +359,6 @@ FillFrameArrayCBnonskin(AnimBlendFrameData *frame, void *arg)
frames[CVisibilityPlugins::GetFrameHierarchyId(frame->frame)] = frame;
}
-#ifdef PED_SKIN
void
RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames)
{
@@ -373,22 +368,18 @@ RpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames)
for(i = PED_MID; i < PED_NODE_MAX; i++)
frames[i] = &clumpData->frames[RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(i))];
}
-#endif
void
RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames)
{
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
RpAnimBlendClumpFillFrameArraySkin(clump, frames);
else
-#endif
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCBnonskin, frames);
}
AnimBlendFrameData *pFrameDataFound;
-// FrameFindCallBack on PS2
void
FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
{
@@ -397,7 +388,6 @@ FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
pFrameDataFound = frame;
}
-#ifdef PED_SKIN
void
FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
{
@@ -405,25 +395,55 @@ FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
if(name && CGeneral::faststricmp(name, (char*)arg) == 0)
pFrameDataFound = frame;
}
-#endif
+
+void
+FrameFindByBoneCB(AnimBlendFrameData *frame, void *arg)
+{
+ if(frame->nodeID == (int32)(uintptr)arg)
+ pFrameDataFound = frame;
+}
AnimBlendFrameData*
RpAnimBlendClumpFindFrame(RpClump *clump, const char *name)
{
pFrameDataFound = nil;
-#ifdef PED_SKIN
if(IsClumpSkinned(clump))
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name);
else
-#endif
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name);
return pFrameDataFound;
}
+AnimBlendFrameData*
+RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag)
+{
+ pFrameDataFound = nil;
+ (*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByBoneCB, (void*)boneTag);
+ return pFrameDataFound;
+}
+
void
-RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
+RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes)
{
+ CAnimBlendNode **node;
int i;
+
+ for(node = updateData->nodes; *node; node++){
+ CAnimBlendAssociation *a = (*node)->association;
+ for(i = 0; i < numNodes; i++)
+ if((frames[i].flag & AnimBlendFrameData::VELOCITY_EXTRACTION) == 0 ||
+ gpAnimBlendClump->velocity == nil){
+ if((*node)[i].sequence)
+ (*node)[i].FindKeyFrame(a->currentTime - a->timeStep);
+ }
+ }
+}
+
+void
+RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta, bool doRender)
+{
+ int i;
+ CAnimBlendAssociation *assoc;
AnimBlendFrameUpdateData updateData;
float totalLength = 0.0f;
float totalBlend = 0.0f;
@@ -439,30 +459,45 @@ RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
updateData.foobar = 0;
for(link = clumpData->link.next; link; link = next){
next = link->next;
- CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);
+ assoc = CAnimBlendAssociation::FromLink(link);
if(assoc->UpdateBlend(timeDelta)){
- // CAnimManager::UncompressAnimation(v6->hierarchy)
- updateData.nodes[i++] = assoc->GetNode(0);
- if(assoc->flags & ASSOC_MOVEMENT){
- totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;
- totalBlend += assoc->blendAmount;
+ if(assoc->hierarchy->sequences){
+ //CAnimManager::UncompressAnimation(v6->hierarchy)
+ if(i < 11)
+ updateData.nodes[i++] = assoc->GetNode(0);
+ if(assoc->flags & ASSOC_MOVEMENT){
+ totalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;
+ totalBlend += assoc->blendAmount;
+ }else
+ updateData.foobar = 1;
}else
- updateData.foobar = 1;
+ debug("anim %s is not loaded\n", assoc->hierarchy->name);
}
}
+
+ for(link = clumpData->link.next; link; link = link->next){
+ assoc = CAnimBlendAssociation::FromLink(link);
+ assoc->UpdateTimeStep(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);
+ }
+
updateData.nodes[i] = nil;
-#ifdef PED_SKIN
- if(IsClumpSkinned(clump))
- clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData);
- else
-#endif
- clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData);
+ if(doRender){
+ if(clumpData->frames[0].flag & AnimBlendFrameData::UPDATE_KEYFRAMES)
+ RpAnimBlendNodeUpdateKeyframes(clumpData->frames, &updateData, clumpData->numFrames);
+ if(IsClumpSkinned(clump))
+ clumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData);
+ else
+ clumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData);
+ clumpData->frames[0].flag &= ~AnimBlendFrameData::UPDATE_KEYFRAMES;
+ }else{
+ clumpData->ForAllFrames(FrameUpdateCallBackOffscreen, &updateData);
+ clumpData->frames[0].flag |= AnimBlendFrameData::UPDATE_KEYFRAMES;
+ }
for(link = clumpData->link.next; link; link = link->next){
- CAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);
- float relSpeed = totalLength == 0.0f ? 1.0f : totalBlend/totalLength;
- assoc->UpdateTime(timeDelta, relSpeed);
+ assoc = CAnimBlendAssociation::FromLink(link);
+ assoc->UpdateTime(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);
}
RwFrameUpdateObjects(RpClumpGetFrame(clump));
}
diff --git a/src/animation/RpAnimBlend.h b/src/animation/RpAnimBlend.h
index 838c8816..d0f7a114 100644
--- a/src/animation/RpAnimBlend.h
+++ b/src/animation/RpAnimBlend.h
@@ -26,6 +26,7 @@ void RpAnimBlendClumpInit(RpClump *clump);
bool RpAnimBlendClumpIsInitialized(RpClump *clump);
void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);
AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);
+AnimBlendFrameData *RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag);
void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);
CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);
CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet);
@@ -34,9 +35,11 @@ CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int
CAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n);
CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask);
CAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump);
-void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta);
+void RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes);
+void RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta, bool doRender = true);
extern CAnimBlendClumpData *gpAnimBlendClump;
void FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg);
void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);
+void FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg);