diff options
Diffstat (limited to 'src/animation')
-rw-r--r-- | src/animation/AnimBlendAssocGroup.cpp | 49 | ||||
-rw-r--r-- | src/animation/AnimBlendAssocGroup.h | 4 | ||||
-rw-r--r-- | src/animation/AnimBlendAssociation.cpp | 38 | ||||
-rw-r--r-- | src/animation/AnimBlendAssociation.h | 22 | ||||
-rw-r--r-- | src/animation/AnimBlendClumpData.cpp | 1 | ||||
-rw-r--r-- | src/animation/AnimBlendClumpData.h | 7 | ||||
-rw-r--r-- | src/animation/AnimBlendHierarchy.cpp | 57 | ||||
-rw-r--r-- | src/animation/AnimBlendHierarchy.h | 4 | ||||
-rw-r--r-- | src/animation/AnimBlendNode.cpp | 46 | ||||
-rw-r--r-- | src/animation/AnimBlendNode.h | 2 | ||||
-rw-r--r-- | src/animation/AnimBlendSequence.cpp | 19 | ||||
-rw-r--r-- | src/animation/AnimBlendSequence.h | 7 | ||||
-rw-r--r-- | src/animation/AnimManager.cpp | 453 | ||||
-rw-r--r-- | src/animation/AnimManager.h | 31 | ||||
-rw-r--r-- | src/animation/AnimationId.h | 14 | ||||
-rw-r--r-- | src/animation/Bones.cpp | 73 | ||||
-rw-r--r-- | src/animation/Bones.h | 38 | ||||
-rw-r--r-- | src/animation/CutsceneMgr.cpp | 28 | ||||
-rw-r--r-- | src/animation/CutsceneMgr.h | 1 | ||||
-rw-r--r-- | src/animation/FrameUpdate.cpp | 16 | ||||
-rw-r--r-- | src/animation/RpAnimBlend.cpp | 101 | ||||
-rw-r--r-- | src/animation/RpAnimBlend.h | 5 |
22 files changed, 675 insertions, 341 deletions
diff --git a/src/animation/AnimBlendAssocGroup.cpp b/src/animation/AnimBlendAssocGroup.cpp index fe419f2a..c3d6b2c1 100644 --- a/src/animation/AnimBlendAssocGroup.cpp +++ b/src/animation/AnimBlendAssocGroup.cpp @@ -8,16 +8,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) @@ -48,6 +54,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; } @@ -107,6 +114,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); @@ -123,8 +139,7 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name) int i; CAnimBlock *animBlock; - if(assocList) - DestroyAssociations(); + DestroyAssociations(); animBlock = CAnimManager::GetAnimationBlock(name); assocList = new CAnimBlendAssociation[animBlock->numAnims]; @@ -133,17 +148,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; } @@ -153,10 +169,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]; @@ -164,7 +178,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 2dff4391..fe9b18e0 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; @@ -76,6 +77,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); @@ -87,5 +89,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 230e22fb..8da34dda 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 a3a2013a..b886e95d 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) { @@ -228,8 +229,6 @@ FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, RwMatrixUpdate(mat); } -#ifdef PED_SKIN - void FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg) { @@ -259,11 +258,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; @@ -319,11 +316,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; @@ -442,4 +437,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); |