diff --git a/src/d3d.cpp b/src/d3d.cpp index 268f7b1..80f3ac6 100644 --- a/src/d3d.cpp +++ b/src/d3d.cpp @@ -92,5 +92,18 @@ unlockVertices(void *vertexBuffer) #endif } +void +deleteObject(void *object) +{ + if(object == NULL) + return; +#ifdef RW_D3D9 + IUnknown *unk = (IUnknown*)object; + unk->Release(); +#else + delete[] (uint*)object; +#endif +} + } } diff --git a/src/d3d8.cpp b/src/d3d8.cpp index 44e6ee9..77185a1 100644 --- a/src/d3d8.cpp +++ b/src/d3d8.cpp @@ -48,9 +48,16 @@ destroyNativeData(void *object, int32, int32) Geometry *geometry = (Geometry*)object; assert(geometry->instData != NULL); assert(geometry->instData->platform == PLATFORM_D3D8); - // TODO InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + geometry->instData = NULL; + InstanceData *inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + deleteObject(inst->indexBuffer); + deleteObject(inst->vertexBuffer); + inst++; + } + delete[] header->inst; delete header; return object; } @@ -244,7 +251,62 @@ ObjPipeline::instance(Atomic *atomic) void ObjPipeline::uninstance(Atomic *atomic) { - assert(0 && "can't uninstance"); + Geometry *geo = atomic->geometry; + if((geo->geoflags & Geometry::NATIVE) == 0) + return; + geo->geoflags &= ~Geometry::NATIVE; + geo->allocateData(); + geo->meshHeader->allocateIndices(); + + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + InstanceData *inst = header->inst; + Mesh *mesh = geo->meshHeader->mesh; + for(uint32 i = 0; i < header->numMeshes; i++){ + uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); + if(inst->minVert == 0) + memcpy(mesh->indices, indices, inst->numIndices*sizeof(uint16)); + else + for(int32 j = 0; j < inst->numIndices; j++) + mesh->indices[j] = indices[j] + inst->minVert; + unlockIndices(inst->indexBuffer); + + this->uninstanceCB(geo, inst); + mesh++; + inst++; + } + geo->generateTriangles(); + destroyNativeData(geo, 0, 0); +} + +void +defaultUninstanceCB(Geometry *geo, InstanceData *inst) +{ + uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + uninstV3d(VERT_FLOAT3, + &geo->morphTargets[0].vertices[3*inst->minVert], + src, inst->numVertices, inst->stride); + src += 12; + + if(geo->geoflags & Geometry::NORMALS){ + uninstV3d(VERT_FLOAT3, + &geo->morphTargets[0].normals[3*inst->minVert], + src, inst->numVertices, inst->stride); + src += 12; + } + + inst->vertexAlpha = 0; + if(geo->geoflags & Geometry::PRELIT){ + uninstColor(VERT_ARGB, &geo->colors[4*inst->minVert], src, + inst->numVertices, inst->stride); + src += 4; + } + + for(int32 i = 0; i < geo->numTexCoordSets; i++){ + uninstV2d(VERT_FLOAT2, &geo->texCoords[i][2*inst->minVert], src, + inst->numVertices, inst->stride); + src += 8; + } + unlockVertices(inst->vertexBuffer); } void @@ -290,6 +352,7 @@ makeDefaultPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; return pipe; } @@ -298,6 +361,7 @@ makeSkinPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; pipe->pluginID = ID_SKIN; pipe->pluginData = 1; return pipe; @@ -308,6 +372,7 @@ makeMatFXPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; pipe->pluginID = ID_MATFX; pipe->pluginData = 0; return pipe; diff --git a/src/d3d9.cpp b/src/d3d9.cpp index 9ab1ef4..0bbcf6d 100644 --- a/src/d3d9.cpp +++ b/src/d3d9.cpp @@ -35,7 +35,7 @@ createVertexDeclaration(VertexElement *elements) VertexElement *e = (VertexElement*)elements; while(e[n++].stream != 0xFF) ; - e = new VertexElement[n]; + e = (VertexElement*)new uint8[n*sizeof(VertexElement)]; memcpy(e, elements, n*sizeof(VertexElement)); return e; #endif @@ -67,9 +67,14 @@ destroyNativeData(void *object, int32, int32) Geometry *geometry = (Geometry*)object; assert(geometry->instData != NULL); assert(geometry->instData->platform == PLATFORM_D3D9); - // TODO InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + geometry->instData = NULL; + deleteObject(header->vertexDeclaration); + deleteObject(header->indexBuffer); + deleteObject(header->vertexStream[0].vertexBuffer); + deleteObject(header->vertexStream[1].vertexBuffer); + delete[] header->inst; delete header; return object; } diff --git a/src/geometry.cpp b/src/geometry.cpp index d4fa0fa..4d635d3 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -72,8 +72,8 @@ Geometry::~Geometry(void) delete[] this->morphTargets; if(this->meshHeader){ - for(uint32 i = 0; i < this->meshHeader->numMeshes; i++) - delete[] this->meshHeader->mesh[i].indices; + // first mesh holds pointer to all indices + delete[] this->meshHeader->mesh[0].indices; delete[] this->meshHeader->mesh; delete this->meshHeader; } diff --git a/src/ogl.cpp b/src/ogl.cpp index 8d4e499..676f936 100644 --- a/src/ogl.cpp +++ b/src/ogl.cpp @@ -213,6 +213,8 @@ destroyNativeData(void *object, int32, int32) assert(geometry->instData->platform == PLATFORM_OGL); InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + geometry->instData = NULL; + // TODO: delete ibo and vbo delete[] header->attribs; delete[] header->data; delete header; @@ -480,10 +482,7 @@ ObjPipeline::uninstance(Atomic *atomic) geo->generateTriangles(); - delete header->attribs; - delete header->data; - delete header; - geo->instData = NULL; + destroyNativeData(geo, 0, 0); } ObjPipeline* diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 2cdba2f..80c2c33 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -97,6 +97,36 @@ instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride) assert(0 && "unsupported instV3d type"); } +void +uninstV3d(int type, float *dst, uint8 *src, uint32 numVertices, uint32 stride) +{ + if(type == VERT_FLOAT3) + for(uint32 i = 0; i < numVertices; i++){ + memcpy(dst, src, 12); + src += stride; + dst += 3; + } + else if(type == VERT_COMPNORM) + for(uint32 i = 0; i < numVertices; i++){ + uint32 n = *(uint32*)src; + int32 normal[3]; + normal[0] = n & 0x7FF; + normal[1] = (n >> 11) & 0x7FF; + normal[2] = (n >> 22) & 0x3FF; + // sign extend + if(normal[0] & 0x400) normal[0] |= ~0x7FF; + if(normal[1] & 0x400) normal[1] |= ~0x7FF; + if(normal[2] & 0x200) normal[2] |= ~0x3FF; + dst[0] = normal[0] / 1023.0f; + dst[1] = normal[1] / 1023.0f; + dst[2] = normal[2] / 511.0f; + src += stride; + dst += 3; + } + else + assert(0 && "unsupported uninstV3d type"); +} + void instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride) { @@ -108,20 +138,50 @@ instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride) } } +void +uninstV2d(int type, float *dst, uint8 *src, uint32 numVertices, uint32 stride) +{ + assert(type == VERT_FLOAT2); + for(uint32 i = 0; i < numVertices; i++){ + memcpy(dst, src, 8); + src += stride; + dst += 2; + } +} + bool32 instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride) { assert(type == VERT_ARGB); bool32 hasAlpha = 0; for(uint32 i = 0; i < numVertices; i++){ - uint32 col = COLOR_ARGB(src[3], src[0], src[1], src[2]); - if(src[3] < 0xFF) - hasAlpha = 1; - memcpy(dst, &col, 4); +// uint32 col = COLOR_ARGB(src[3], src[0], src[1], src[2]); +// if(src[3] < 0xFF) +// hasAlpha = 1; +// memcpy(dst, &col, 4); + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; dst += stride; src += 4; } return hasAlpha; } +void +uninstColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride) +{ + assert(type == VERT_ARGB); + bool32 hasAlpha = 0; + for(uint32 i = 0; i < numVertices; i++){ + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; + src += stride; + dst += 4; + } +} + } diff --git a/src/plugins.cpp b/src/plugins.cpp index 5af3076..0b3a656 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -164,6 +164,9 @@ readMesh(Stream *stream, int32 len, void *object, int32, int32) geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; Mesh *mesh = geo->meshHeader->mesh; bool hasData = len > 12+geo->meshHeader->numMeshes*8; + uint16 *p = NULL; + if(!(geo->geoflags & Geometry::NATIVE) || hasData) + p = new uint16[geo->meshHeader->totalIndices]; for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ stream->read(buf, 8); mesh->numIndices = buf[0]; @@ -172,12 +175,14 @@ readMesh(Stream *stream, int32 len, void *object, int32, int32) if(geo->geoflags & Geometry::NATIVE){ // OpenGL stores uint16 indices here if(hasData){ - mesh->indices = new uint16[mesh->numIndices]; + mesh->indices = p; + p += mesh->numIndices; stream->read(mesh->indices, mesh->numIndices*2); } }else{ - mesh->indices = new uint16[mesh->numIndices]; + mesh->indices = p; + p += mesh->numIndices; uint16 *ind = mesh->indices; int32 numIndices = mesh->numIndices; for(; numIndices > 0; numIndices -= 256){ @@ -253,6 +258,17 @@ registerMeshPlugin(void) Geometry::registerPluginStream(0x50E, readMesh, writeMesh, getSizeMesh); } +void +MeshHeader::allocateIndices(void) +{ + uint16 *p = new uint16[this->totalIndices]; + Mesh *mesh = this->mesh; + for(uint32 i = 0; i < this->numMeshes; i++){ + mesh->indices = p; + p += mesh->numIndices; + } +} + // Native Data static void* diff --git a/src/rwd3d.h b/src/rwd3d.h index edb0aa5..ac4a6ea 100644 --- a/src/rwd3d.h +++ b/src/rwd3d.h @@ -65,6 +65,7 @@ void unlockIndices(void *indexBuffer); void *createVertexBuffer(uint32 length, uint32 fvf, int32 pool); uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags); void unlockVertices(void *vertexBuffer); +void deleteObject(void *object); } } diff --git a/src/rwobjects.h b/src/rwobjects.h index 55642dc..7afa1fc 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -245,6 +245,8 @@ struct MeshHeader // RW has uint16 serialNum here uint32 totalIndices; Mesh *mesh; // RW has a byte offset here + + void allocateIndices(void); }; struct MorphTarget diff --git a/src/rwpipeline.h b/src/rwpipeline.h index d59371e..2f31fcf 100644 --- a/src/rwpipeline.h +++ b/src/rwpipeline.h @@ -47,7 +47,10 @@ enum { }; void instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride); +void uninstV3d(int type, float *dst, uint8 *src, uint32 numVertices, uint32 stride); void instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride); +void uninstV2d(int type, float *dst, uint8 *src, uint32 numVertices, uint32 stride); bool32 instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride); +void uninstColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride); } diff --git a/src/xbox.cpp b/src/xbox.cpp index a8329cd..2f68944 100644 --- a/src/xbox.cpp +++ b/src/xbox.cpp @@ -24,7 +24,10 @@ destroyNativeData(void *object, int32, int32) assert(geometry->instData->platform == PLATFORM_XBOX); InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; - // TODO + geometry->instData = NULL; + delete[] header->vertexBuffer; + delete[] header->begin; + delete[] header->data; delete header; return object; } diff --git a/tools/d3d9/d3dInit.cpp b/tools/d3d9/d3dInit.cpp index 5b748b5..207fb93 100644 --- a/tools/d3d9/d3dInit.cpp +++ b/tools/d3d9/d3dInit.cpp @@ -210,12 +210,15 @@ drawAtomic(Atomic *atomic) } rw::Clump *clump; +void (*renderCB)(rw::Atomic*) = NULL; void initrw(void) { rw::currentTexDictionary = new rw::TexDictionary; - rw::Image::setSearchPath("D:\\rockstargames\\ps2\\gta3\\MODELS\\gta3_archive\\txd_extracted\\;D:\\rockstargames\\ps2\\gtavc\\MODELS\\gta3_archive\\txd_extracted\\;D:\\rockstargames\\ps2\\gtasa\\models\\gta3_archive\\txd_extracted\\"); + rw::Image::setSearchPath("D:\\rockstargames\\ps2\\gta3\\MODELS\\gta3_archive\\txd_extracted\\;" + "D:\\rockstargames\\ps2\\gtavc\\MODELS\\gta3_archive\\txd_extracted\\;" + "D:\\rockstargames\\ps2\\gtasa\\models\\gta3_archive\\txd_extracted\\"); gta::registerEnvSpecPlugin(); rw::registerMatFXPlugin(); @@ -233,16 +236,17 @@ initrw(void) rw::registerNativeDataPlugin(); rw::registerMeshPlugin(); rw::Atomic::init(); + rw::d3d::registerNativeRaster(); - rw::platform = rw::PLATFORM_D3D8; + rw::platform = rw::PLATFORM_D3D9; rw::d3d::device = Device; -// char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\admiral.dff"; + char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\admiral.dff"; // char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\player.dff"; // char *filename = "C:\\gtasa\\test\\hanger.dff"; // char *filename = "C:\\Users\\aap\\Desktop\\tmp\\out.dff"; - char *filename = "out2.dff"; +// char *filename = "out2.dff"; rw::StreamFile in; if(in.open(filename, "rb") == NULL){ MessageBox(0, "couldn't open file\n", 0, 0); @@ -257,6 +261,10 @@ initrw(void) rw::Atomic *a = clump->atomicList[i]; a->getPipeline()->instance(a); } + if(rw::platform == rw::PLATFORM_D3D8) + renderCB = rw::d3d8::drawAtomic; + else if(rw::platform == rw::PLATFORM_D3D9) + renderCB = rw::d3d9::drawAtomic; // rw::StreamFile out; // out.open("out2.dff", "wb"); @@ -329,10 +337,7 @@ Display(float timeDelta) gta::nodeNameOffset); if(strstr(name, "_dam") || strstr(name, "_vlo")) continue; - if(rw::platform == rw::PLATFORM_D3D9) - rw::d3d9::drawAtomic(clump->atomicList[i]); - else if(rw::platform == rw::PLATFORM_D3D8) - rw::d3d8::drawAtomic(clump->atomicList[i]); + renderCB(clump->atomicList[i]); } Device->EndScene(); diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index f693f52..0e74b10 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -32,7 +32,8 @@ main(int argc, char *argv[]) // rw::version = 0x33002; // rw::platform = rw::PLATFORM_PS2; // rw::platform = rw::PLATFORM_OGL; - rw::platform = rw::PLATFORM_XBOX; +// rw::platform = rw::PLATFORM_XBOX; + rw::platform = rw::PLATFORM_D3D8; int uninstance = 0; int arg = 1;