base code from last week

This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2025-03-04 17:25:59 +01:00 committed by Stefanos Kornilios Mitsis Poiitidis
parent 3e49dce7af
commit f6cc9c6995
14 changed files with 1628 additions and 295 deletions

View file

@ -18,6 +18,7 @@ MOD_NAME?=
GTA_DIR?=../../miami
GTA_MOD_DIR?=../../miami_mod$(MOD_NAME)
GTA_MOD_IMG_DIR?=$(GTA_MOD_DIR)/img
GTA_MOD_CUTS_DIR=$(GTA_MOD_DIR)/cuts
GTA_MOD_SFX_DIR?=$(GTA_MOD_DIR)/sfx
GTA_MOD_LOOSE_DIR?=$(GTA_MOD_DIR)/loose
@ -28,6 +29,8 @@ REPACK_IMG_DC_DIR?=$(REPACK_DIR)/miami-img-dc
REPACK_SFX_ORIG_DIR?=$(REPACK_DIR)/miami-sfx-orig
REPACK_SFX_DC_DIR?=$(REPACK_DIR)/miami-sfx-dc
REPACK_STREAM_DECODED_DIR?=$(REPACK_DIR)/miami-stream-decoded
REPACK_CUTS_ORIG_DIR?=$(REPACK_DIR)/miami-cuts-orig
REPACK_CUTS_DC_DIR?=$(REPACK_DIR)/miami-cuts-dc
LIBS :=
TEXCONV_FLAGS :=
@ -293,6 +296,9 @@ texconv: $(OBJS_TEXCONV) | pvrtex # You'll have to rebuild pvrtex manually if yo
%.texconv.o: %.cpp
$(CXX) -std=c++2a -c -O0 -g -MMD -MP -o $@ -I../vendor/koshle -I../vendor/librw/src $(INCLUDE) -I../vendor/emu -I../vendor/crypto -I../vendor/TriStripper/include $(DEFINES) -DDC_TEXCONV -DDC_SIM $(TEXCONV_FLAGS) $<
animtool: animtool.cpp
$(CXX) -std=c++17 -o $@ -g -O0 $<
-include $(DEPS)
#### Repacking ####
@ -343,11 +349,18 @@ TEXTURE_DOWNSAMPLE_IMG ?= HALF
-include sfxlooplist.mk
-include wavlist.mk
-include mp3list.mk
-include cuts.mk
IMG_TEXTURES_DC = $(addprefix $(REPACK_IMG_DC_DIR)/, $(IMG_TEXTURES))
IMG_MODELS_DC = $(addprefix $(REPACK_IMG_DC_DIR)/, $(IMG_MODELS))
IMG_IFP_DC = $(addprefix $(REPACK_IMG_DC_DIR)/, $(IMG_IFP))
IMG_MISC_DC = $(addprefix $(REPACK_IMG_DC_DIR)/, $(IMG_MISC))
CUTS_IFP_DC = $(addprefix $(REPACK_CUTS_DC_DIR)/, $(CUTS_IFP))
CUTS_MISC_DC = $(addprefix $(REPACK_CUTS_DC_DIR)/, $(CUTS_MISC))
LOOSE_FILES_DC = $(addprefix $(REPACK_GTA_DIR)/, $(MISC_FILES))
SFX_DC_DIR = $(REPACK_GTA_DIR)/sfx
SFX_DC_RAW = $(SFX_DC_DIR)/sfx_all.raw
SFX_DC_DSC = $(SFX_DC_DIR)/sfx_all.dsc
@ -357,8 +370,12 @@ STREAM_ADPCM_DC = $(addprefix $(REPACK_GTA_DIR)/stream/, $(STREAM_WAV:.wav=.APM)
IMG_TEXTURES_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_TEXTURES))
IMG_MODELS_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_MODELS))
IMG_IFP_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_IFP))
IMG_MISC_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_MISC))
CUTS_IFP_ORIG = $(addprefix $(REPACK_CUTS_ORIG_DIR)/, $(CUTS_IFP))
CUTS_MISC_ORIG = $(addprefix $(REPACK_CUTS_ORIG_DIR)/, $(CUTS_MISC))
SFX_ORIG = $(addprefix $(REPACK_SFX_ORIG_DIR)/, $(SFX_WAV))
SFX_ORIG_LOOP = $(addprefix $(REPACK_SFX_ORIG_DIR)/, $(SFX_LOOP_WAV))
SFX_REPACK_DC_WAV = $(addprefix $(REPACK_SFX_DC_DIR)/, $(SFX_WAV) $(SFX_LOOP_WAV))
@ -367,7 +384,7 @@ STREAM_ADF_DECODED = $(addprefix $(REPACK_STREAM_DECODED_DIR)/, $(STREAM_ADF:.ad
.PRECIOUS: $(SFX_ORIG) $(SFX_REPACK_DC) $(STREAM_ADF_DECODED)
$(REPACK_DIR)/repacked: $(REPACK_GTA_DIR)/models/gta3.img $(REPACK_GTA_DIR)/models/gta3.dir $(LOOSE_FILES_DC) $(STREAM_ADPCM_DC) $(SFX_DC_RAW) $(SFX_DC_DSC)
$(REPACK_DIR)/repacked: $(REPACK_GTA_DIR)/models/gta3.img $(REPACK_GTA_DIR)/models/gta3.dir $(REPACK_GTA_DIR)/anim/cuts.img $(REPACK_GTA_DIR)/anim/cuts.dir $(LOOSE_FILES_DC) $(STREAM_ADPCM_DC) $(SFX_DC_RAW) $(SFX_DC_DSC)
mkdir -p $(@D)
@git archive --format zip --output "$(REPACK_GTA_DIR)/DCA3-$(GIT_VERSION).zip" HEAD
@touch $@
@ -378,7 +395,16 @@ $(REPACK_DIR)/unpacked: imgtool $(GTA_DIR)/models/gta3.img $(GTA_DIR)/models/gta
./imgtool unpack "$(GTA_DIR)/models/gta3" "$(REPACK_IMG_ORIG_DIR)"
@touch $@
$(IMG_TEXTURES_ORIG) $(IMG_MODELS_ORIG) $(IMG_MISC_ORIG): $(REPACK_DIR)/unpacked
$(IMG_TEXTURES_ORIG) $(IMG_MODELS_ORIG) $(IMG_IFP_ORIG) $(IMG_MISC_ORIG): $(REPACK_DIR)/unpacked
@test -f $@
@touch $@
$(REPACK_DIR)/unpacked-cuts: imgtool $(GTA_DIR)/anim/cuts.img $(GTA_DIR)/anim/cuts.dir
mkdir -p $(@D)
./imgtool unpack "$(GTA_DIR)/anim/cuts" "$(REPACK_CUTS_ORIG_DIR)"
@touch $@
$(CUTS_IFP_ORIG) $(CUTS_MISC_ORIG): $(REPACK_DIR)/unpacked-cuts
@test -f $@
@touch $@
@ -418,17 +444,35 @@ $(REPACK_IMG_DC_DIR)/%.TXD: $(REPACK_IMG_ORIG_DIR)/%.TXD texconv
$(REPACK_IMG_DC_DIR)/%.col: $(GTA_MOD_IMG_DIR)/%.col
@mkdir -p $(@D)
cp $< $@
$(REPACK_IMG_DC_DIR)/%.ifp: $(GTA_MOD_IMG_DIR)/%.ifp
$(REPACK_IMG_DC_DIR)/%.ifp: $(GTA_MOD_IMG_DIR)/%.ifp animtool
@mkdir -p $(@D)
cp $< $@
./animtool $< $@
# if not, the extracted img directory
$(REPACK_IMG_DC_DIR)/%.col: $(REPACK_IMG_ORIG_DIR)/%.col
@mkdir -p $(@D)
cp $< $@
$(REPACK_IMG_DC_DIR)/%.ifp: $(REPACK_IMG_ORIG_DIR)/%.ifp
$(REPACK_IMG_DC_DIR)/%.ifp: $(REPACK_IMG_ORIG_DIR)/%.ifp animtool
@mkdir -p $(@D)
./animtool $< $@
### cuts
# First try the mods img directory
$(REPACK_CUTS_DC_DIR)/%.dat: $(GTA_MOD_CUTS_DIR)/%.dat
@mkdir -p $(@D)
cp $< $@
$(REPACK_CUTS_DC_DIR)/%.ifp: $(GTA_MOD_CUTS_DIR)/%.ifp animtool
@mkdir -p $(@D)
./animtool $< $@
# if not, the extracted img directory
$(REPACK_CUTS_DC_DIR)/%.dat: $(REPACK_CUTS_ORIG_DIR)/%.dat
@mkdir -p $(@D)
cp $< $@
$(REPACK_CUTS_DC_DIR)/%.ifp: $(REPACK_CUTS_ORIG_DIR)/%.ifp animtool
@mkdir -p $(@D)
./animtool $< $@
# first try the mods loose directory
$(REPACK_GTA_DIR)/%.dff: $(GTA_MOD_LOOSE_DIR)/%.dff texconv
@ -463,7 +507,23 @@ $(REPACK_GTA_DIR)/%.TXD: $(GTA_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)
$(REPACK_DIR)/packed: $(IMG_TEXTURES_DC) $(IMG_MODELS_DC) $(IMG_MISC_DC)
# first try the mods loose directory
$(REPACK_GTA_DIR)/%.ifp: $(GTA_MOD_LOOSE_DIR)/%.ifp animtool
@mkdir -p $(@D)
./animtool $< $@
$(REPACK_GTA_DIR)/%.IFP: $(GTA_MOD_LOOSE_DIR)/%.IFP animtool
@mkdir -p $(@D)
./animtool $< $@
#if not, the original files
$(REPACK_GTA_DIR)/%.ifp: $(GTA_DIR)/%.ifp animtool
@mkdir -p $(@D)
./animtool $< $@
$(REPACK_GTA_DIR)/%.IFP: $(GTA_DIR)/%.IFP animtool
@mkdir -p $(@D)
./animtool $< $@
$(REPACK_DIR)/packed: $(IMG_TEXTURES_DC) $(IMG_MODELS_DC) $(IMG_IFP_DC) $(IMG_MISC_DC)
mkdir -p $(@D)
mkdir -p "$(REPACK_GTA_DIR)/models/gta3"
./imgtool pack "$(REPACK_GTA_DIR)/models/gta3" "$(REPACK_IMG_DC_DIR)"
@ -472,6 +532,15 @@ $(REPACK_DIR)/packed: $(IMG_TEXTURES_DC) $(IMG_MODELS_DC) $(IMG_MISC_DC)
$(REPACK_GTA_DIR)/models/gta3.img $(REPACK_GTA_DIR)/models/gta3.dir: $(REPACK_DIR)/packed
@touch $@
$(REPACK_DIR)/packed-cuts: $(CUTS_IFP_DC) $(CUTS_MISC_DC)
mkdir -p $(@D)
mkdir -p "$(REPACK_GTA_DIR)/anim/cuts"
./imgtool pack "$(REPACK_GTA_DIR)/anim/cuts" "$(REPACK_CUTS_DC_DIR)"
@touch $@
$(REPACK_GTA_DIR)/anim/cuts.img $(REPACK_GTA_DIR)/anim/cuts.dir: $(REPACK_DIR)/packed-cuts
@touch $@
# sfx processing
$(REPACK_DIR)/unpacked-sfx: extract-sfx $(GTA_DIR)/Audio/sfx.SDT $(GTA_DIR)/Audio/sfx.RAW
mkdir -p $(@D)

151
miami/cuts.mk Normal file
View file

@ -0,0 +1,151 @@
CUTS_IFP = \
ass_1.ifp \
ass_2.ifp \
bank_1.ifp \
bank_2a.ifp \
bank_2b.ifp \
bank_3a.ifp \
bank_3b.ifp \
bank_4.ifp \
bike_1.ifp \
bike_2.ifp \
bike_3.ifp \
bud_1.ifp \
bud_2.ifp \
bud_3.ifp \
cap_1.ifp \
car_1.ifp \
cnt_1a.ifp \
cnt_1b.ifp \
cnt_2.ifp \
cok_1.ifp \
cok_2a.ifp \
cok_2b.ifp \
cok_3.ifp \
cok_4a.ifp \
cok_4a2.ifp \
cok_4b.ifp \
col_1.ifp \
col_2.ifp \
col_3a.ifp \
col_4a.ifp \
col_4b.ifp \
col_5a.ifp \
col_5b.ifp \
cub_1.ifp \
cub_2.ifp \
cub_3.ifp \
cub_4.ifp \
drug_1.ifp \
fin.ifp \
fin_2.ifp \
finale.ifp \
hat_1.ifp \
hat_2.ifp \
hat_3.ifp \
ice_1.ifp \
int_a.ifp \
int_b.ifp \
int_d.ifp \
int_m.ifp \
int_m2.ifp \
law_1a.ifp \
law_1b.ifp \
law_2a.ifp \
law_2b.ifp \
law_2c.ifp \
law_3.ifp \
law_4.ifp \
phil_1.ifp \
phil_2.ifp \
porn_1.ifp \
porn_2.ifp \
porn_3.ifp \
porn_4.ifp \
resc_1a.ifp \
rok_1.ifp \
rok_2.ifp \
rok_3a.ifp \
rok_4a.ifp \
rok_4b.ifp \
rok_4c.ifp \
rok_4d.ifp \
stripa.ifp \
tax_1.ifp \
tex_1.ifp \
tex_2.ifp \
tex_3.ifp
CUTS_MISC = \
ass_1.dat \
ass_2.dat \
bank_1.dat \
bank_2a.dat \
bank_2b.dat \
bank_3a.dat \
bank_3b.dat \
bank_4.dat \
bike_1.dat \
bike_2.dat \
bike_3.dat \
bud_1.dat \
bud_2.dat \
bud_3.dat \
cap_1.dat \
car_1.dat \
cnt_1a.dat \
cnt_1b.dat \
cnt_2.dat \
cok_1.dat \
cok_2a.dat \
cok_2b.dat \
cok_3.dat \
cok_4a.dat \
cok_4a2.dat \
cok_4b.dat \
col_1.dat \
col_2.dat \
col_3a.dat \
col_4a.dat \
col_5a.dat \
col_5b.dat \
cub_1.dat \
cub_2.dat \
cub_3.dat \
cub_4.dat \
drug_1.dat \
fin.dat \
fin_2.dat \
finale.dat \
hat_1.dat \
hat_2.dat \
hat_3.dat \
ice_1.dat \
int_a.dat \
int_b.dat \
int_d.dat \
int_m.dat \
int_m2.dat \
law_1a.dat \
law_1b.dat \
law_2a.dat \
law_2b.dat \
law_2c.dat \
law_3.dat \
law_4.dat \
phil_1.dat \
phil_2.dat \
porn_1.dat \
porn_2.dat \
porn_3.dat \
porn_4.dat \
resc_1a.dat \
rok_1.dat \
rok_2.dat \
rok_3a.dat \
rok_4a.dat \
stripa.dat \
tax_1.dat \
tex_1.dat \
tex_2.dat \
tex_3.dat

View file

@ -45,8 +45,6 @@ MISC_FILES = \
models/generic/zonecylb.DFF \
models/gta3.img \
\
anim/cuts.img \
anim/cuts.dir \
anim/ped.ifp \
\
Icons/app.ico \

View file

@ -2,42 +2,50 @@ IMG_MISC = \
airport.col \
airportN.col \
bank.col \
baseball.ifp \
biked.ifp \
bikeh.ifp \
bikes.ifp \
bikev.ifp \
bridge.col \
buddy.ifp \
chainsaw.ifp \
cisland.col \
CLUB.col \
coach.ifp \
colt45.ifp \
concerth.col \
docks.col \
downtown.col \
downtows.col \
flame.ifp \
golf.col \
grenade.ifp \
haiti.col \
haitin.col \
hotel.col \
islandsf.col \
knife.ifp \
lance.ifp \
lawyers.col \
littleha.col \
m60.ifp \
mall.col \
mansion.col \
medic.ifp \
nbeachbt.col \
nbeach.col \
nbeachw.col \
oceandN.col \
oceandrv.col \
stadint.col \
starisl.col \
stripclb.col \
washintn.col \
washints.col \
yacht.col
IMG_IFP = \
baseball.ifp \
biked.ifp \
bikeh.ifp \
bikes.ifp \
bikev.ifp \
buddy.ifp \
chainsaw.ifp \
coach.ifp \
colt45.ifp \
flame.ifp \
grenade.ifp \
knife.ifp \
lance.ifp \
m60.ifp \
medic.ifp \
playidles.ifp \
python.ifp \
rifle.ifp \
@ -45,15 +53,9 @@ IMG_MISC = \
shotgun.ifp \
skate.ifp \
sniper.ifp \
stadint.col \
starisl.col \
stripclb.col \
strip.ifp \
sunbathe.ifp \
sword.ifp \
tec.ifp \
uzi.ifp \
van.ifp \
washintn.col \
washints.col \
yacht.col
van.ifp

View file

@ -35,21 +35,19 @@ CAnimBlendHierarchy::CalcTotalTime(void)
if(sequences[i].numFrames == 0)
continue;
#endif
float seqTime = 0.0f;
for(j = 0; j < sequences[i].numFrames; j++)
seqTime += sequences[i].GetDeltaTime(j);
float seqTime = sequences->GetEndTime();
totalLength = Max(totalLength, seqTime);
}
}
void
CAnimBlendHierarchy::RemoveQuaternionFlips(void)
{
int i;
// void
// CAnimBlendHierarchy::RemoveQuaternionFlips(void)
// {
// int i;
for(i = 0; i < numSequences; i++)
sequences[i].RemoveQuaternionFlips();
}
// for(i = 0; i < numSequences; i++)
// sequences[i].RemoveQuaternionFlips();
// }
void
CAnimBlendHierarchy::RemoveAnimSequences(void)

View file

@ -21,7 +21,7 @@ public:
void Shutdown(void);
void SetName(char *name);
void CalcTotalTime(void);
void RemoveQuaternionFlips(void);
// void RemoveQuaternionFlips(void);
void RemoveAnimSequences(void);
void Uncompress(void);
void RemoveUncompressedData(void);

View file

@ -6,8 +6,8 @@
void
CAnimBlendNode::Init(void)
{
frameA = -1;
frameB = -1;
_frameA = -1;
_frameB = -1;
remainingTime = 0.0f;
sequence = nil;
association = nil;
@ -29,17 +29,17 @@ CAnimBlendNode::Update(CVector &trans, CQuaternion &rot, float weight)
float blend = association->GetBlendAmount(weight);
if(blend > 0.0f){
float kfAdt = sequence->GetDeltaTime(frameA);
float kfAdt = sequence->GetNextTimeDelta();
float t = kfAdt == 0.0f ? 0.0f : (kfAdt - remainingTime)/kfAdt;
if(sequence->type & CAnimBlendSequence::KF_TRANS){
auto kfAt = sequence->GetTranslation(frameA);
auto kfBt = sequence->GetTranslation(frameB);
trans = kfBt + t*(kfAt - kfBt);
auto kfdAt = sequence->GetNextTranslationDelta();
auto kfBt = sequence->GetCurrentTranslation();
trans = kfBt + t*kfdAt;
trans *= blend;
}
if(sequence->type & CAnimBlendSequence::KF_ROT){
auto kfAr = sequence->GetRotation(frameA);
auto kfBr = sequence->GetRotation(frameB);
auto kfAr = sequence->GetNextRotation();
auto kfBr = sequence->GetCurrentRotation();
rot.Slerp(kfBr, kfAr, theta, invSin, t);
rot *= blend;
}
@ -48,6 +48,7 @@ CAnimBlendNode::Update(CVector &trans, CQuaternion &rot, float weight)
return looped;
}
// TODO: Check this
bool
CAnimBlendNode::NextKeyFrame(void)
{
@ -57,29 +58,29 @@ CAnimBlendNode::NextKeyFrame(void)
return false;
looped = false;
frameB = frameA;
_frameB = _frameA;
// Advance as long as we have to
while(remainingTime <= 0.0f){
frameA++;
_frameA++;
if(frameA >= sequence->numFrames){
if(_frameA >= sequence->numFrames){
// reached end of animation
if(!association->IsRepeating()){
frameA--;
_frameA--;
remainingTime = 0.0f;
return false;
}
looped = true;
frameA = 0;
_frameA = 0;
}
remainingTime += sequence->GetDeltaTime(frameA);
sequence->AdvanceFrame();
remainingTime += sequence->GetNextTimeDelta();
}
frameB = frameA - 1;
if(frameB < 0)
frameB += sequence->numFrames;
_frameB = _frameA - 1;
if(_frameB < 0)
_frameB += sequence->numFrames;
CalcDeltas();
return looped;
@ -129,28 +130,33 @@ CAnimBlendNode::FindKeyFrame(float t)
if(sequence->numFrames < 1)
return false;
frameA = 0;
frameB = frameA;
_frameA = 0;
_frameB = _frameA;
if(sequence->numFrames == 1){
remainingTime = 0.0f;
}else{
// advance until t is between frameB and frameA
while (t > sequence->GetDeltaTime(++frameA)) {
t -= sequence->GetDeltaTime(frameA);
if (frameA + 1 >= sequence->numFrames) {
sequence->AdvanceFrame();
_frameA++;
while (t > sequence->GetNextTimeDelta()) {
t -= sequence->GetNextTimeDelta();
if (_frameA + 1 >= sequence->numFrames) {
// reached end of animation
if (!association->IsRepeating()) {
CalcDeltas();
remainingTime = 0.0f;
return false;
}
frameA = 0;
_frameA = 0;
}
frameB = frameA;
_frameB = _frameA;
sequence->AdvanceFrame();
_frameA++;
}
remainingTime = sequence->GetDeltaTime(frameA) - t;
remainingTime = sequence->GetNextTimeDelta() - t;
}
CalcDeltas();
@ -162,8 +168,8 @@ CAnimBlendNode::CalcDeltas(void)
{
if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
return;
auto kfAr = sequence->GetRotation(frameA);
auto kfBr = sequence->GetRotation(frameB);
auto kfAr = sequence->GetNextRotation();
auto kfBr = sequence->GetCurrentRotation();
float cos = DotProduct(kfAr, kfBr);
if(cos > 1.0f)
cos = 1.0f;
@ -178,12 +184,12 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
float blend = association->GetBlendAmount(weight);
if(blend > 0.0f){
auto kfAdt = sequence->GetDeltaTime(frameA);
auto kfAdt = sequence->GetNextTimeDelta();
float t = kfAdt == 0.0f ? 0.0f : (kfAdt - remainingTime)/kfAdt;
if(sequence->type & CAnimBlendSequence::KF_TRANS){
auto kfAt = sequence->GetTranslation(frameA);
auto kfBt = sequence->GetTranslation(frameB);
trans = kfBt + t*(kfAt - kfBt);
auto kfdAt = sequence->GetNextTranslationDelta();
auto kfBt = sequence->GetCurrentTranslation();
trans = kfBt + t*kfdAt;
trans *= blend;
}
}
@ -198,7 +204,7 @@ CAnimBlendNode::GetEndTranslation(CVector &trans, float weight)
float blend = association->GetBlendAmount(weight);
if(blend > 0.0f){
if(sequence->type & CAnimBlendSequence::KF_TRANS){
CVector pos = sequence->GetTranslation(sequence->numFrames-1);
CVector pos = sequence->GetEndTranslation();
trans = pos * blend;
}
}

View file

@ -12,17 +12,15 @@ public:
float theta; // angle between quaternions
float invSin; // 1/Sin(theta)
// indices into array in sequence
int32 frameA; // next key frame
int32 frameB; // previous key frame
int32 _frameA; // next key frame
int32 _frameB; // previous key frame
float remainingTime; // time until frames have to advance
CAnimBlendSequence *sequence;
CAnimBlendAssociation *association;
void Init(void);
bool Update(CVector &trans, CQuaternion &rot, float weight);
bool UpdateCompressed(CVector &trans, CQuaternion &rot, float weight);
bool NextKeyFrame(void);
bool NextKeyFrameCompressed(void);
bool FindKeyFrame(float t);
void CalcDeltas(void);
void GetCurrentTranslation(CVector &trans, float weight);

View file

@ -23,44 +23,23 @@ CAnimBlendSequence::SetName(char *name)
strncpy(this->name, name, 24);
}
void
CAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compress)
{
int sz;
// void
// CAnimBlendSequence::RemoveQuaternionFlips(void)
// {
// int i;
// CQuaternion last;
if(translation){
type |= KF_ROT | KF_TRANS;
if (compress) {
type |= KF_COMPRESSED;
sz = sizeof(KeyFrameTransCompressed);
} else {
sz = sizeof(KeyFrameTransUncompressed);
}
}else{
sz = sizeof(KeyFrame);
type |= KF_ROT;
}
keyFrames = RwMalloc(sz * numFrames);
this->numFrames = numFrames;
}
// if(numFrames < 2)
// return;
void
CAnimBlendSequence::RemoveQuaternionFlips(void)
{
int i;
CQuaternion last;
if(numFrames < 2)
return;
last = GetRotation(0);
for(i = 1; i < numFrames; i++){
auto KFr = GetRotation(i);
if(DotProduct(last, KFr) < 0.0f)
SetRotation(i, -KFr);
last = GetRotation(i);
}
}
// last = GetRotation(0);
// for(i = 1; i < numFrames; i++){
// auto KFr = GetRotation(i);
// if(DotProduct(last, KFr) < 0.0f)
// SetRotation(i, -KFr);
// last = GetRotation(i);
// }
// }
#ifdef USE_CUSTOM_ALLOCATOR
bool

View file

@ -1,5 +1,7 @@
#pragma once
#include <cmath>
#include "Quaternion.h"
#ifdef MoveMemory
@ -72,83 +74,261 @@ struct KeyFrameTransCompressed : KeyFrame {
// The sequence of key frames of one animated node
class CAnimBlendSequence
{
template <typename T>
T get(unsigned offset) {
return *(T*)((uint8_t*)keyFrames + offset);
}
template <typename T>
T read() {
T rv;
memcpy(&rv, (uint8_t*)keyFrames + readOffset, sizeof(T));
readOffset += sizeof(T);
return rv;
}
CQuaternion fromSphericalFixed(uint16_t y, uint16_t p, uint16_t r) {
CQuaternion q;
q.w = cos((y / 65536.0f) * 2 * M_PI) * cos((p / 65536.0f) * 2 * M_PI);
q.x = cos((y / 65536.0f) * 2 * M_PI) * sin((p / 65536.0f) * 2 * M_PI);
q.y = sin((y / 65536.0f) * 2 * M_PI) * cos((r / 65536.0f) * 2 * M_PI);
q.z = sin((y / 65536.0f) * 2 * M_PI) * sin((r / 65536.0f) * 2 * M_PI);
return q;
}
public:
enum {
KF_ROT = 1,
KF_TRANS = 2,
KF_COMPRESSED = 4, // only applicable for KF_TRANS
FLAGS_HAS_ROT_Y = 1 << 8,
FLAGS_HAS_ROT_P = 1 << 9,
FLAGS_HAS_ROT_R = 1 << 10,
FLAGS_HAS_TRANS_X = 1 << 11,
FLAGS_HAS_TRANS_Y = 1 << 12,
FLAGS_HAS_TRANS_Z = 1 << 13,
FLAGS_HAS_TRANS_ANY = 7 << 11,
FLAGS_HAS_TRANS_LARGE = 1 << 14,
FLAGS_QUAT0_NEG = 1 << 15
};
int32 type;
char name[24];
int32 numFrames;
int32 curFrame;
int16 boneTag;
void *keyFrames;
CQuaternion currentRotation;
CQuaternion nextRotation;
CVector currentTranslation;
CVector nextTranslation;
CVector startTranslation, endTranslation;
float endTime;
unsigned readOffset;
uint16_t predicted_y, predicted_p, predicted_r;
float predicted_tx = 0, predicted_ty = 0, predicted_tz = 0;
float nextDeltaTime;
void Init() {
curFrame = 0;
readOffset = 0;
float startTime = read<float>();
endTime = read<float>();
if (type & KF_TRANS) {
if (type & FLAGS_HAS_TRANS_LARGE) {
startTranslation.x = read<float>();
startTranslation.y = read<float>();
startTranslation.z = read<float>();
predicted_tx = startTranslation.x;
predicted_ty = startTranslation.y;
predicted_tz = startTranslation.z;
// Read final translation (may be used for verification or ignored)
endTranslation.x = read<float>();
endTranslation.y = read<float>();
endTranslation.z = read<float>();
} else {
startTranslation.x = read<int16_t>() / 128.f;
startTranslation.y = read<int16_t>() / 128.f;
startTranslation.z = read<int16_t>() / 128.f;
predicted_tx = startTranslation.x;
predicted_ty = startTranslation.y;
predicted_tz = startTranslation.z;
// Read final translation (for completeness)
endTranslation.x = read<int16_t>() / 128.f;
endTranslation.y = read<int16_t>() / 128.f;
endTranslation.z = read<int16_t>() / 128.f;
}
nextTranslation = startTranslation;
} else {
startTranslation = { 0, 0, 0 };
endTranslation = { 0, 0, 0 };
nextTranslation = startTranslation;
}
predicted_y = read<uint16_t>();
predicted_p = read<uint16_t>();
predicted_r = read<uint16_t>();
nextRotation = fromSphericalFixed(predicted_y, predicted_p, predicted_r);
if (type & FLAGS_QUAT0_NEG) {
nextRotation = -nextRotation;
}
if (numFrames > 1) {
AdvanceFrame();
} else {
currentTranslation = nextTranslation;
currentRotation = nextRotation;
nextDeltaTime = 0;
}
}
CQuaternion GetCurrentRotation() {
return currentRotation;
}
CQuaternion GetNextRotation() {
return nextRotation;
}
float GetNextTimeDelta() {
return nextDeltaTime;
}
float GetEndTime() {
return endTime;
}
CVector GetStartTranslation() {
return startTranslation;
}
CVector GetCurrentTranslation() {
return currentTranslation;
}
CVector GetNextTranslationDelta() {
return nextTranslation - currentTranslation;
}
CVector GetEndTranslation() {
return endTranslation;
}
void AdvanceFrame() {
if (++curFrame == numFrames){
Init();
}
// rotation
{
currentRotation = nextRotation;
// For rotation Y:
if (type & FLAGS_HAS_ROT_Y) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
predicted_y = read<uint16_t>();
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_y += diff * 8;
}
}
// For rotation P:
if (type & FLAGS_HAS_ROT_P) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
predicted_p = read<uint16_t>();
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_p += diff * 8;
}
}
// For rotation R:
if (type & FLAGS_HAS_ROT_R) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
predicted_r = read<uint16_t>();
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_r += diff * 8;
}
}
nextRotation = fromSphericalFixed(predicted_y, predicted_p, predicted_r);
}
// translation
if (type & KF_TRANS) {
currentTranslation = nextTranslation;
if (type & FLAGS_HAS_TRANS_X) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
uint16_t diff = read<uint16_t>();
if (diff != 32768) {
predicted_tx += static_cast<int16_t>(diff) / 128.f;
} else {
predicted_tx = read<float>();
}
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_tx += diff / 127.f;
}
}
// Translation Y:
if (type & FLAGS_HAS_TRANS_Y) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
uint16_t diff = read<uint16_t>();
if (diff != 32768) {
predicted_ty += static_cast<int16_t>(diff) / 128.f;
} else {
predicted_ty = read<float>();
}
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_ty += diff / 127.f;
}
}
// Translation Z:
if (type & FLAGS_HAS_TRANS_Z) {
uint8_t byteVal = read<uint8_t>();
if (byteVal == 128) {
uint16_t diff = read<uint16_t>();
if (diff != 32768) {
predicted_tz += static_cast<int16_t>(diff) / 128.f;
} else {
predicted_tz = read<float>();
}
} else {
int8_t diff = static_cast<int8_t>(byteVal);
predicted_tz += diff / 127.f;
}
}
nextTranslation = { predicted_tx, predicted_ty, predicted_tz };
}
// time delta + quaternion flips
{
uint8_t byteValPacked = read<uint8_t>();
uint8_t byteVal = byteValPacked & 127;
float diff;
if (byteVal == 127) {
uint16_t fixed_diff = read<uint16_t>();
diff = fixed_diff / 256.f;
} else {
diff = byteVal / 256.f;
}
nextDeltaTime = diff;
if (byteValPacked & 128) {
nextRotation = -nextRotation;
}
}
}
CAnimBlendSequence(void);
virtual ~CAnimBlendSequence(void);
void SetName(char *name);
void SetNumFrames(int numFrames, bool translation, bool compressed);
void RemoveQuaternionFlips(void);
void SetTranslation(int n, const CVector &v) {
if (type & KF_COMPRESSED) {
((KeyFrameTransCompressed*)keyFrames)[n].translation_(v);
} else if (type & KF_TRANS) {
((KeyFrameTransUncompressed*)keyFrames)[n].translation_(v);
} else {
assert(false && "SetTranslation called on sequence without translation");
}
}
CVector GetTranslation(int n) {
if (type & KF_COMPRESSED) {
return ((KeyFrameTransCompressed*)keyFrames)[n].translation_();
} else if (type & KF_TRANS) {
return ((KeyFrameTransUncompressed*)keyFrames)[n].translation_();
} else {
assert(false && "GetTranslation called on sequence without translation");
}
}
void SetRotation(int n, const CQuaternion &q) {
if (type & KF_COMPRESSED) {
((KeyFrameTransCompressed*)keyFrames)[n].rotation_(q);
} else if (type & KF_TRANS) {
((KeyFrameTransUncompressed*)keyFrames)[n].rotation_(q);
} else {
((KeyFrame*)keyFrames)[n].rotation_(q);
}
}
CQuaternion GetRotation(int n) {
if (type & KF_COMPRESSED) {
return ((KeyFrameTransCompressed*)keyFrames)[n].rotation_();
} else if (type & KF_TRANS) {
return ((KeyFrameTransUncompressed*)keyFrames)[n].rotation_();
} else {
return ((KeyFrame*)keyFrames)[n].rotation_();
}
}
void SetDeltaTime(int n, float t) {
if (type & KF_COMPRESSED) {
((KeyFrameTransCompressed*)keyFrames)[n].deltaTime_(t);
} else if (type & KF_TRANS) {
((KeyFrameTransUncompressed*)keyFrames)[n].deltaTime_(t);
} else {
((KeyFrame*)keyFrames)[n].deltaTime_(t);
}
}
float GetDeltaTime(int n) {
if (type & KF_COMPRESSED) {
return ((KeyFrameTransCompressed*)keyFrames)[n].deltaTime_();
} else if (type & KF_TRANS) {
return ((KeyFrameTransUncompressed*)keyFrames)[n].deltaTime_();
} else {
return ((KeyFrame*)keyFrames)[n].deltaTime_();
}
}
bool HasTranslation(void) { return !!(type & KF_TRANS); }
bool MoveMemory(void);

View file

@ -1244,34 +1244,32 @@ CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedA
char ident[4];
uint32 size;
};
IfpHeader anpk, info, name, dgan, cpan, anim;
IfpHeader anpv;
char buf[256];
int j, k, l;
float *fbuf = (float*)buf;
// 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);
RwStreamRead(stream, &anpv, sizeof(IfpHeader));
assert(memcmp(anpv.ident, "ANPV", 4) == 0);
RwStreamRead(stream, buf, anpv.size);
int32_t numAnims;
RwStreamRead(stream, &numAnims, sizeof(numAnims));
CAnimBlock *animBlock = GetAnimationBlock(buf);
if(animBlock){
if(animBlock->numAnims == 0){
animBlock->numAnims = *(int*)buf;
animBlock->numAnims = numAnims;
animBlock->firstIndex = ms_numAnimations;
}
}else{
animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
strncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME);
animBlock->numAnims = *(int*)buf;
strncpy(animBlock->name, buf, MAX_ANIMBLOCK_NAME);
animBlock->numAnims = numAnims;
animBlock->firstIndex = ms_numAnimations;
}
debug("Loading ANIMS %s\n", animBlock->name);
bool stub_out = strcmp(animBlock->name, "law_1b") == 0;
animBlock->isLoaded = true;
int animIndex = animBlock->firstIndex;
@ -1279,116 +1277,50 @@ CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedA
assert(animIndex < ARRAY_SIZE(ms_aAnimations));
CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
int32_t animNameLength;
// animation name
RwStreamRead(stream, &name, sizeof(IfpHeader));
ROUNDSIZE(name.size);
RwStreamRead(stream, buf, name.size);
RwStreamRead(stream, &animNameLength, sizeof(animNameLength));
RwStreamRead(stream, buf, animNameLength);
hier->SetName(buf);
bool compressHier = compress;
if (uncompressedAnims) {
for (int i = 0; uncompressedAnims[i][0]; i++) {
if (!CGeneral::faststricmp(uncompressedAnims[i], hier->name)){
debug("Loading %s uncompressed\n", hier->name);
compressHier = 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);
RwStreamRead(stream, buf, info.size);
hier->numSequences = *(int*)buf;
int32_t numSeqs;
RwStreamRead(stream, &numSeqs, sizeof(numSeqs));
hier->numSequences = numSeqs;
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
RwStreamRead(stream, &cpan, sizeof(IfpHeader));
ROUNDSIZE(dgan.size);
RwStreamRead(stream, &anim, sizeof(IfpHeader));
ROUNDSIZE(anim.size);
RwStreamRead(stream, buf, anim.size);
int numFrames = *(int*)(buf+28);
int32_t seqNameLength;
RwStreamRead(stream, &seqNameLength, sizeof(seqNameLength));
RwStreamRead(stream, buf, seqNameLength);
seq->SetName(buf);
if(anim.size == 44)
seq->SetBoneTag(*(int*)(buf+40));
int32_t numFrames;
RwStreamRead(stream, &numFrames, sizeof(numFrames));
seq->numFrames = numFrames;
int32_t boneTag;
RwStreamRead(stream, &boneTag, sizeof(boneTag));
seq->SetBoneTag(boneTag);
if(numFrames == 0)
continue;
bool hasScale = false;
bool hasTranslation = false;
RwStreamRead(stream, &info, sizeof(info));
if(strncmp(info.ident, "KRTS", 4) == 0){
hasScale = true;
seq->SetNumFrames(stub_out ? 1 : numFrames, true, compressHier);
}else if(strncmp(info.ident, "KRT0", 4) == 0){
hasTranslation = true;
seq->SetNumFrames(stub_out ? 1 : numFrames, true, compressHier);
}else if(strncmp(info.ident, "KR00", 4) == 0){
seq->SetNumFrames(stub_out ? 1 : numFrames, false, compressHier);
}
uint32_t dataSize;
RwStreamRead(stream, &dataSize, sizeof(dataSize));
uint16_t flags;
RwStreamRead(stream, &flags, sizeof(flags));
seq->keyFrames = RwMalloc(dataSize);
assert(seq->keyFrames);
RwStreamRead(stream, seq->keyFrames, dataSize - sizeof(flags));
seq->type = flags;
if(strstr(seq->name, "L Toe"))
debug("anim %s has toe keyframes\n", hier->name); // BUG: seq->name
float *frameTimes = (float*)RwMalloc(sizeof(float) * numFrames);
for(l = 0; l < numFrames; l++){
if(hasScale){
RwStreamRead(stream, buf, 0x2C);
CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);
rot.Invert();
CVector trans(fbuf[4], fbuf[5], fbuf[6]);
if (!stub_out || l ==0) {
seq->SetRotation(l, rot);
seq->SetTranslation(l, trans);
}
// scaling ignored
frameTimes[l] = fbuf[10]; // absolute time here
}else if(hasTranslation){
RwStreamRead(stream, buf, 0x20);
CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);
rot.Invert();
CVector trans(fbuf[4], fbuf[5], fbuf[6]);
if (!stub_out || l ==0) {
seq->SetRotation(l, rot);
seq->SetTranslation(l, trans);
}
frameTimes[l] = fbuf[7]; // absolute time here
}else{
RwStreamRead(stream, buf, 0x14);
CQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);
rot.Invert();
if (!stub_out || l ==0) {
seq->SetRotation(l, rot);
}
frameTimes[l] = fbuf[4]; // absolute time here
}
}
// convert absolute time to deltas
float running_sum = 0.0f;
for (l = 0; l < numFrames; l++) {
auto dt = frameTimes[l] - running_sum;
if (!stub_out || l ==0) {
seq->SetDeltaTime(l, dt);
assert(seq->GetDeltaTime(l) <= dt);
running_sum += seq->GetDeltaTime(l);
}
// if (seq->GetDeltaTime(l) == 0.0f && dt != 0.0f) {
// seq->SetDeltaTime(l, KF_MINDELTA);
// }
// assert(seq->GetDeltaTime(l) != 0.0f || dt == 0.0f);
}
RwFree(frameTimes);
seq->Init();
}
hier->RemoveQuaternionFlips();
hier->CalcTotalTime();
}
if(animIndex > ms_numAnimations)

View file

@ -289,7 +289,7 @@ CCutsceneMgr::SetupCutsceneToStart(void)
if (ms_pCutsceneObjects[i]->m_pAttachTo != nil) {
pAnimBlendAssoc->flags &= (~ASSOC_HAS_TRANSLATION);
} else {
ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + pAnimBlendAssoc->hierarchy->sequences[0].GetTranslation(0));
ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + pAnimBlendAssoc->hierarchy->sequences[0].GetStartTranslation());
}
pAnimBlendAssoc->SetRun();
} else {

View file

@ -4894,7 +4894,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedDraggedOutCarAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedDraggedOutCarAnimOffset = seq->GetEndTranslation();
}
}
@ -4904,7 +4904,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedCarDoorAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedCarDoorAnimOffset = seq->GetEndTranslation();
}
}
@ -4914,7 +4914,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedCarDoorLoAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedCarDoorLoAnimOffset = seq->GetEndTranslation();
}
}
@ -4924,7 +4924,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedQuickDraggedOutCarAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedQuickDraggedOutCarAnimOffset = seq->GetEndTranslation();
}
}
@ -4934,7 +4934,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedVanRearDoorAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedVanRearDoorAnimOffset = seq->GetEndTranslation();
}
}
@ -4944,7 +4944,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedTrainDoorAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedTrainDoorAnimOffset = seq->GetEndTranslation();
}
}
@ -4954,7 +4954,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedStdBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedStdBikeJumpRhsAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedStdBikeJumpRhsAnimOffset = seq->GetEndTranslation();
}
}
@ -4964,7 +4964,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedVespaBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedVespaBikeJumpRhsAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedVespaBikeJumpRhsAnimOffset = seq->GetEndTranslation();
}
}
@ -4974,7 +4974,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedHarleyBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedHarleyBikeJumpRhsAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedHarleyBikeJumpRhsAnimOffset = seq->GetEndTranslation();
}
}
@ -4984,7 +4984,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedDirtBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedDirtBikeJumpRhsAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedDirtBikeJumpRhsAnimOffset = seq->GetEndTranslation();
}
}
@ -4994,7 +4994,7 @@ CPed::SetAnimOffsetForEnterOrExitVehicle(void)
if (!seq->HasTranslation())
vecPedBikeKickAnimOffset = CVector(0.0f, 0.0f, 0.0f);
else {
vecPedBikeKickAnimOffset = seq->GetTranslation(seq->numFrames - 1);
vecPedBikeKickAnimOffset = seq->GetEndTranslation();
}
}

1020
src/tools/animtool.cpp Normal file

File diff suppressed because it is too large Load diff