diff --git a/src/d3d.cpp b/src/d3d.cpp index 80f3ac6..7b2f0a7 100644 --- a/src/d3d.cpp +++ b/src/d3d.cpp @@ -39,6 +39,8 @@ createIndexBuffer(uint32 length) uint16* lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags) { + if(indexBuffer == NULL) + return NULL; #ifdef RW_D3D9 uint16 *indices; IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; @@ -52,6 +54,8 @@ lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags) void unlockIndices(void *indexBuffer) { + if(indexBuffer == NULL) + return; #ifdef RW_D3D9 IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; ibuf->Unlock(); @@ -73,6 +77,8 @@ createVertexBuffer(uint32 length, uint32 fvf, int32 pool) uint8* lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags) { + if(vertexBuffer == NULL) + return NULL; #ifdef RW_D3D9 uint8 *verts; IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; @@ -86,6 +92,8 @@ lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags) void unlockVertices(void *vertexBuffer) { + if(vertexBuffer == NULL) + return; #ifdef RW_D3D9 IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; vertbuf->Unlock(); diff --git a/src/d3d8.cpp b/src/d3d8.cpp index 77185a1..ef3c9d7 100644 --- a/src/d3d8.cpp +++ b/src/d3d8.cpp @@ -233,10 +233,10 @@ ObjPipeline::instance(Atomic *atomic) inst->managed = 0; inst->remapped = 0; - inst->indexBuffer = createIndexBuffer(inst->numIndices*sizeof(uint16)); + inst->indexBuffer = createIndexBuffer(inst->numIndices*2); uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); if(inst->minVert == 0) - memcpy(indices, mesh->indices, inst->numIndices*sizeof(uint16)); + memcpy(indices, mesh->indices, inst->numIndices*2); else for(int32 j = 0; j < inst->numIndices; j++) indices[j] = mesh->indices[j] - inst->minVert; @@ -254,6 +254,8 @@ ObjPipeline::uninstance(Atomic *atomic) Geometry *geo = atomic->geometry; if((geo->geoflags & Geometry::NATIVE) == 0) return; + assert(geo->instData != NULL); + assert(geo->instData->platform == PLATFORM_D3D8); geo->geoflags &= ~Geometry::NATIVE; geo->allocateData(); geo->meshHeader->allocateIndices(); @@ -264,7 +266,7 @@ ObjPipeline::uninstance(Atomic *atomic) 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)); + memcpy(mesh->indices, indices, inst->numIndices*2); else for(int32 j = 0; j < inst->numIndices; j++) mesh->indices[j] = indices[j] + inst->minVert; diff --git a/src/d3d9.cpp b/src/d3d9.cpp index 0bbcf6d..591a6fd 100644 --- a/src/d3d9.cpp +++ b/src/d3d9.cpp @@ -23,6 +23,8 @@ using namespace d3d; #define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} #endif +#define NUMDECLELT 12 + void* createVertexDeclaration(VertexElement *elements) { @@ -120,7 +122,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) inst++; } - VertexElement elements[10]; + VertexElement elements[NUMDECLELT]; uint32 numDeclarations = stream->readU32(); stream->read(elements, numDeclarations*8); header->vertexDeclaration = createVertexDeclaration(elements); @@ -202,7 +204,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) } stream->write(data, size); - VertexElement elements[10]; + VertexElement elements[NUMDECLELT]; uint32 numElt = getDeclaration(header->vertexDeclaration, elements); stream->writeU32(numElt); stream->write(elements, 8*numElt); @@ -284,7 +286,7 @@ ObjPipeline::instance(Atomic *atomic) header->totalNumIndex = meshh->totalIndices; header->inst = new InstanceData[header->numMeshes]; - header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16)); + header->indexBuffer = createIndexBuffer(header->totalNumIndex*2); uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0); InstanceData *inst = header->inst; @@ -301,7 +303,7 @@ ObjPipeline::instance(Atomic *atomic) inst->startIndex = startindex; inst->numPrimitives = header->primType == D3DPT_TRIANGLESTRIP ? inst->numIndex-2 : inst->numIndex/3; if(inst->minVert == 0) - memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*sizeof(uint16)); + memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*2); else for(uint32 j = 0; j < inst->numIndex; j++) indices[inst->startIndex+j] = mesh->indices[j] - inst->minVert; @@ -319,14 +321,39 @@ 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; + assert(geo->instData != NULL); + assert(geo->instData->platform == PLATFORM_D3D9); + geo->geoflags &= ~Geometry::NATIVE; + geo->allocateData(); + geo->meshHeader->allocateIndices(); + + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0); + InstanceData *inst = header->inst; + Mesh *mesh = geo->meshHeader->mesh; + for(uint32 i = 0; i < header->numMeshes; i++){ + if(inst->minVert == 0) + memcpy(mesh->indices, &indices[inst->startIndex], inst->numIndex*2); + else + for(int32 j = 0; j < inst->numIndex; j++) + mesh->indices[j] = indices[inst->startIndex+j] + inst->minVert; + mesh++; + inst++; + } + unlockIndices(header->indexBuffer); + + this->uninstanceCB(geo, header); + geo->generateTriangles(); + destroyNativeData(geo, 0, 0); } -// TODO: support more than one set of tex coords void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) { - VertexElement dcl[6]; + VertexElement dcl[NUMDECLELT]; VertexStream *s = &header->vertexStream[0]; s->offset = 0; @@ -346,10 +373,9 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) stride += 4; } - bool isTextured = (geo->geoflags & (Geometry::TEXTURED | Geometry::TEXTURED2)) != 0; - if(isTextured){ - dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}; - s->geometryFlags |= 0x10; + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, n}; + s->geometryFlags |= 0x10 << n; stride += 8; } @@ -366,6 +392,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, D3DPOOL_MANAGED); + // TODO: support both vertex buffers uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++) ; @@ -377,17 +404,18 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) if(isPrelit){ for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++) ; + // TODO: vertex alpha (instance per mesh) instColor(vertFormatMap[dcl[i].type], verts + dcl[i].offset, geo->colors, header->totalNumVertex, header->vertexStream[dcl[i].stream].stride); } - if(isTextured){ - for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != 0; i++) + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++) ; instV2d(vertFormatMap[dcl[i].type], verts + dcl[i].offset, - geo->texCoords[0], + geo->texCoords[n], header->totalNumVertex, header->vertexStream[dcl[i].stream].stride); } @@ -403,11 +431,65 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) unlockVertices(s->vertexBuffer); } +void +defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header) +{ + VertexElement dcl[NUMDECLELT]; + uint32 numElt = getDeclaration(header->vertexDeclaration, dcl); + + uint8 *verts[2]; + verts[0] = lockVertices(header->vertexStream[0].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + verts[1] = lockVertices(header->vertexStream[1].vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + + int i; + for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++) + ; + uninstV3d(vertFormatMap[dcl[i].type], + geo->morphTargets[0].vertices, + verts[dcl[i].stream] + dcl[i].offset, + header->totalNumVertex, + header->vertexStream[dcl[i].stream].stride); + + if(geo->geoflags & Geometry::PRELIT){ + for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++) + ; + uninstColor(vertFormatMap[dcl[i].type], + geo->colors, + verts[dcl[i].stream] + dcl[i].offset, + header->totalNumVertex, + header->vertexStream[dcl[i].stream].stride); + } + + for(int32 n = 0; n < geo->numTexCoordSets; n++){ + for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++) + ; + uninstV2d(vertFormatMap[dcl[i].type], + geo->texCoords[n], + verts[dcl[i].stream] + dcl[i].offset, + header->totalNumVertex, + header->vertexStream[dcl[i].stream].stride); + } + + if(geo->geoflags & Geometry::NORMALS){ + for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++) + ; + uninstV3d(vertFormatMap[dcl[i].type], + geo->morphTargets[0].normals, + verts[dcl[i].stream] + dcl[i].offset, + header->totalNumVertex, + header->vertexStream[dcl[i].stream].stride); + } + + unlockVertices(verts[0]); + unlockVertices(verts[1]); +} + ObjPipeline* makeDefaultPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; return pipe; } @@ -416,6 +498,7 @@ makeSkinPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; pipe->pluginID = ID_SKIN; pipe->pluginData = 1; return pipe; @@ -426,6 +509,7 @@ makeMatFXPipeline(void) { ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9); pipe->instanceCB = defaultInstanceCB; + pipe->uninstanceCB = defaultUninstanceCB; pipe->pluginID = ID_MATFX; pipe->pluginData = 0; return pipe; diff --git a/src/ogl.cpp b/src/ogl.cpp index 676f936..7d44edc 100644 --- a/src/ogl.cpp +++ b/src/ogl.cpp @@ -422,6 +422,8 @@ ObjPipeline::uninstance(Atomic *atomic) Geometry *geo = atomic->geometry; if((geo->geoflags & Geometry::NATIVE) == 0) return; + assert(geo->instData != NULL); + assert(geo->instData->platform == PLATFORM_OGL); geo->geoflags &= ~Geometry::NATIVE; geo->allocateData(); diff --git a/tools/d3d9/d3dInit.cpp b/tools/d3d9/d3dInit.cpp index 207fb93..16408eb 100644 --- a/tools/d3d9/d3dInit.cpp +++ b/tools/d3d9/d3dInit.cpp @@ -244,6 +244,9 @@ initrw(void) char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\admiral.dff"; // char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\player.dff"; +// char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\od_newscafe_dy.dff"; +// char *filename = "D:\\rockstargames\\pc\\gtasa\\models\\gta3_archive\\admiral.dff"; +// char *filename = "D:\\rockstargames\\pc\\gtasa\\models\\gta3_archive\\lae2_roads89.dff"; // char *filename = "C:\\gtasa\\test\\hanger.dff"; // char *filename = "C:\\Users\\aap\\Desktop\\tmp\\out.dff"; // char *filename = "out2.dff"; @@ -267,7 +270,7 @@ initrw(void) renderCB = rw::d3d9::drawAtomic; // rw::StreamFile out; -// out.open("out2.dff", "wb"); +// out.open("out.dff", "wb"); // clump->streamWrite(&out); // out.close(); } diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index 0e74b10..cb1a0c1 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -33,7 +33,8 @@ main(int argc, char *argv[]) // rw::platform = rw::PLATFORM_PS2; // rw::platform = rw::PLATFORM_OGL; // rw::platform = rw::PLATFORM_XBOX; - rw::platform = rw::PLATFORM_D3D8; +// rw::platform = rw::PLATFORM_D3D8; + rw::platform = rw::PLATFORM_D3D9; int uninstance = 0; int arg = 1;