diff --git a/clump.cpp b/clump.cpp index 91f6197..be77b77 100644 --- a/clump.cpp +++ b/clump.cpp @@ -13,18 +13,6 @@ using namespace std; namespace Rw { -static int32 -findFrame(Frame *f, Frame **frameList, int32 numFrames) -{ - int frm; - for(frm = 0; frm < numFrames; frm++) - if(frameList[frm] == f) - goto foundfrm; - return -1; -foundfrm: - return frm; -} - Frame::Frame(void) { this->child = NULL; @@ -224,7 +212,7 @@ Clump::streamWrite(ostream &stream) for(int32 i = 0; i < this->numLights; i++){ Light *l = this->lightList[i]; - int frm = findFrame(l->frame, flist, numFrames); + int frm = findPointer((void*)l->frame, (void**)flist,numFrames); if(frm < 0) return false; WriteChunkHeader(stream, ID_STRUCT, 4); @@ -347,7 +335,7 @@ Clump::frameListStreamWrite(ostream &stream, Frame **frameList, int32 numFrames) buf.pos[0] = f->matrix[12]; buf.pos[1] = f->matrix[13]; buf.pos[2] = f->matrix[14]; - buf.parent = findFrame(f, frameList, numFrames); + buf.parent = findPointer((void*)f, (void**)frameList,numFrames); buf.matflag = f->matflag; stream.write((char*)&buf, sizeof(buf)); } @@ -399,7 +387,7 @@ Atomic::streamWriteClump(ostream &stream, Frame **frameList, int32 numFrames) return false; WriteChunkHeader(stream, ID_ATOMIC, this->streamGetSize()); WriteChunkHeader(stream, ID_STRUCT, 16); - buf[0] = findFrame(this->frame, frameList, numFrames); + buf[0] = findPointer((void*)this->frame, (void**)frameList, numFrames); // TODO for(buf[1] = 0; buf[1] < c->numAtomics; buf[1]++) diff --git a/main.cpp b/main.cpp index fd85821..e8e3a82 100644 --- a/main.cpp +++ b/main.cpp @@ -74,10 +74,9 @@ main(int argc, char *argv[]) // Rw::Version = 0x31000; // Rw::Build = 0; -// int Xoff = Rw::Clump::registerPlugin(8, 0x123, ctorX, dtorX, cctorX); -// Xoff = Rw::Clump::registerPluginStream(0x123, readX, writeX, getSizeX); + registerNodeNamePlugin(); + registerMeshPlugin(); Rw::Clump *c; -// X *x; ifstream in(argv[1], ios::binary); Rw::FindChunk(in, Rw::ID_CLUMP, NULL, NULL); diff --git a/plugins.cpp b/plugins.cpp new file mode 100644 index 0000000..2edc965 --- /dev/null +++ b/plugins.cpp @@ -0,0 +1,175 @@ +#include +#include +#include + +#include +#include + +#include "rwbase.h" +#include "rwplugin.h" +#include "rw.h" + +using namespace std; +using namespace Rw; + +static void* +createNodeName(void *object, int32 offset, int32) +{ + char *name = PLUGINOFFSET(char, object, offset); + name[0] = '\0'; + return object; +} + +static void* +copyNodeName(void *dst, void *src, int32 offset, int32) +{ + char *dstname = PLUGINOFFSET(char, dst, offset); + char *srcname = PLUGINOFFSET(char, src, offset); + strncpy(dstname, srcname, 17); + return dst; +} + +static void* +destroyNodeName(void *object, int32, int32) +{ + return object; +} + +static void +readNodeName(istream &stream, Rw::int32 len, void *object, int32 offset, int32) +{ + char *name = PLUGINOFFSET(char, object, offset); + stream.read(name, len); + name[len] = '\0'; +} + +static void +writeNodeName(ostream &stream, Rw::int32 len, void *object, int32 offset, int32) +{ + char *name = PLUGINOFFSET(char, object, offset); + stream.write(name, len); +} + +static int32 +getSizeNodeName(void *object, int32 offset) +{ + char *name = PLUGINOFFSET(char, object, offset); + int32 len = strlen(name); + return len > 0 ? len : -1; +} + + +void +registerNodeNamePlugin(void) +{ + Rw::Frame::registerPlugin(18, 0x253f2fe, (Constructor)createNodeName, + (Destructor)destroyNodeName, + (CopyConstructor)copyNodeName); + Rw::Frame::registerPluginStream(0x253f2fe, (StreamRead)readNodeName, + (StreamWrite)writeNodeName, + (StreamGetSize)getSizeNodeName); +} + + +static void* +createMesh(void *object, int, int) +{ + return object; +} + +static void* +copyMesh(void *dst, void *src, int, int) +{ + return dst; +} + +static void* +destroyMesh(void *object, int, int) +{ + return object; +} + +static void +readMesh(istream &stream, Rw::int32, void *object, int32, int32) +{ + Geometry *geo = (Geometry*)object; + uint32 buf[3]; + stream.read((char*)buf, 12); + geo->meshHeader = new MeshHeader; + geo->meshHeader->flags = buf[0]; + geo->meshHeader->numMeshes = buf[1]; + geo->meshHeader->totalIndices = buf[2]; + geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; + Mesh *mesh = geo->meshHeader->mesh; + for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ + stream.read((char*)buf, 8); + mesh->numIndices = buf[0]; + mesh->material = geo->materialList[buf[1]]; + mesh->indices = NULL; + if(geo->geoflags & Geometry::NATIVE) + // TODO: compressed indices in OpenGL + ; + else{ + mesh->indices = new uint16[mesh->numIndices]; + for(uint32 j = 0; j < mesh->numIndices; j++) + mesh->indices[j] = readUInt32(stream); + } + mesh++; + } +} + +static void +writeMesh(ostream &stream, Rw::int32, void *object, int32, int32) +{ + Geometry *geo = (Geometry*)object; + uint32 buf[3]; + buf[0] = geo->meshHeader->flags; + buf[1] = geo->meshHeader->numMeshes; + buf[2] = geo->meshHeader->totalIndices; + stream.write((char*)buf, 12); + Mesh *mesh = geo->meshHeader->mesh; + for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ + buf[0] = mesh->numIndices; + buf[1] = findPointer((void*)mesh->material, + (void**)geo->materialList, + geo->numMaterials); + stream.write((char*)buf, 8); + if(geo->geoflags & Geometry::NATIVE) + // TODO: compressed indices in OpenGL + ; + else + for(uint32 j = 0; j < mesh->numIndices; j++) + writeUInt32(mesh->indices[j], stream); + mesh++; + } +} + +static int32 +getSizeMesh(void *object, int32) +{ + Geometry *geo = (Geometry*)object; + if(geo->meshHeader == NULL) + return -1; + int32 size = 12 + geo->meshHeader->numMeshes*8; + if(geo->geoflags & Geometry::NATIVE) + // TODO: compressed indices in OpenGL + ; + else{ + size += geo->meshHeader->totalIndices*4; + } + return size; +} + + +void +registerMeshPlugin(void) +{ + Rw::Geometry::registerPlugin(0, 0x50E, (Constructor)createMesh, + (Destructor)destroyMesh, + (CopyConstructor)copyMesh); + Rw::Geometry::registerPluginStream(0x50E, (StreamRead)readMesh, + (StreamWrite)writeMesh, + (StreamGetSize)getSizeMesh); +} + + diff --git a/rw.h b/rw.h index eed690a..d85d6ab 100644 --- a/rw.h +++ b/rw.h @@ -36,6 +36,22 @@ struct Material : PluginBase uint32 streamGetSize(void); }; +struct Mesh +{ + uint16 *indices; + uint32 numIndices; + Material *material; +}; + +struct MeshHeader +{ + uint32 flags; + uint16 numMeshes; + // RW has uint16 serialNum here + uint32 totalIndices; + Mesh *mesh; // RW has a byte offset here +}; + struct MorphTarget { float32 boundingSphere[4]; @@ -60,6 +76,8 @@ struct Geometry : PluginBase, Object int32 numMaterials; Material **materialList; + MeshHeader *meshHeader; + Geometry(void); Geometry(Geometry *g); ~Geometry(void); @@ -159,3 +177,6 @@ private: }; } + +void registerNodeNamePlugin(void); +void registerMeshPlugin(void); diff --git a/rwbase.cpp b/rwbase.cpp index f04d96f..2fd5c2d 100644 --- a/rwbase.cpp +++ b/rwbase.cpp @@ -160,4 +160,16 @@ FindChunk(istream &s, uint32 type, uint32 *length, uint32 *version) return false; } +int32 +findPointer(void *p, void **list, int32 num) +{ + int i; + for(i = 0; i < num; i++) + if(list[i] == p) + goto found; + return -1; +found: + return i; +} + } diff --git a/rwbase.h b/rwbase.h index 127d00d..8ca59f7 100644 --- a/rwbase.h +++ b/rwbase.h @@ -97,4 +97,5 @@ bool WriteChunkHeader(std::ostream &s, int32 type, int32 size); bool ReadChunkHeaderInfo(std::istream &s, ChunkHeaderInfo *header); bool FindChunk(std::istream &s, uint32 type, uint32 *length, uint32 *version); +int32 findPointer(void *p, void **list, int32 num); } diff --git a/rwplugin.h b/rwplugin.h index 2373652..70f4b75 100644 --- a/rwplugin.h +++ b/rwplugin.h @@ -3,12 +3,12 @@ namespace Rw { #define PLUGINOFFSET(type, base, offset) \ ((type*)((char*)(base) + (offset))) -typedef void *(*Constructor)(void *object, int offset, int size); -typedef void *(*Destructor)(void *object, int offset, int size); -typedef void *(*CopyConstructor)(void *dst, void *src, int offset, int size); -typedef void (*StreamRead)(std::istream &stream, int length, void *object, int offset, int size); -typedef void (*StreamWrite)(std::ostream &stream, int length, void *object, int offset, int size); -typedef int32 (*StreamGetSize)(void *object, int offset, int size); +typedef void *(*Constructor)(void *object, int32 offset, int32 size); +typedef void *(*Destructor)(void *object, int32 offset, int32 size); +typedef void *(*CopyConstructor)(void *dst, void *src, int32 offset, int32 size); +typedef void (*StreamRead)(std::istream &stream, int32 length, void *object, int32 offset, int32 size); +typedef void (*StreamWrite)(std::ostream &stream, int32 length, void *object, int32 offset, int32 size); +typedef int32 (*StreamGetSize)(void *object, int32 offset, int32 size); struct Plugin {