mirror of
https://github.com/GTAmodding/re3.git
synced 2024-12-27 10:55:40 +00:00
Merge remote-tracking branch 'upstream/miami' into miami
This commit is contained in:
commit
756e4dd068
27 changed files with 497 additions and 229 deletions
|
@ -3,16 +3,23 @@
|
|||
#include "ctype.h"
|
||||
|
||||
#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)
|
||||
|
@ -43,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;
|
||||
}
|
||||
|
||||
|
@ -102,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);
|
||||
|
@ -118,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];
|
||||
|
@ -128,13 +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();
|
||||
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;
|
||||
}
|
||||
|
@ -144,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];
|
||||
|
@ -155,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
#include "AnimBlendAssociation.h"
|
||||
#include "RwHelper.h"
|
||||
|
||||
//--MIAMI: file done except for one TODO
|
||||
|
||||
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
|
||||
|
@ -146,14 +159,20 @@ CAnimBlendAssociation::Start(float time)
|
|||
flags |= ASSOC_RUNNING;
|
||||
SetCurrentTime(time);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
||||
{
|
||||
if(!IsRunning())
|
||||
return;
|
||||
return true;
|
||||
if(currentTime >= hierarchy->totalLength){
|
||||
flags &= ~ASSOC_RUNNING;
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(MIAMI): we still need this for some reason
|
||||
#ifndef NOT_YET
|
||||
timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
|
||||
#endif
|
||||
currentTime += timeStep;
|
||||
|
||||
if(currentTime >= hierarchy->totalLength){
|
||||
|
@ -163,7 +182,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;
|
||||
|
@ -174,6 +192,7 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
|||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// return whether we still exist after this function
|
||||
|
|
|
@ -37,7 +37,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;
|
||||
|
@ -46,8 +47,8 @@ public:
|
|||
float currentTime;
|
||||
float speed;
|
||||
float timeStep;
|
||||
int32 animId;
|
||||
int32 flags;
|
||||
int16 animId;
|
||||
int16 flags;
|
||||
int32 callbackType;
|
||||
void (*callback)(CAnimBlendAssociation*, void*);
|
||||
void *callbackArg;
|
||||
|
@ -75,7 +76,7 @@ public:
|
|||
void SetCurrentTime(float time);
|
||||
void SyncAnimation(CAnimBlendAssociation *other);
|
||||
void Start(float time);
|
||||
void UpdateTime(float timeDelta, float relSpeed);
|
||||
bool UpdateTime(float timeDelta, float relSpeed);
|
||||
bool UpdateBlend(float timeDelta);
|
||||
|
||||
void SetRun(void) { flags |= ASSOC_RUNNING; }
|
||||
|
@ -86,4 +87,3 @@ public:
|
|||
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(CAnimBlendAssociation) == 0x40, "CAnimBlendAssociation: error");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "AnimBlendClumpData.h"
|
||||
#include "RwHelper.h"
|
||||
|
||||
//--MIAMI: file done
|
||||
|
||||
CAnimBlendClumpData::CAnimBlendClumpData(void)
|
||||
{
|
||||
|
|
|
@ -35,9 +35,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 +47,3 @@ public:
|
|||
#endif
|
||||
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
|
||||
};
|
||||
#ifndef PED_SKIN
|
||||
static_assert(sizeof(CAnimBlendClumpData) == 0x14, "CAnimBlendClumpData: error");
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,5 +23,6 @@ public:
|
|||
prev->next = next;
|
||||
if(next)
|
||||
next->prev = prev;
|
||||
Init();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
#include "AnimBlendAssociation.h"
|
||||
#include "AnimBlendNode.h"
|
||||
|
||||
//--MIAMI: file done
|
||||
|
||||
void
|
||||
CAnimBlendNode::Init(void)
|
||||
{
|
||||
frameA = 0;
|
||||
frameB = 0;
|
||||
frameA = -1;
|
||||
frameB = -1;
|
||||
remainingTime = 0.0f;
|
||||
sequence = nil;
|
||||
association = nil;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -129,6 +155,20 @@ CAnimBlendNode::CalcDeltas(void)
|
|||
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
#include "AnimBlendAssociation.h"
|
||||
#include "AnimBlendAssocGroup.h"
|
||||
#include "AnimManager.h"
|
||||
#include "Streaming.h"
|
||||
|
||||
CAnimBlock CAnimManager::ms_aAnimBlocks[2];
|
||||
CAnimBlendHierarchy CAnimManager::ms_aAnimations[250];
|
||||
//--MIAMI: code done (except for pointless TODO)
|
||||
|
||||
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
|
||||
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
|
||||
int32 CAnimManager::ms_numAnimBlocks;
|
||||
int32 CAnimManager::ms_numAnimations;
|
||||
CAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups;
|
||||
|
@ -564,8 +567,6 @@ CAnimManager::Initialise(void)
|
|||
ms_numAnimations = 0;
|
||||
ms_numAnimBlocks = 0;
|
||||
ms_animCache.Init(25);
|
||||
|
||||
// dumpanimdata();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -573,31 +574,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 +630,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 +704,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++;
|
||||
}
|
||||
|
@ -739,24 +824,33 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a
|
|||
|
||||
void
|
||||
CAnimManager::LoadAnimFiles(void)
|
||||
{
|
||||
LoadAnimFile("ANIM\\PED.IFP");
|
||||
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
|
||||
CreateAnimAssocGroups();
|
||||
}
|
||||
|
||||
void
|
||||
CAnimManager::CreateAnimAssocGroups(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
LoadAnimFile("ANIM\\PED.IFP");
|
||||
|
||||
// Create all assoc groups
|
||||
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
|
||||
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 = &CAnimManager::ms_aAnimAssocGroups[i];
|
||||
const AnimAssocDefinition *def = &CAnimManager::ms_aAnimAssocDefinitions[i];
|
||||
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 +861,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 +878,130 @@ 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));
|
||||
debug("Loading ANIMS %s\n", animBlock->name);
|
||||
animBlock->isLoaded = true;
|
||||
|
||||
int animIndex = animBlock->firstIndex;
|
||||
for(j = 0; j < animBlock->numAnims; j++){
|
||||
CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
|
||||
|
||||
// animation name
|
||||
RwStreamRead(stream, &name, sizeof(IfpHeader));
|
||||
ROUNDSIZE(name.size);
|
||||
RwStreamRead(stream, buf, name.size);
|
||||
hier->SetName(buf);
|
||||
|
||||
// TODO(MIAMI)? some unused crap here
|
||||
hier->compressed = false;
|
||||
hier->compressed2 = false;
|
||||
|
||||
// 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);
|
||||
CFileMgr::Read(fd, buf, info.size);
|
||||
CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
|
||||
strncpy(animBlock->name, buf+4, 24);
|
||||
animBlock->numAnims = *(int*)buf;
|
||||
RwStreamRead(stream, buf, info.size);
|
||||
hier->numSequences = *(int*)buf;
|
||||
hier->sequences = new CAnimBlendSequence[hier->numSequences];
|
||||
|
||||
animBlock->firstIndex = ms_numAnimations;
|
||||
|
||||
for(j = 0; j < animBlock->numAnims; j++){
|
||||
CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++];
|
||||
|
||||
// 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
|
||||
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;
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// 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;
|
||||
}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();
|
||||
/*
|
||||
// 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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
hier->RemoveQuaternionFlips();
|
||||
hier->CalcTotalTime();
|
||||
}
|
||||
if(animIndex > ms_numAnimations)
|
||||
ms_numAnimations = animIndex;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -913,5 +1011,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;
|
||||
}
|
||||
|
|
|
@ -31,17 +31,21 @@ enum AssocGroupId
|
|||
ASSOCGRP_ROCKETLEFT,
|
||||
ASSOCGRP_ROCKETRIGHT,
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -64,8 +68,8 @@ struct AnimAssocDefinition
|
|||
class CAnimManager
|
||||
{
|
||||
static const AnimAssocDefinition ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS];
|
||||
static CAnimBlock ms_aAnimBlocks[2];
|
||||
static CAnimBlendHierarchy ms_aAnimations[250];
|
||||
static CAnimBlock ms_aAnimBlocks[NUMANIMBLOCKS];
|
||||
static CAnimBlendHierarchy ms_aAnimations[NUMANIMATIONS];
|
||||
static int32 ms_numAnimBlocks;
|
||||
static int32 ms_numAnimations;
|
||||
static CAnimBlendAssocGroup *ms_aAnimAssocGroups;
|
||||
|
@ -75,7 +79,15 @@ public:
|
|||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
static void UncompressAnimation(CAnimBlendHierarchy *anim);
|
||||
static void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier);
|
||||
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 +99,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);
|
||||
};
|
||||
|
|
|
@ -185,23 +185,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);
|
||||
|
|
|
@ -386,7 +386,6 @@ RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames)
|
|||
|
||||
AnimBlendFrameData *pFrameDataFound;
|
||||
|
||||
// FrameFindCallBack on PS2
|
||||
void
|
||||
FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
|
||||
{
|
||||
|
@ -395,7 +394,6 @@ FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
|
|||
pFrameDataFound = frame;
|
||||
}
|
||||
|
||||
#ifdef PED_SKIN
|
||||
void
|
||||
FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
|
||||
{
|
||||
|
@ -403,21 +401,33 @@ 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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1529,7 +1529,6 @@ CCamera::UpdateTargetEntity(void)
|
|||
pTargetEntity = FindPlayerVehicle();
|
||||
else{
|
||||
pTargetEntity = FindPlayerPed();
|
||||
#ifndef GTA_PS2_STUFF
|
||||
// this keeps the camera on the player while entering cars
|
||||
if(PLAYER->GetPedState() == PED_ENTER_CAR ||
|
||||
PLAYER->GetPedState() == PED_CARJACK ||
|
||||
|
@ -1539,7 +1538,6 @@ CCamera::UpdateTargetEntity(void)
|
|||
if(!enteringCar)
|
||||
if(Cams[ActiveCam].CamTargetEntity != pTargetEntity)
|
||||
Cams[ActiveCam].CamTargetEntity = pTargetEntity;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool cantOpen = true;
|
||||
|
@ -1558,16 +1556,9 @@ CCamera::UpdateTargetEntity(void)
|
|||
|
||||
if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
|
||||
if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)
|
||||
#ifdef GTA_PS2_STUFF
|
||||
// dunno if this has any amazing effects
|
||||
{
|
||||
#endif
|
||||
pTargetEntity = PLAYER->m_pMyVehicle;
|
||||
if(PLAYER->m_pMyVehicle == nil)
|
||||
pTargetEntity = PLAYER;
|
||||
#ifdef GTA_PS2_STUFF
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(PLAYER->GetPedState() == PED_EXIT_CAR)
|
||||
|
|
|
@ -39,7 +39,7 @@ CColStore::AddColSlot(const char *name)
|
|||
ColDef *def = ms_pColPool->New();
|
||||
assert(def);
|
||||
def->isLoaded = false;
|
||||
def->a = 0;
|
||||
def->unused = 0;
|
||||
def->bounds.left = 1000000.0f;
|
||||
def->bounds.top = 1000000.0f;
|
||||
def->bounds.right = -1000000.0f;
|
||||
|
@ -133,6 +133,7 @@ CColStore::LoadAllCollision(void)
|
|||
for(i = 1; i < COLSTORESIZE; i++)
|
||||
if(GetSlot(i))
|
||||
CStreaming::RequestCol(i, 0);
|
||||
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "templates.h"
|
||||
|
||||
struct ColDef { // made up name
|
||||
int32 a;
|
||||
int32 unused;
|
||||
bool isLoaded;
|
||||
CRect bounds;
|
||||
char name[20];
|
||||
|
|
|
@ -358,7 +358,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
|
|||
|
||||
*dot = '\0';
|
||||
|
||||
if(!CGeneral::faststricmp(dot+1, "DFF")){
|
||||
if(strncasecmp(dot+1, "DFF", 3) == 0){
|
||||
if(CModelInfo::GetModelInfo(direntry.name, &modelId)){
|
||||
bAddToStreaming = true;
|
||||
}else{
|
||||
|
@ -370,13 +370,13 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
|
|||
#endif
|
||||
lastID = -1;
|
||||
}
|
||||
}else if(!CGeneral::faststricmp(dot+1, "TXD")){
|
||||
}else if(strncasecmp(dot+1, "TXD", 3) == 0){
|
||||
modelId = CTxdStore::FindTxdSlot(direntry.name);
|
||||
if(modelId == -1)
|
||||
modelId = CTxdStore::AddTxdSlot(direntry.name);
|
||||
modelId += STREAM_OFFSET_TXD;
|
||||
bAddToStreaming = true;
|
||||
}else if(!CGeneral::faststricmp(dot+1, "COL")){
|
||||
}else if(strncasecmp(dot+1, "COL", 3) == 0){
|
||||
modelId = CColStore::FindColSlot(direntry.name);
|
||||
if(modelId == -1)
|
||||
modelId = CColStore::AddColSlot(direntry.name);
|
||||
|
@ -413,7 +413,7 @@ GetObjectName(int streamId)
|
|||
sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName());
|
||||
else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)
|
||||
sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));
|
||||
else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO)
|
||||
else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM)
|
||||
sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL));
|
||||
// TODO(MIAMI): IFP
|
||||
return objname;
|
||||
|
@ -506,7 +506,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
|
|||
RwStreamClose(stream, &mem);
|
||||
return false;
|
||||
}
|
||||
}else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO){
|
||||
}else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){
|
||||
if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){
|
||||
debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL));
|
||||
RemoveModel(streamId);
|
||||
|
@ -514,6 +514,8 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
|
|||
RwStreamClose(stream, &mem);
|
||||
return false;
|
||||
}
|
||||
}else if(streamId >= STREAM_OFFSET_ANIM){
|
||||
assert(streamId < NUMSTREAMINFO);
|
||||
// TODO(MIAMI): IFP
|
||||
}
|
||||
|
||||
|
@ -829,7 +831,7 @@ CStreaming::RemoveModel(int32 id)
|
|||
CModelInfo::GetModelInfo(id)->DeleteRwObject();
|
||||
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
||||
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
||||
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
|
||||
else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
|
||||
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
||||
// TODO(MIAMI): IFP
|
||||
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
|
||||
|
@ -854,7 +856,7 @@ CStreaming::RemoveModel(int32 id)
|
|||
RpClumpGtaCancelStream();
|
||||
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
||||
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
||||
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
|
||||
else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
|
||||
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
||||
// TODO(MIAMI): IFP
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
enum {
|
||||
STREAM_OFFSET_TXD = MODELINFOSIZE,
|
||||
STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,
|
||||
NUMSTREAMINFO = STREAM_OFFSET_COL+COLSTORESIZE
|
||||
STREAM_OFFSET_ANIM = STREAM_OFFSET_COL+COLSTORESIZE,
|
||||
NUMSTREAMINFO = STREAM_OFFSET_ANIM+NUMANIMBLOCKS
|
||||
};
|
||||
|
||||
enum StreamFlags
|
||||
|
@ -118,16 +119,19 @@ public:
|
|||
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
|
||||
static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }
|
||||
static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }
|
||||
static bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); }
|
||||
static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }
|
||||
static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }
|
||||
static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }
|
||||
static bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); }
|
||||
static void RequestModel(int32 model, int32 flags);
|
||||
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
|
||||
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
|
||||
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
|
||||
static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }
|
||||
static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }
|
||||
static void RequestSubway(void);
|
||||
static void RequestAnim(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_ANIM, flags); }
|
||||
static void ReRequestAnim(int32 col) { ReRequestModel(col + STREAM_OFFSET_ANIM); }
|
||||
static void RequestBigBuildings(eLevelName level);
|
||||
static void RequestBigBuildings(eLevelName level, const CVector &pos);
|
||||
static void InstanceBigBuildings(eLevelName level, const CVector &pos);
|
||||
|
@ -140,6 +144,7 @@ public:
|
|||
static void RemoveModel(int32 id);
|
||||
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
|
||||
static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }
|
||||
static void RemoveAnim(int32 id) { RemoveModel(id + STREAM_OFFSET_ANIM); }
|
||||
static void RemoveUnusedBuildings(eLevelName level);
|
||||
static void RemoveBuildings(eLevelName level);
|
||||
static void RemoveUnusedBigBuildings(eLevelName level);
|
||||
|
@ -149,7 +154,6 @@ public:
|
|||
static bool RemoveLeastUsedModel(uint32 excludeMask);
|
||||
static void RemoveAllUnusedModels(void);
|
||||
static void RemoveUnusedModelsInLoadedList(void);
|
||||
static bool RemoveReferencedTxds(int32 mem);
|
||||
static int32 GetAvailableVehicleSlot(void);
|
||||
static bool IsTxdUsedByRequestedModels(int32 txdId);
|
||||
static bool AddToLoadedVehiclesList(int32 modelId);
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
|
||||
#if (defined(_MSC_VER))
|
||||
extern int strcasecmp(const char *str1, const char *str2);
|
||||
extern int strncasecmp(const char *str1, const char *str2, size_t len);
|
||||
#endif
|
||||
|
||||
#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))
|
||||
|
|
|
@ -38,6 +38,9 @@ enum Config {
|
|||
NUMCUTSCENEOBJECTS = 50, // does not exist in VC
|
||||
// TODO(MIAMI): colmodel pool
|
||||
|
||||
NUMANIMBLOCKS = 35,
|
||||
NUMANIMATIONS = 450,
|
||||
|
||||
NUMTEMPOBJECTS = 30,
|
||||
|
||||
// Path data
|
||||
|
|
|
@ -1678,5 +1678,9 @@ int strcasecmp(const char* str1, const char* str2)
|
|||
{
|
||||
return _strcmpi(str1, str2);
|
||||
}
|
||||
int strncasecmp(const char *str1, const char *str2, size_t len)
|
||||
{
|
||||
return _strnicmp(str1, str2, len);
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -3150,5 +3150,9 @@ int strcasecmp(const char *str1, const char *str2)
|
|||
{
|
||||
return _strcmpi(str1, str2);
|
||||
}
|
||||
int strncasecmp(const char *str1, const char *str2, size_t len)
|
||||
{
|
||||
return _strnicmp(str1, str2, len);
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in a new issue