diff --git a/Makefile b/Makefile index 9e7b5d7..007c59a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp geometryplg.cpp\ + geometry.cpp plugins.cpp\ ps2.cpp ogl.cpp\ image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) diff --git a/Makefile.mingw b/Makefile.mingw index f50600d..a78acbf 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -6,7 +6,7 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp geometryplg.cpp\ + geometry.cpp plugins.cpp\ ps2.cpp ogl.cpp\ image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) diff --git a/Makefile.ps2 b/Makefile.ps2 index fee7f97..cf5c8f3 100644 --- a/Makefile.ps2 +++ b/Makefile.ps2 @@ -7,7 +7,7 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp geometryplg.cpp\ + geometry.cpp plugins.cpp\ ps2.cpp ogl.cpp\ image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) diff --git a/TODO b/TODO index ccc251f..bcaed7d 100644 --- a/TODO +++ b/TODO @@ -15,8 +15,6 @@ Clump & related: - implement plugins: Clump R* Collision - Frame - HAnim Atomic ((Particles)) R* Pipeline Set diff --git a/dffwrite.cpp b/dffwrite.cpp index 49d28ca..5bd1b79 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -21,6 +21,7 @@ main(int argc, char *argv[]) Rw::RegisterMaterialRightsPlugin(); Rw::RegisterMatFXPlugin(); Rw::RegisterAtomicRightsPlugin(); + Rw::RegisterHAnimPlugin(); Rw::RegisterNodeNamePlugin(); Rw::RegisterBreakableModelPlugin(); Rw::RegisterExtraVertColorPlugin(); diff --git a/src/clump.cpp b/src/clump.cpp index 3c9b4e6..37caf6b 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -108,6 +108,7 @@ Frame::updateLTM(void) Frame *parent = (Frame*)this->parent; if(parent){ parent->updateLTM(); +// TODO: replace with platform optimized code #define L(i,j) this->ltm[i*4+j] #define A(i,j) parent->ltm[i*4+j] #define B(i,j) this->matrix[i*4+j] @@ -127,6 +128,21 @@ Frame::updateLTM(void) } } +static Frame* +dirtyCB(Frame *f, void *) +{ + f->dirty = true; + f->forAllChildren(dirtyCB, NULL); + return f; +} + +void +Frame::setDirty(void) +{ + this->dirty = true; + this->forAllChildren(dirtyCB, NULL); +} + static Frame* sizeCB(Frame *f, void *size) { diff --git a/src/geometryplg.cpp b/src/plugins.cpp similarity index 85% rename from src/geometryplg.cpp rename to src/plugins.cpp index 3b466d6..a244ed9 100644 --- a/src/geometryplg.cpp +++ b/src/plugins.cpp @@ -2,9 +2,6 @@ #include #include #include - -//#include -//#include #include #include "rwbase.h" @@ -17,6 +14,128 @@ using namespace std; namespace Rw { +// +// HAnim +// + +int32 HAnimOffset; + +static void* +createHAnim(void *object, int32 offset, int32 size) +{ + HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); + hanim->id = -1; + hanim->hierarchy = NULL; + return object; +} + +static void* +destroyHAnim(void *object, int32 offset, int32 size) +{ + HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); + if(hanim->hierarchy){ + HAnimHierarchy *hier = hanim->hierarchy; + delete[] (uint8*)hier->matricesUnaligned; + delete[] hier->nodeInfo; + delete hier; + } + hanim->id = -1; + hanim->hierarchy = NULL; + return object; +} + +static void* +copyHAnim(void *dst, void *src, int32 offset, int32 size) +{ + HAnimData *dsthanim = PLUGINOFFSET(HAnimData, dst, offset); + HAnimData *srchanim = PLUGINOFFSET(HAnimData, src, offset); + dsthanim->id = srchanim->id; + // TODO + dsthanim->hierarchy = NULL; + return dst; +} + +static void +readHAnim(Stream *stream, int32 len, void *object, int32 offset, int32) +{ + int32 cnst, numNodes; + HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); + cnst = stream->readI32(); + if(cnst != 256){ + printf("hanim const was not 256\n"); + return; + } + hanim->id = stream->readI32(); + numNodes = stream->readI32(); + if(numNodes != 0){ + HAnimHierarchy *hier = new HAnimHierarchy; + hanim->hierarchy = hier; + hier->numNodes = numNodes; + hier->flags = stream->readI32(); + hier->maxInterpKeyFrameSize = stream->readI32(); + hier->parentFrame = (Frame*)object; + hier->parentHierarchy = hier; + if(hier->flags & 2) + hier->matrices = hier->matricesUnaligned = NULL; + else{ + hier->matricesUnaligned = + (float*) new uint8[hier->numNodes*64 + 15]; + hier->matrices = + (float*)((uintptr)hier->matricesUnaligned & ~0xF); + } + hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; + for(int32 i = 0; i < hier->numNodes; i++){ + hier->nodeInfo[i].id = stream->readI32(); + hier->nodeInfo[i].index = stream->readI32(); + hier->nodeInfo[i].flags = stream->readI32(); + hier->nodeInfo[i].frame = NULL; + } + } +} + +static void +writeHAnim(Stream *stream, int32 len, void *object, int32 offset, int32) +{ + HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); + stream->writeI32(256); + stream->writeI32(hanim->id); + if(hanim->hierarchy == NULL){ + stream->writeI32(0); + return; + } + HAnimHierarchy *hier = hanim->hierarchy; + stream->writeI32(hier->numNodes); + stream->writeI32(hier->flags); + stream->writeI32(hier->maxInterpKeyFrameSize); + for(int32 i = 0; i < hier->numNodes; i++){ + stream->writeI32(hier->nodeInfo[i].id); + stream->writeI32(hier->nodeInfo[i].index); + stream->writeI32(hier->nodeInfo[i].flags); + } +} + +static int32 +getSizeHAnim(void *object, int32 offset, int32) +{ + HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset); + if(hanim->hierarchy) + return 12 + 8 + hanim->hierarchy->numNodes*12; + return 12; +} + +void +RegisterHAnimPlugin(void) +{ + HAnimOffset = Frame::registerPlugin(sizeof(HAnimData), ID_HANIMPLUGIN, + createHAnim, + destroyHAnim, copyHAnim); + Frame::registerPluginStream(ID_HANIMPLUGIN, + readHAnim, + writeHAnim, + getSizeHAnim); +} + + // // Geometry // @@ -207,7 +326,9 @@ RegisterNativeDataPlugin(void) (StreamGetSize)getSizeNativeData); } +// // Skin +// SkinGlobals_ SkinGlobals = { 0, NULL }; @@ -442,7 +563,11 @@ RegisterSkinPlugin(void) Atomic::setStreamRightsCallback(ID_SKIN, skinRights); } -// Atomic MatFX +// +// MatFX +// + +// Atomic static void* createAtomicMatFX(void *object, int32 offset, int32) @@ -463,10 +588,7 @@ readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32) { int32 flag; uint32 version; -//stream->seek(-4); -//version = stream->readU32(); stream->read(&flag, 4); -//printf("atomicMatFX: %X %X\n", LibraryIDUnpackVersion(version), flag); *PLUGINOFFSET(int32, object, offset) = flag; if(flag) ((Atomic*)object)->pipeline = MatFXGlobals.pipeline; @@ -488,7 +610,7 @@ getSizeAtomicMatFX(void *object, int32 offset, int32) return flag ? 4 : -1; } -// Material MatFX +// Material MatFXGlobals_ MatFXGlobals = { 0, 0, NULL }; diff --git a/src/rwbase.h b/src/rwbase.h index 175e72d..f532741 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -110,6 +110,7 @@ enum PluginID ID_UVANIMDICT = 0x2B, ID_SKIN = 0x116, + ID_HANIMPLUGIN = 0x11E, ID_MATFX = 0x120, ID_PDS = 0x131, ID_ADC = 0x134, diff --git a/src/rwobjects.h b/src/rwobjects.h index 4fa9ffa..559c87e 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -1,6 +1,6 @@ namespace Rw { -// TODO: mostly +// TODO: mostly a stub right now struct Pipeline { uint32 pluginID; @@ -37,8 +37,40 @@ struct Frame : PluginBase, Object Frame *forAllChildren(Callback cb, void *data); int32 count(void); void updateLTM(void); + void setDirty(void); }; +struct HAnimNodeInfo +{ + int32 id; + int32 index; + int32 flags; + Frame *frame; +}; + +struct HAnimHierarchy +{ + int32 flags; + int32 numNodes; + float *matrices; + float *matricesUnaligned; + HAnimNodeInfo *nodeInfo; + Frame *parentFrame; + HAnimHierarchy *parentHierarchy; // mostly unused + + // temporary + int32 maxInterpKeyFrameSize; +}; + +struct HAnimData +{ + int32 id; + HAnimHierarchy *hierarchy; +}; + +extern int32 HAnimOffset; +void RegisterHAnimPlugin(void); + struct Image { int32 flags;