animation compression from PS2

This commit is contained in:
aap 2020-11-16 22:43:15 +01:00
parent 5335b46cbb
commit 3564b85b4e
6 changed files with 133 additions and 10 deletions

View File

@ -13,7 +13,7 @@ enum {
ASSOC_MOVEMENT = 0x20, // ??? ASSOC_MOVEMENT = 0x20, // ???
ASSOC_HAS_TRANSLATION = 0x40, ASSOC_HAS_TRANSLATION = 0x40,
ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void) ASSOC_WALK = 0x80, // for CPed::PlayFootSteps(void)
ASSOC_FLAG_XPRESS = 0x100, // only used by xpress scratch, see CPed::Chat(void) ASSOC_IDLE = 0x100, // only used by xpress scratch, see CPed::Chat(void)
ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void) ASSOC_NOWALK = 0x200, // see CPed::PlayFootSteps(void)
ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played ASSOC_BLOCK = 0x400, // unused in assoc description, blocks other anims from being played
ASSOC_FRONTAL = 0x800, // anims that we fall to front ASSOC_FRONTAL = 0x800, // anims that we fall to front

View File

@ -30,15 +30,14 @@ void
CAnimBlendHierarchy::CalcTotalTime(void) CAnimBlendHierarchy::CalcTotalTime(void)
{ {
int i, j; int i, j;
float totalTime = 0.0f; totalLength = 0.0f;
for(i = 0; i < numSequences; i++){ for(i = 0; i < numSequences; i++){
float seqTime = 0.0f; float seqTime = 0.0f;
for(j = 0; j < sequences[i].numFrames; j++) for(j = 0; j < sequences[i].numFrames; j++)
seqTime += sequences[i].GetKeyFrame(j)->deltaTime; seqTime += sequences[i].GetKeyFrame(j)->deltaTime;
totalTime = Max(totalTime, seqTime); totalLength = Max(totalLength, seqTime);
} }
totalLength = totalTime;
} }
void void
@ -61,6 +60,12 @@ CAnimBlendHierarchy::RemoveAnimSequences(void)
void void
CAnimBlendHierarchy::Uncompress(void) CAnimBlendHierarchy::Uncompress(void)
{ {
#ifdef ANIM_COMPRESSION
int i;
assert(compressed);
for(i = 0; i < numSequences; i++)
sequences[i].Uncompress();
#endif
if(totalLength == 0.0f) if(totalLength == 0.0f)
CalcTotalTime(); CalcTotalTime();
compressed = 0; compressed = 0;
@ -69,6 +74,11 @@ CAnimBlendHierarchy::Uncompress(void)
void void
CAnimBlendHierarchy::RemoveUncompressedData(void) CAnimBlendHierarchy::RemoveUncompressedData(void)
{ {
// useless #ifdef ANIM_COMPRESSION
int i;
assert(!compressed);
for(i = 0; i < numSequences; i++)
sequences[i].RemoveUncompressedData();
#endif
compressed = 1; compressed = 1;
} }

View File

@ -15,6 +15,7 @@ CAnimBlendSequence::CAnimBlendSequence(void)
CAnimBlendSequence::~CAnimBlendSequence(void) CAnimBlendSequence::~CAnimBlendSequence(void)
{ {
assert(keyFramesCompressed == nil);
if(keyFrames) if(keyFrames)
RwFree(keyFrames); RwFree(keyFrames);
} }
@ -60,3 +61,106 @@ CAnimBlendSequence::RemoveQuaternionFlips(void)
last = frame->rotation; last = frame->rotation;
} }
} }
void
CAnimBlendSequence::Uncompress(void)
{
int i;
if(numFrames == 0)
return;
float rotScale = 1.0f/4096.0f;
float timeScale = 1.0f/60.0f;
float transScale = 1.0f/128.0f;
if(type & KF_TRANS){
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans));
KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed;
KeyFrameTrans *kf = (KeyFrameTrans*)newKfs;
for(i = 0; i < numFrames; i++){
kf->rotation.x = ckf->rot[0]*rotScale;
kf->rotation.y = ckf->rot[1]*rotScale;
kf->rotation.z = ckf->rot[2]*rotScale;
kf->rotation.w = ckf->rot[3]*rotScale;
kf->deltaTime = ckf->deltaTime*timeScale;
kf->translation.x = ckf->trans[0]*transScale;
kf->translation.y = ckf->trans[1]*transScale;
kf->translation.z = ckf->trans[2]*transScale;
kf++;
ckf++;
}
keyFrames = newKfs;
}else{
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrame));
KeyFrameCompressed *ckf = (KeyFrameCompressed*)keyFramesCompressed;
KeyFrame *kf = (KeyFrame*)newKfs;
for(i = 0; i < numFrames; i++){
kf->rotation.x = ckf->rot[0]*rotScale;
kf->rotation.y = ckf->rot[1]*rotScale;
kf->rotation.z = ckf->rot[2]*rotScale;
kf->rotation.w = ckf->rot[3]*rotScale;
kf->deltaTime = ckf->deltaTime*timeScale;
kf++;
ckf++;
}
keyFrames = newKfs;
}
RwFree(keyFramesCompressed);
keyFramesCompressed = nil;
}
void
CAnimBlendSequence::CompressKeyframes(void)
{
int i;
if(numFrames == 0)
return;
float rotScale = 4096.0f;
float timeScale = 60.0f;
float transScale = 128.0f;
if(type & KF_TRANS){
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed));
KeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs;
KeyFrameTrans *kf = (KeyFrameTrans*)keyFrames;
for(i = 0; i < numFrames; i++){
ckf->rot[0] = kf->rotation.x*rotScale;
ckf->rot[1] = kf->rotation.y*rotScale;
ckf->rot[2] = kf->rotation.z*rotScale;
ckf->rot[3] = kf->rotation.w*rotScale;
ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
ckf->trans[0] = kf->translation.x*transScale;
ckf->trans[1] = kf->translation.y*transScale;
ckf->trans[2] = kf->translation.z*transScale;
kf++;
ckf++;
}
keyFramesCompressed = newKfs;
}else{
void *newKfs = RwMalloc(numFrames * sizeof(KeyFrameCompressed));
KeyFrameCompressed *ckf = (KeyFrameCompressed*)newKfs;
KeyFrame *kf = (KeyFrame*)keyFrames;
for(i = 0; i < numFrames; i++){
ckf->rot[0] = kf->rotation.x*rotScale;
ckf->rot[1] = kf->rotation.y*rotScale;
ckf->rot[2] = kf->rotation.z*rotScale;
ckf->rot[3] = kf->rotation.w*rotScale;
ckf->deltaTime = kf->deltaTime*timeScale + 0.5f;
kf++;
ckf++;
}
keyFramesCompressed = newKfs;
}
}
void
CAnimBlendSequence::RemoveUncompressedData(void)
{
if(numFrames == 0)
return;
CompressKeyframes();
RwFree(keyFrames);
keyFrames = nil;
}

View File

@ -12,6 +12,15 @@ struct KeyFrameTrans : KeyFrame {
CVector translation; CVector translation;
}; };
struct KeyFrameCompressed {
int16 rot[4]; // 4096
int16 deltaTime; // 60
};
struct KeyFrameTransCompressed : KeyFrameCompressed {
int16 trans[3]; // 128
};
// The sequence of key frames of one animated node // The sequence of key frames of one animated node
class CAnimBlendSequence class CAnimBlendSequence
@ -41,10 +50,9 @@ public:
&((KeyFrame*)keyFrames)[n]; &((KeyFrame*)keyFrames)[n];
} }
bool HasTranslation(void) { return !!(type & KF_TRANS); } bool HasTranslation(void) { return !!(type & KF_TRANS); }
// TODO? these are unused void Uncompress(void);
// void Uncompress(void); void CompressKeyframes(void);
// void CompressKeyframes(void); void RemoveUncompressedData(void);
// void RemoveUncompressedData(void);
#ifdef PED_SKIN #ifdef PED_SKIN
void SetBoneTag(int tag) { boneTag = tag; } void SetBoneTag(int tag) { boneTag = tag; }

View File

@ -176,7 +176,7 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
{ ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL }, { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },
{ ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG_XPRESS }, { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE },
{ ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL },
{ ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },

View File

@ -177,6 +177,7 @@ enum Config {
# define GTA_PS2_STUFF # define GTA_PS2_STUFF
# define RANDOMSPLASH # define RANDOMSPLASH
# define VU_COLLISION # define VU_COLLISION
# define ANIM_COMPRESSION
#elif defined GTA_PC #elif defined GTA_PC
# define GTA3_1_1_PATCH # define GTA3_1_1_PATCH
//# define GTA3_STEAM_PATCH //# define GTA3_STEAM_PATCH