diff --git a/dffwrite.cpp b/dffwrite.cpp index 091b0ce..955a090 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -17,6 +17,7 @@ main(int argc, char *argv[]) // Rw::Build = 0; registerNodeNamePlugin(); + registerBreakableModelPlugin(); registerNativeDataPlugin(); registerMeshPlugin(); Rw::Clump *c; diff --git a/src/ogl.cpp b/src/ogl.cpp index 1bf380b..1b8b959 100644 --- a/src/ogl.cpp +++ b/src/ogl.cpp @@ -18,11 +18,21 @@ using namespace std; namespace Rw { namespace Gl { +// 20303 0 0 0 3 vertices: 3 float +// 53 1 0 0 2 texCoords: 2 floats +// 20043 1 3 0 2 texCoords: 2 shorts +// 6954 2 1 1 3 normal: 3 bytes normalized +// 13527 3 2 1 4 color: 4 ubytes normalized +// 196 4 2 1 4 weight: 4 ubytes normalized +// 225 4 4 1 4 weight: 4 ushorts normalized +// 421 5 2 0 4 indices: 4 ubytes +// 12887 6 2 1 4 extracolor:4 ubytes normalized + static void printAttribInfo(AttribDesc *attribs, int n) { for(int i = 0; i < n; i++) - printf("%x %x %x %x %x %x\n", + printf("%x %x %x %x\n", attribs[i].index, attribs[i].type, attribs[i].normalized, @@ -55,7 +65,7 @@ ReadNativeData(istream &stream, int32, void *object, int32, int32) header->attribs = new AttribDesc[header->numAttribs]; stream.read((char*)header->attribs, header->numAttribs*sizeof(AttribDesc)); - // Any better way to find out the size? (header length can be wrong) + printAttribInfo(header->attribs, header->numAttribs); header->dataSize = header->attribs[0].stride*geometry->numVertices; header->data = new uint8[header->dataSize]; stream.read((char*)header->data, header->dataSize); diff --git a/src/plugins.cpp b/src/plugins.cpp index b635931..76dd2ae 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -258,8 +258,119 @@ getSizeNativeData(void *object, int32 offset, int32 size) void registerNativeDataPlugin(void) { - Geometry::registerPlugin(0, 0x510, NULL, destroyNativeData, NULL); - Geometry::registerPluginStream(0x510, (StreamRead)readNativeData, + Geometry::registerPlugin(0, ID_NATIVEDATA, + NULL, destroyNativeData, NULL); + Geometry::registerPluginStream(ID_NATIVEDATA, + (StreamRead)readNativeData, (StreamWrite)writeNativeData, (StreamGetSize)getSizeNativeData); } + +// Breakable Model + +// TODO: put this in a header +struct Breakable +{ + uint32 position; + uint32 numVertices; + uint32 numFaces; + uint32 numMaterials; + + float32 *vertices; + float32 *texCoords; + uint8 *colors; + uint16 *faces; + uint16 *matIDs; + char (*texNames)[32]; + char (*maskNames)[32]; + float32 (*surfaceProps)[3]; +}; + +static void* +destroyBreakableModel(void *object, int32 offset, int32 size) +{ + uint8 *p = *PLUGINOFFSET(uint8*, object, offset); + delete[] p; + return object; +} + +static void +readBreakableModel(istream &stream, int32 len, void *object, int32 o, int32 s) +{ + uint32 header[13]; + uint32 hasBreakable = readUInt32(stream); + if(hasBreakable == 0) + return; + stream.read((char*)header, 13*4); + uint32 size = header[1]*(12+8+4) + header[5]*(6+2) + + header[8]*(32+32+12); + uint8 *p = new uint8[sizeof(Breakable)+size]; + Breakable *breakable = (Breakable*)p; + *PLUGINOFFSET(Breakable*, object, o) = breakable; + breakable->position = header[0]; + breakable->numVertices = header[1]; + breakable->numFaces = header[5]; + breakable->numMaterials = header[8]; + p += sizeof(Breakable); + stream.read((char*)p, size); + breakable->vertices = (float*)p; + p += breakable->numVertices*12; + breakable->texCoords = (float*)p; + p += breakable->numVertices*8; + breakable->colors = (uint8*)p; + p += breakable->numVertices*4; + breakable->faces = (uint16*)p; + p += breakable->numFaces*6; + breakable->matIDs = (uint16*)p; + p += breakable->numFaces*2; + breakable->texNames = (char(*)[32])p; + p += breakable->numMaterials*32; + breakable->maskNames = (char(*)[32])p; + p += breakable->numMaterials*32; + breakable->surfaceProps = (float32(*)[3])p; +} + +static void +writeBreakableModel(ostream &stream, int32 len, void *object, int32 o, int32 s) +{ + uint32 header[13]; + Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o); + uint8 *p = (uint8*)breakable; + if(breakable == NULL){ + writeUInt32(0, stream); + return; + } + writeUInt32(1, stream); + memset((char*)header, 0, 13*4); + header[0] = breakable->position; + header[1] = breakable->numVertices; + header[5] = breakable->numFaces; + header[8] = breakable->numMaterials; + stream.write((char*)header, 13*4); + p += sizeof(Breakable); + stream.write((char*)p, breakable->numVertices*(12+8+4) + + breakable->numFaces*(6+2) + + breakable->numMaterials*(32+32+12)); +} + +static int32 +getSizeBreakableModel(void *object, int32 offset, int32 size) +{ + Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset); + if(breakable == NULL) + return 4; + return 56 + breakable->numVertices*(12+8+4) + + breakable->numFaces*(6+2) + + breakable->numMaterials*(32+32+12); +} + +void +registerBreakableModelPlugin(void) +{ + Geometry::registerPlugin(sizeof(Breakable*), ID_BREAKABLE, NULL, + destroyBreakableModel, NULL); + Geometry::registerPluginStream(ID_BREAKABLE, + (StreamRead)readBreakableModel, + (StreamWrite)writeBreakableModel, + (StreamGetSize)getSizeBreakableModel); +} diff --git a/src/rwbase.h b/src/rwbase.h index f17c962..a3b924e 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -59,6 +59,11 @@ enum PluginID ID_ANIMANIMATION = 0x1B, ID_RIGHTTORENDER = 0x1F, ID_UVANIMDICT = 0x2B, + + ID_NATIVEDATA = 0x510, + + ID_EXTRACOLORS = 0x253f2f9, + ID_BREAKABLE = 0x253f2fd }; extern int Version; diff --git a/src/rwobjects.h b/src/rwobjects.h index ca025e9..065216b 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -211,3 +211,4 @@ private: void registerNodeNamePlugin(void); void registerMeshPlugin(void); void registerNativeDataPlugin(void); +void registerBreakableModelPlugin(void); diff --git a/src/rwogl.h b/src/rwogl.h index af95adc..f1e53a9 100644 --- a/src/rwogl.h +++ b/src/rwogl.h @@ -4,7 +4,7 @@ namespace Gl { struct AttribDesc { // arguments to glVertexAttribPointer (should use OpenGL types here) - // Vertex = 0, TexCoord, Normal, Color, Weight, Bone Index + // Vertex = 0, TexCoord, Normal, Color, Weight, Bone Index, Extra Color uint32 index; // float = 0, byte, ubyte, short, ushort int32 type; diff --git a/src/rwplugin.h b/src/rwplugin.h index 70f4b75..9831285 100644 --- a/src/rwplugin.h +++ b/src/rwplugin.h @@ -80,11 +80,11 @@ PluginBase::copyPlugins(T *t) template void PluginBase::streamReadPlugins(std::istream &stream) { - uint32 length; + int32 length; Rw::ChunkHeaderInfo header; - if(!Rw::FindChunk(stream, Rw::ID_EXTENSION, &length, NULL)) + if(!Rw::FindChunk(stream, Rw::ID_EXTENSION, (uint32*)&length, NULL)) return; - while(length){ + while(length > 0){ Rw::ReadChunkHeaderInfo(stream, &header); length -= 12; for(Plugin *p = this->s_plugins; p; p = p->next)