From 0097487f9bbc9d948f90bb87cf7d8b1263da51a5 Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Tue, 23 Dec 2014 11:29:37 +0100 Subject: [PATCH] Implemented reading and writing of OGL native data. --- ogl.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++ plugins.cpp | 81 ++++++++++++++++++++++++++++++----------------------- ps2.cpp | 4 +-- rwbase.h | 1 + rwogl.h | 27 ++++++++++++++++++ 5 files changed, 147 insertions(+), 37 deletions(-) create mode 100644 ogl.cpp create mode 100644 rwogl.h diff --git a/ogl.cpp b/ogl.cpp new file mode 100644 index 0000000..7c472b6 --- /dev/null +++ b/ogl.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include +#include + +#include "rwbase.h" +#include "rwplugin.h" +#include "rw.h" +#include "rwogl.h" + +using namespace std; + +namespace Rw { + +void* +DestroyNativeDataOGL(void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + assert(geometry->instData->platform == PLATFORM_OGL); + OGLInstanceDataHeader *header = + (OGLInstanceDataHeader*)geometry->instData; + delete[] header->attribs; + delete[] header->data; + delete header; + return object; +} + +void +ReadNativeDataOGL(istream &stream, int32, void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + OGLInstanceDataHeader *header = new OGLInstanceDataHeader; + geometry->instData = header; + header->platform = PLATFORM_OGL; + header->numAttribs = readUInt32(stream); + header->attribs = new OGLAttrib[header->numAttribs]; + stream.read((char*)header->attribs, + header->numAttribs*sizeof(OGLAttrib)); + // Any better way to find out the size? (header length can be wrong) + header->dataSize = header->attribs[0].stride*geometry->numVertices; + header->data = new uint8[header->dataSize]; + stream.read((char*)header->data, header->dataSize); +} + +void +WriteNativeDataOGL(ostream &stream, int32 len, void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + assert(geometry->instData->platform == PLATFORM_OGL); + OGLInstanceDataHeader *header = + (OGLInstanceDataHeader*)geometry->instData; + writeUInt32(header->numAttribs, stream); + stream.write((char*)header->attribs, + header->numAttribs*sizeof(OGLAttrib)); + stream.write((char*)header->data, header->dataSize); +} + +int32 +GetSizeNativeDataOGL(void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + assert(geometry->instData->platform == PLATFORM_OGL); + OGLInstanceDataHeader *header = + (OGLInstanceDataHeader*)geometry->instData; + return 4 + header->numAttribs*sizeof(OGLAttrib) + header->dataSize; +} + +} diff --git a/plugins.cpp b/plugins.cpp index 372951f..c30e26e 100644 --- a/plugins.cpp +++ b/plugins.cpp @@ -9,6 +9,7 @@ #include "rwplugin.h" #include "rw.h" #include "rwps2.h" +#include "rwogl.h" using namespace std; using namespace Rw; @@ -43,7 +44,7 @@ destroyNodeName(void *object, int32, int32) } static void -readNodeName(istream &stream, Rw::int32 len, void *object, int32 offset, int32) +readNodeName(istream &stream, int32 len, void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); stream.read(name, len); @@ -51,7 +52,7 @@ readNodeName(istream &stream, Rw::int32 len, void *object, int32 offset, int32) } static void -writeNodeName(ostream &stream, Rw::int32 len, void *object, int32 offset, int32) +writeNodeName(ostream &stream, int32 len, void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); stream.write(name, len); @@ -69,12 +70,12 @@ getSizeNodeName(void *object, int32 offset) void registerNodeNamePlugin(void) { - Rw::Frame::registerPlugin(18, 0x253f2fe, (Constructor)createNodeName, - (Destructor)destroyNodeName, - (CopyConstructor)copyNodeName); - Rw::Frame::registerPluginStream(0x253f2fe, (StreamRead)readNodeName, - (StreamWrite)writeNodeName, - (StreamGetSize)getSizeNodeName); + Frame::registerPlugin(18, 0x253f2fe, (Constructor)createNodeName, + (Destructor)destroyNodeName, + (CopyConstructor)copyNodeName); + Frame::registerPluginStream(0x253f2fe, (StreamRead)readNodeName, + (StreamWrite)writeNodeName, + (StreamGetSize)getSizeNodeName); } // @@ -84,7 +85,7 @@ registerNodeNamePlugin(void) // Mesh static void -readMesh(istream &stream, Rw::int32, void *object, int32, int32) +readMesh(istream &stream, int32 len, void *object, int32, int32) { Geometry *geo = (Geometry*)object; int32 indbuf[256]; @@ -96,15 +97,20 @@ readMesh(istream &stream, Rw::int32, void *object, int32, int32) geo->meshHeader->totalIndices = buf[2]; geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; Mesh *mesh = geo->meshHeader->mesh; + bool hasData = len > 12+geo->meshHeader->numMeshes*8; 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{ + if(geo->geoflags & Geometry::NATIVE){ + // OpenGL stores uint16 indices here + if(hasData){ + mesh->indices = new uint16[mesh->numIndices]; + stream.read((char*)mesh->indices, + mesh->numIndices*2); + } + }else{ mesh->indices = new uint16[mesh->numIndices]; uint16 *ind = mesh->indices; int32 numIndices = mesh->numIndices; @@ -121,7 +127,7 @@ readMesh(istream &stream, Rw::int32, void *object, int32, int32) } static void -writeMesh(ostream &stream, Rw::int32, void *object, int32, int32) +writeMesh(ostream &stream, int32, void *object, int32, int32) { Geometry *geo = (Geometry*)object; int32 indbuf[256]; @@ -137,10 +143,11 @@ writeMesh(ostream &stream, Rw::int32, void *object, int32, int32) (void**)geo->materialList, geo->numMaterials); stream.write((char*)buf, 8); - if(geo->geoflags & Geometry::NATIVE) - // TODO: compressed indices in OpenGL - ; - else{ + if(geo->geoflags & Geometry::NATIVE){ + if(mesh->indices) + stream.write((char*)mesh->indices, + mesh->numIndices*2); + }else{ uint16 *ind = mesh->indices; int32 numIndices = mesh->numIndices; for(; numIndices > 0; numIndices -= 256){ @@ -162,10 +169,10 @@ getSizeMesh(void *object, int32) if(geo->meshHeader == NULL) return -1; int32 size = 12 + geo->meshHeader->numMeshes*8; - if(geo->geoflags & Geometry::NATIVE) - // TODO: compressed indices in OpenGL - ; - else{ + if(geo->geoflags & Geometry::NATIVE){ + if(geo->meshHeader[0].mesh->indices) + size += geo->meshHeader->totalIndices*2; + }else{ size += geo->meshHeader->totalIndices*4; } return size; @@ -175,10 +182,10 @@ getSizeMesh(void *object, int32) void registerMeshPlugin(void) { - Rw::Geometry::registerPlugin(0, 0x50E, NULL, NULL, NULL); - Rw::Geometry::registerPluginStream(0x50E, (StreamRead)readMesh, - (StreamWrite)writeMesh, - (StreamGetSize)getSizeMesh); + Geometry::registerPlugin(0, 0x50E, NULL, NULL, NULL); + Geometry::registerPluginStream(0x50E, (StreamRead)readMesh, + (StreamWrite)writeMesh, + (StreamGetSize)getSizeMesh); } // Native Data @@ -191,6 +198,8 @@ destroyNativeData(void *object, int32 offset, int32 size) return object; if(geometry->instData->platform == PLATFORM_PS2) return DestroyNativeDataPS2(object, offset, size); + if(geometry->instData->platform == PLATFORM_OGL) + return DestroyNativeDataOGL(object, offset, size); return object; } @@ -213,10 +222,10 @@ readNativeData(istream &stream, int32 len, void *object, int32 o, int32 s) ReadNativeDataPS2(stream, len, object, o, s); else if(platform == PLATFORM_XBOX) stream.seekg(len, ios::cur); - }else - // OpenGL - // doesn't work always, some headers have wrong size - stream.seekg(len-12, ios::cur); + }else{ + stream.seekg(-12, ios::cur); + ReadNativeDataOGL(stream, len, object, o, s); + } } static void @@ -227,6 +236,8 @@ writeNativeData(ostream &stream, int32 len, void *object, int32 o, int32 s) return; if(geometry->instData->platform == PLATFORM_PS2) WriteNativeDataPS2(stream, len, object, o, s); + else if(geometry->instData->platform == PLATFORM_OGL) + WriteNativeDataOGL(stream, len, object, o, s); } static int32 @@ -240,15 +251,15 @@ getSizeNativeData(void *object, int32 offset, int32 size) else if(geometry->instData->platform == PLATFORM_XBOX) return -1; else if(geometry->instData->platform == PLATFORM_OGL) - return -1; + return GetSizeNativeDataOGL(object, offset, size); return -1; } void registerNativeDataPlugin(void) { - Rw::Geometry::registerPlugin(0, 0x510, NULL, destroyNativeData, NULL); - Rw::Geometry::registerPluginStream(0x510, (StreamRead)readNativeData, - (StreamWrite)writeNativeData, - (StreamGetSize)getSizeNativeData); + Geometry::registerPlugin(0, 0x510, NULL, destroyNativeData, NULL); + Geometry::registerPluginStream(0x510, (StreamRead)readNativeData, + (StreamWrite)writeNativeData, + (StreamGetSize)getSizeNativeData); } diff --git a/ps2.cpp b/ps2.cpp index a000eb8..ec398dd 100644 --- a/ps2.cpp +++ b/ps2.cpp @@ -34,10 +34,10 @@ ReadNativeDataPS2(istream &stream, int32, void *object, int32, int32) { Geometry *geometry = (Geometry*)object; assert(FindChunk(stream, ID_STRUCT, NULL, NULL)); - assert(readUInt32(stream) == 4); + assert(readUInt32(stream) == PLATFORM_PS2); PS2InstanceDataHeader *header = new PS2InstanceDataHeader; geometry->instData = header; - header->platform = 4; + header->platform = PLATFORM_PS2; assert(geometry->meshHeader != NULL); header->numMeshes = geometry->meshHeader->numMeshes; header->instanceMeshes = new PS2InstanceData[header->numMeshes]; diff --git a/rwbase.h b/rwbase.h index 6928905..f17c962 100644 --- a/rwbase.h +++ b/rwbase.h @@ -9,6 +9,7 @@ typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; typedef float float32; +typedef int32 bool32; typedef uint8 byte; typedef uint32 uint; diff --git a/rwogl.h b/rwogl.h new file mode 100644 index 0000000..265e9fc --- /dev/null +++ b/rwogl.h @@ -0,0 +1,27 @@ +namespace Rw { + +struct OGLAttrib +{ + // arguments to glVertexAttribPointer (should use OpenGL types here) + uint32 index; + int32 type; + bool32 normalized; + int32 size; + uint32 stride; + uint32 offset; +}; + +struct OGLInstanceDataHeader : InstanceDataHeader +{ + int32 numAttribs; + OGLAttrib *attribs; + uint32 dataSize; + uint8 *data; +}; + +void *DestroyNativeDataOGL(void *object, int32, int32); +void ReadNativeDataOGL(std::istream &stream, int32 len, void *object, int32, int32); +void WriteNativeDataOGL(std::ostream &stream, int32 len, void *object, int32, int32); +int32 GetSizeNativeDataOGL(void *object, int32, int32); + +}