From 0c96bc7b990c5dfb4db99b7f5fc2c263b7413d4e Mon Sep 17 00:00:00 2001 From: aap Date: Mon, 7 Sep 2015 14:50:10 +0200 Subject: [PATCH] implemented d3d8 native data read/write and instance --- librw.vcxproj | 4 + rw.h | 2 + src/clump.cpp | 3 + src/d3d.cpp | 96 +++++++++++++ src/d3d8.cpp | 317 +++++++++++++++++++++++++++++++++++++++++ src/d3d9.cpp | 152 ++------------------ src/pipeline.cpp | 5 +- src/plugins.cpp | 43 ++++-- src/rwd3d.h | 70 +++++++++ src/rwd3d8.h | 56 ++++++++ src/rwd3d9.h | 16 --- src/rwpipeline.h | 5 +- src/xbox.cpp | 2 +- tools/d3d9/d3dInit.cpp | 64 +++++++-- 14 files changed, 651 insertions(+), 184 deletions(-) create mode 100644 src/d3d.cpp create mode 100644 src/d3d8.cpp create mode 100644 src/rwd3d.h create mode 100644 src/rwd3d8.h diff --git a/librw.vcxproj b/librw.vcxproj index 15cb3ef..e286e8d 100644 --- a/librw.vcxproj +++ b/librw.vcxproj @@ -99,6 +99,8 @@ + + @@ -113,6 +115,8 @@ + + diff --git a/rw.h b/rw.h index 8a98324..e633a40 100644 --- a/rw.h +++ b/rw.h @@ -4,5 +4,7 @@ #include "src/rwobjects.h" #include "src/rwps2.h" #include "src/rwxbox.h" +#include "src/rwd3d.h" +#include "src/rwd3d8.h" #include "src/rwd3d9.h" #include "src/rwogl.h" diff --git a/src/clump.cpp b/src/clump.cpp index d857282..7d9f695 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -12,6 +12,7 @@ #include "rwps2.h" #include "rwogl.h" #include "rwxbox.h" +#include "rwd3d8.h" #include "rwd3d9.h" using namespace std; @@ -538,6 +539,8 @@ Atomic::init(void) gl::makeDefaultPipeline(); defaultPipelines[platformIdx[PLATFORM_XBOX]] = xbox::makeDefaultPipeline(); + defaultPipelines[platformIdx[PLATFORM_D3D8]] = + d3d8::makeDefaultPipeline(); defaultPipelines[platformIdx[PLATFORM_D3D9]] = d3d9::makeDefaultPipeline(); } diff --git a/src/d3d.cpp b/src/d3d.cpp new file mode 100644 index 0000000..268f7b1 --- /dev/null +++ b/src/d3d.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +#include + +#include "rwbase.h" +#include "rwplugin.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwd3d.h" + +using namespace std; + +namespace rw { +namespace d3d { + +#ifdef RW_D3D9 +IDirect3DDevice9 *device = NULL; +#endif + +int vertFormatMap[] = { + -1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB +}; + +void* +createIndexBuffer(uint32 length) +{ +#ifdef RW_D3D9 + IDirect3DIndexBuffer9 *ibuf; + device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); + return ibuf; +#else + return new uint8[length]; +#endif +} + +uint16* +lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags) +{ +#ifdef RW_D3D9 + uint16 *indices; + IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; + ibuf->Lock(offset, size, (void**)&indices, flags); + return indices; +#else + return (uint16*)indexBuffer; +#endif +} + +void +unlockIndices(void *indexBuffer) +{ +#ifdef RW_D3D9 + IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; + ibuf->Unlock(); +#endif +} + +void* +createVertexBuffer(uint32 length, uint32 fvf, int32 pool) +{ +#ifdef RW_D3D9 + IDirect3DVertexBuffer9 *vbuf; + device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0); + return vbuf; +#else + return new uint8[length]; +#endif +} + +uint8* +lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags) +{ +#ifdef RW_D3D9 + uint8 *verts; + IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; + vertbuf->Lock(offset, size, (void**)&verts, flags); + return verts; +#else + return (uint8*)vertexBuffer; +#endif +} + +void +unlockVertices(void *vertexBuffer) +{ +#ifdef RW_D3D9 + IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; + vertbuf->Unlock(); +#endif +} + +} +} diff --git a/src/d3d8.cpp b/src/d3d8.cpp new file mode 100644 index 0000000..44e6ee9 --- /dev/null +++ b/src/d3d8.cpp @@ -0,0 +1,317 @@ +#include +#include +#include +#include + +#include + +#include "rwbase.h" +#include "rwplugin.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwd3d.h" +#include "rwd3d8.h" + +using namespace std; + +namespace rw { +namespace d3d8 { +using namespace d3d; + +uint32 +makeFVFDeclaration(uint32 flags, int32 numTex) +{ + uint32 fvf = 0x2; + if(flags & Geometry::NORMALS) + fvf |= 0x10; + if(flags & Geometry::PRELIT) + fvf |= 0x40; + fvf |= numTex << 8; + return fvf; +} + +int32 +getStride(uint32 flags, int32 numTex) +{ + int32 stride = 12; + if(flags & Geometry::NORMALS) + stride += 12;; + if(flags & Geometry::PRELIT) + stride += 4; + stride += numTex*8; + return stride; +} + +void* +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; + delete header; + return object; +} + +void +readNativeData(Stream *stream, int32, void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + uint32 vers; + assert(findChunk(stream, ID_STRUCT, NULL, &vers)); + assert(stream->readU32() == PLATFORM_D3D8); + InstanceDataHeader *header = new InstanceDataHeader; + geometry->instData = header; + header->platform = PLATFORM_D3D8; + + int32 size = stream->readI32(); + uint8 *data = new uint8[size]; + stream->read(data, size); + uint8 *p = data; + header->serialNumber = *(uint16*)p; p += 2; + header->numMeshes = *(uint16*)p; p += 2; + header->inst = new InstanceData[header->numMeshes]; + + InstanceData *inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + inst->minVert = *(uint32*)p; p += 4; + inst->stride = *(uint32*)p; p += 4; + inst->numVertices = *(uint32*)p; p += 4; + inst->numIndices = *(uint32*)p; p += 4; + uint32 matid = *(uint32*)p; p += 4; + inst->material = geometry->materialList[matid]; + inst->vertexShader = *(uint32*)p; p += 4; + inst->primType = *(uint32*)p; p += 4; + inst->indexBuffer = NULL; p += 4; + inst->vertexBuffer = NULL; p += 4; + inst->baseIndex = 0; p += 4; + inst->vertexAlpha = *p++; + inst->managed = 0; p++; + inst->remapped = 0; p++; // TODO: really unused? and what's that anyway? + inst++; + } + delete[] data; + + inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + inst->indexBuffer = createIndexBuffer(inst->numIndices*2); + uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); + stream->read(indices, 2*inst->numIndices); + unlockIndices(inst->indexBuffer); + + inst->managed = 1; + inst->vertexBuffer = createVertexBuffer(inst->stride*inst->numVertices, 0, D3DPOOL_MANAGED); + uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + stream->read(verts, inst->stride*inst->numVertices); + unlockVertices(inst->vertexBuffer); + + inst++; + } +} + +void +writeNativeData(Stream *stream, int32 len, void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + writeChunkHeader(stream, ID_STRUCT, len-12); + assert(geometry->instData != NULL); + assert(geometry->instData->platform == PLATFORM_D3D8); + stream->writeU32(PLATFORM_D3D8); + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + + int32 size = 4 + geometry->meshHeader->numMeshes*0x2C; + uint8 *data = new uint8[size]; + stream->writeI32(size); + uint8 *p = data; + *(uint16*)p = header->serialNumber; p += 2; + *(uint16*)p = header->numMeshes; p += 2; + + InstanceData *inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + *(uint32*)p = inst->minVert; p += 4; + *(uint32*)p = inst->stride; p += 4; + *(uint32*)p = inst->numVertices; p += 4; + *(uint32*)p = inst->numIndices; p += 4; + int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials); + *(int32*)p = matid; p += 4; + *(uint32*)p = inst->vertexShader; p += 4; + *(uint32*)p = inst->primType; p += 4; + *(uint32*)p = 0; p += 4; // index buffer + *(uint32*)p = 0; p += 4; // vertex buffer + *(uint32*)p = inst->baseIndex; p += 4; + *p++ = inst->vertexAlpha; + *p++ = inst->managed; + *p++ = inst->remapped; + inst++; + } + stream->write(data, size); + delete[] data; + + inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); + stream->write(indices, 2*inst->numIndices); + unlockIndices(inst->indexBuffer); + + uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + stream->write(verts, inst->stride*inst->numVertices); + unlockVertices(inst->vertexBuffer); + inst++; + } +} + +int32 +getSizeNativeData(void *object, int32, int32) +{ + Geometry *geometry = (Geometry*)object; + assert(geometry->instData != NULL); + assert(geometry->instData->platform == PLATFORM_D3D8); + + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; + InstanceData *inst = header->inst; + int32 size = 12 + 4 + 4 + 4 + header->numMeshes*0x2C; + for(int32 i = 0; i < header->numMeshes; i++){ + size += inst->numIndices*2 + inst->numVertices*inst->stride; + inst++; + } + return size; +} + +void +registerNativeDataPlugin(void) +{ + Geometry::registerPlugin(0, ID_NATIVEDATA, + NULL, destroyNativeData, NULL); + Geometry::registerPluginStream(ID_NATIVEDATA, + readNativeData, + writeNativeData, + getSizeNativeData); +} + + +ObjPipeline::ObjPipeline(uint32 platform) + : rw::ObjPipeline(platform), + instanceCB(NULL), uninstanceCB(NULL) { } + +void +ObjPipeline::instance(Atomic *atomic) +{ + Geometry *geo = atomic->geometry; + if(geo->geoflags & Geometry::NATIVE) + return; + geo->geoflags |= Geometry::NATIVE; + InstanceDataHeader *header = new InstanceDataHeader; + MeshHeader *meshh = geo->meshHeader; + geo->instData = header; + header->platform = PLATFORM_D3D8; + + header->serialNumber = 0; + header->numMeshes = meshh->numMeshes; + header->inst = new InstanceData[header->numMeshes]; + + InstanceData *inst = header->inst; + Mesh *mesh = meshh->mesh; + for(uint32 i = 0; i < header->numMeshes; i++){ + findMinVertAndNumVertices(mesh->indices, mesh->numIndices, + &inst->minVert, &inst->numVertices); + inst->numIndices = mesh->numIndices; + inst->material = mesh->material; + inst->vertexShader = 0; + inst->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST; + inst->vertexBuffer = NULL; + inst->baseIndex = 0; // (maybe) not used by us + inst->vertexAlpha = 0; + inst->managed = 0; + inst->remapped = 0; + + inst->indexBuffer = createIndexBuffer(inst->numIndices*sizeof(uint16)); + uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); + if(inst->minVert == 0) + memcpy(indices, mesh->indices, inst->numIndices*sizeof(uint16)); + else + for(int32 j = 0; j < inst->numIndices; j++) + indices[j] = mesh->indices[j] - inst->minVert; + unlockIndices(inst->indexBuffer); + + this->instanceCB(geo, inst); + mesh++; + inst++; + } +} + +void +ObjPipeline::uninstance(Atomic *atomic) +{ + assert(0 && "can't uninstance"); +} + +void +defaultInstanceCB(Geometry *geo, InstanceData *inst) +{ + inst->vertexShader = makeFVFDeclaration(geo->geoflags, geo->numTexCoordSets); + inst->stride = getStride(geo->geoflags, geo->numTexCoordSets); + + inst->vertexBuffer = createVertexBuffer(inst->numVertices*inst->stride, + inst->vertexShader, D3DPOOL_MANAGED); + inst->managed = 1; + + uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); + instV3d(VERT_FLOAT3, dst, + &geo->morphTargets[0].vertices[3*inst->minVert], + inst->numVertices, inst->stride); + dst += 12; + + if(geo->geoflags & Geometry::NORMALS){ + instV3d(VERT_FLOAT3, dst, + &geo->morphTargets[0].normals[3*inst->minVert], + inst->numVertices, inst->stride); + dst += 12; + } + + inst->vertexAlpha = 0; + if(geo->geoflags & Geometry::PRELIT){ + inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[4*inst->minVert], + inst->numVertices, inst->stride); + dst += 4; + } + + for(int32 i = 0; i < geo->numTexCoordSets; i++){ + instV2d(VERT_FLOAT2, dst, &geo->texCoords[i][2*inst->minVert], + inst->numVertices, inst->stride); + dst += 8; + } + unlockVertices(inst->vertexBuffer); +} + +ObjPipeline* +makeDefaultPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); + pipe->instanceCB = defaultInstanceCB; + return pipe; +} + +ObjPipeline* +makeSkinPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); + pipe->instanceCB = defaultInstanceCB; + pipe->pluginID = ID_SKIN; + pipe->pluginData = 1; + return pipe; +} + +ObjPipeline* +makeMatFXPipeline(void) +{ + ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D8); + pipe->instanceCB = defaultInstanceCB; + pipe->pluginID = ID_MATFX; + pipe->pluginData = 0; + return pipe; +} + +} +} diff --git a/src/d3d9.cpp b/src/d3d9.cpp index f7118a2..9ab1ef4 100644 --- a/src/d3d9.cpp +++ b/src/d3d9.cpp @@ -9,116 +9,20 @@ #include "rwplugin.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwd3d.h" #include "rwd3d9.h" using namespace std; namespace rw { namespace d3d9 { +using namespace d3d; -#ifdef RW_D3D9 -IDirect3DDevice9 *device = NULL; -#else -enum { - D3DLOCK_NOSYSLOCK = 0, // ignored - D3DPOOL_MANAGED = 0, // ignored - D3DPT_TRIANGLELIST = 4, - D3DPT_TRIANGLESTRIP = 5, - - - D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) - D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) - D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) - D3DDECLTYPE_FLOAT4 = 3, // 4D float - D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range - // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) - D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte - D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.) - D3DDECLTYPE_SHORT4 = 7, // 4D signed short - - D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 - D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) - D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) - D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) - D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) - D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) - D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) - D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) - D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values - D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. - - - D3DDECLMETHOD_DEFAULT = 0, - - - D3DDECLUSAGE_POSITION = 0, - D3DDECLUSAGE_BLENDWEIGHT, // 1 - D3DDECLUSAGE_BLENDINDICES, // 2 - D3DDECLUSAGE_NORMAL, // 3 - D3DDECLUSAGE_PSIZE, // 4 - D3DDECLUSAGE_TEXCOORD, // 5 - D3DDECLUSAGE_TANGENT, // 6 - D3DDECLUSAGE_BINORMAL, // 7 - D3DDECLUSAGE_TESSFACTOR, // 8 - D3DDECLUSAGE_POSITIONT, // 9 - D3DDECLUSAGE_COLOR, // 10 - D3DDECLUSAGE_FOG, // 11 - D3DDECLUSAGE_DEPTH, // 12 - D3DDECLUSAGE_SAMPLE, // 13 -}; +// TODO: move to header, but not as #define +#ifndef RW_D3D9 #define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} -#define D3DCOLOR_ARGB(a,r,g,b) \ - ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) #endif -int vertFormatMap[] = { - -1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB -}; - -uint16* -lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags) -{ -#ifdef RW_D3D9 - uint16 *indices; - IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; - ibuf->Lock(offset, size, (void**)&indices, flags); - return indices; -#else - return (uint16*)indexBuffer; -#endif -} - -void -unlockIndices(void *indexBuffer) -{ -#ifdef RW_D3D9 - IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer; - ibuf->Unlock(); -#endif -} - -uint8* -lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags) -{ -#ifdef RW_D3D9 - uint8 *verts; - IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; - vertbuf->Lock(offset, size, (void**)&verts, flags); - return verts; -#else - return (uint8*)vertexBuffer; -#endif -} - -void -unlockVertices(void *vertexBuffer) -{ -#ifdef RW_D3D9 - IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer; - vertbuf->Unlock(); -#endif -} - void* createVertexDeclaration(VertexElement *elements) { @@ -156,29 +60,6 @@ getDeclaration(void *declaration, VertexElement *elements) #endif } -void* -createIndexBuffer(uint32 length) -{ -#ifdef RW_D3D9 - IDirect3DIndexBuffer9 *ibuf; - device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); - return ibuf; -#else - return new uint8[length]; -#endif -} - -void* -createVertexBuffer(uint32 length, int32 pool) -{ -#ifdef RW_D3D9 - IDirect3DVertexBuffer9 *vbuf; - device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, 0, (D3DPOOL)pool, &vbuf, 0); - return vbuf; -#else - return new uint8[length]; -#endif -} void* destroyNativeData(void *object, int32, int32) @@ -203,6 +84,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) InstanceDataHeader *header = new InstanceDataHeader; geometry->instData = header; header->platform = PLATFORM_D3D9; + int32 size = stream->readI32(); uint8 *data = new uint8[size]; stream->read(data, size); @@ -238,8 +120,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) stream->read(elements, numDeclarations*8); header->vertexDeclaration = createVertexDeclaration(elements); - header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16)); - + header->indexBuffer = createIndexBuffer(header->totalNumIndex*2); uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0); stream->read(indices, 2*header->totalNumIndex); unlockIndices(header->indexBuffer); @@ -260,8 +141,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) continue; // TODO: unset managed flag when using morph targets. // also uses different buffer type and locks differently - s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, D3DPOOL_MANAGED); - + s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, 0, D3DPOOL_MANAGED); uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); stream->read(verts, s->stride*header->totalNumVertex); unlockVertices(s->vertexBuffer); @@ -407,7 +287,7 @@ ObjPipeline::instance(Atomic *atomic) uint32 startindex = 0; for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, - &inst->minVert, &inst->numVertices); + &inst->minVert, (int32*)&inst->numVertices); inst->numIndex = mesh->numIndices; inst->material = mesh->material; inst->vertexAlpha = 0; @@ -419,23 +299,14 @@ ObjPipeline::instance(Atomic *atomic) memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*sizeof(uint16)); else for(uint32 j = 0; j < inst->numIndex; j++) - indices[inst->startIndex+j] = mesh->indices[j]-inst->minVert; + indices[inst->startIndex+j] = mesh->indices[j] - inst->minVert; startindex += inst->numIndex; mesh++; inst++; } unlockIndices(header->indexBuffer); - VertexStream *s; - for(int i = 0; i < 2; i++){ - s = &header->vertexStream[i]; - s->vertexBuffer = NULL; - s->offset = 0; - s->stride = 0; - s->geometryFlags = 0; - s->managed = 0; - s->dynamicLock = 0; - } + memset(&header->vertexStream, 0, 2*sizeof(VertexStream)); this->instanceCB(geo, header); } @@ -446,6 +317,7 @@ ObjPipeline::uninstance(Atomic *atomic) assert(0 && "can't uninstance"); } +// TODO: support more than one set of tex coords void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) { @@ -487,7 +359,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl); - s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, D3DPOOL_MANAGED); + s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, D3DPOOL_MANAGED); uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++) diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 09b74d7..2cdba2f 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -11,6 +11,9 @@ #include "rwobjects.h" #include "rwps2.h" +#define COLOR_ARGB(a,r,g,b) \ + ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) + using namespace std; namespace rw { @@ -57,7 +60,7 @@ ObjPipeline::render(Atomic*) // helper functions void -findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices) +findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, int32 *numVertices) { uint32 min = 0xFFFFFFFF; uint32 max = 0; diff --git a/src/plugins.cpp b/src/plugins.cpp index 68f6d5e..5af3076 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -10,9 +10,10 @@ #include "rwpipeline.h" #include "rwobjects.h" #include "rwps2.h" -#include "rwxbox.h" -#include "rwd3d9.h" #include "rwogl.h" +#include "rwxbox.h" +#include "rwd3d8.h" +#include "rwd3d9.h" using namespace std; @@ -262,12 +263,14 @@ destroyNativeData(void *object, int32 offset, int32 size) return object; if(geometry->instData->platform == PLATFORM_PS2) return ps2::destroyNativeData(object, offset, size); - if(geometry->instData->platform == PLATFORM_XBOX) - return xbox::destroyNativeData(object, offset, size); - if(geometry->instData->platform == PLATFORM_D3D9) - return d3d9::destroyNativeData(object, offset, size); if(geometry->instData->platform == PLATFORM_OGL) return gl::destroyNativeData(object, offset, size); + if(geometry->instData->platform == PLATFORM_XBOX) + return xbox::destroyNativeData(object, offset, size); + if(geometry->instData->platform == PLATFORM_D3D8) + return d3d8::destroyNativeData(object, offset, size); + if(geometry->instData->platform == PLATFORM_D3D9) + return d3d9::destroyNativeData(object, offset, size); return object; } @@ -289,6 +292,8 @@ readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) ps2::readNativeData(stream, len, object, o, s); else if(platform == PLATFORM_XBOX) xbox::readNativeData(stream, len, object, o, s); + else if(platform == PLATFORM_D3D8) + d3d8::readNativeData(stream, len, object, o, s); else if(platform == PLATFORM_D3D9) d3d9::readNativeData(stream, len, object, o, s); else{ @@ -309,12 +314,14 @@ writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) return; if(geometry->instData->platform == PLATFORM_PS2) ps2::writeNativeData(stream, len, object, o, s); - else if(geometry->instData->platform == PLATFORM_XBOX) - xbox::writeNativeData(stream, len, object, o, s); - else if(geometry->instData->platform == PLATFORM_D3D9) - d3d9::writeNativeData(stream, len, object, o, s); else if(geometry->instData->platform == PLATFORM_OGL) gl::writeNativeData(stream, len, object, o, s); + else if(geometry->instData->platform == PLATFORM_XBOX) + xbox::writeNativeData(stream, len, object, o, s); + else if(geometry->instData->platform == PLATFORM_D3D8) + d3d8::writeNativeData(stream, len, object, o, s); + else if(geometry->instData->platform == PLATFORM_D3D9) + d3d9::writeNativeData(stream, len, object, o, s); } static int32 @@ -325,12 +332,14 @@ getSizeNativeData(void *object, int32 offset, int32 size) return -1; if(geometry->instData->platform == PLATFORM_PS2) return ps2::getSizeNativeData(object, offset, size); - else if(geometry->instData->platform == PLATFORM_XBOX) - return xbox::getSizeNativeData(object, offset, size); - else if(geometry->instData->platform == PLATFORM_D3D9) - return d3d9::getSizeNativeData(object, offset, size); else if(geometry->instData->platform == PLATFORM_OGL) return gl::getSizeNativeData(object, offset, size); + else if(geometry->instData->platform == PLATFORM_XBOX) + return xbox::getSizeNativeData(object, offset, size); + else if(geometry->instData->platform == PLATFORM_D3D8) + return d3d8::getSizeNativeData(object, offset, size); + else if(geometry->instData->platform == PLATFORM_D3D9) + return d3d9::getSizeNativeData(object, offset, size); return -1; } @@ -511,6 +520,8 @@ getSizeSkin(void *object, int32 offset, int32) return xbox::getSizeNativeSkin(object, offset); if(geometry->instData->platform == PLATFORM_OGL) return gl::getSizeNativeSkin(object, offset); + if(geometry->instData->platform == PLATFORM_D3D8) + return -1; if(geometry->instData->platform == PLATFORM_D3D9) return -1; assert(0 && "unsupported native skin platform"); @@ -550,6 +561,8 @@ registerSkinPlugin(void) gl::makeSkinPipeline(); skinGlobals.pipelines[platformIdx[PLATFORM_XBOX]] = xbox::makeSkinPipeline(); + skinGlobals.pipelines[platformIdx[PLATFORM_D3D8]] = + d3d8::makeSkinPipeline(); skinGlobals.pipelines[platformIdx[PLATFORM_D3D9]] = d3d9::makeSkinPipeline(); @@ -963,6 +976,8 @@ registerMatFXPlugin(void) gl::makeMatFXPipeline(); matFXGlobals.pipelines[platformIdx[PLATFORM_XBOX]] = xbox::makeMatFXPipeline(); + matFXGlobals.pipelines[platformIdx[PLATFORM_D3D8]] = + d3d8::makeMatFXPipeline(); matFXGlobals.pipelines[platformIdx[PLATFORM_D3D9]] = d3d9::makeMatFXPipeline(); diff --git a/src/rwd3d.h b/src/rwd3d.h new file mode 100644 index 0000000..edb0aa5 --- /dev/null +++ b/src/rwd3d.h @@ -0,0 +1,70 @@ +#ifdef RW_D3D9 +#include +#endif + +namespace rw { +namespace d3d { + +#ifdef RW_D3D9 +extern IDirect3DDevice9 *device; +#else +enum { + D3DLOCK_NOSYSLOCK = 0, // ignored + D3DPOOL_MANAGED = 0, // ignored + D3DPT_TRIANGLELIST = 4, + D3DPT_TRIANGLESTRIP = 5, + + + D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.) + D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.) + D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.) + D3DDECLTYPE_FLOAT4 = 3, // 4D float + D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range + // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) + D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte + D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.) + D3DDECLTYPE_SHORT4 = 7, // 4D signed short + + D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 + D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) + D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) + D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) + D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) + D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) + D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) + D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) + D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values + D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. + + + D3DDECLMETHOD_DEFAULT = 0, + + + D3DDECLUSAGE_POSITION = 0, + D3DDECLUSAGE_BLENDWEIGHT, // 1 + D3DDECLUSAGE_BLENDINDICES, // 2 + D3DDECLUSAGE_NORMAL, // 3 + D3DDECLUSAGE_PSIZE, // 4 + D3DDECLUSAGE_TEXCOORD, // 5 + D3DDECLUSAGE_TANGENT, // 6 + D3DDECLUSAGE_BINORMAL, // 7 + D3DDECLUSAGE_TESSFACTOR, // 8 + D3DDECLUSAGE_POSITIONT, // 9 + D3DDECLUSAGE_COLOR, // 10 + D3DDECLUSAGE_FOG, // 11 + D3DDECLUSAGE_DEPTH, // 12 + D3DDECLUSAGE_SAMPLE, // 13 +}; +#endif + +extern int vertFormatMap[]; + +void *createIndexBuffer(uint32 length); +uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags); +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); + +} +} diff --git a/src/rwd3d8.h b/src/rwd3d8.h new file mode 100644 index 0000000..25b4b30 --- /dev/null +++ b/src/rwd3d8.h @@ -0,0 +1,56 @@ +namespace rw { +namespace d3d8 { + +struct InstanceData +{ + uint32 minVert; + int32 stride; + int32 numVertices; + int32 numIndices; + Material *material; + uint32 vertexShader; + uint32 primType; + void *indexBuffer; + void *vertexBuffer; + uint32 baseIndex; + uint8 vertexAlpha; + uint8 managed; + uint8 remapped; +}; + +struct InstanceDataHeader : rw::InstanceDataHeader +{ + uint16 serialNumber; + uint16 numMeshes; + + InstanceData *inst; +}; + +uint32 makeFVFDeclaration(uint32 flags, int32 numTex); +int32 getStride(uint32 flags, int32 numTex); + +void *destroyNativeData(void *object, int32, int32); +void readNativeData(Stream *stream, int32 len, void *object, int32, int32); +void writeNativeData(Stream *stream, int32 len, void *object, int32, int32); +int32 getSizeNativeData(void *object, int32, int32); +void registerNativeDataPlugin(void); + +class ObjPipeline : public rw::ObjPipeline +{ +public: + void (*instanceCB)(Geometry *geo, InstanceData *header); + void (*uninstanceCB)(Geometry *geo, InstanceData *header); + + ObjPipeline(uint32 platform); + virtual void instance(Atomic *atomic); + virtual void uninstance(Atomic *atomic); +}; + +ObjPipeline *makeDefaultPipeline(void); + +ObjPipeline *makeSkinPipeline(void); + +ObjPipeline *makeMatFXPipeline(void); + +} +} diff --git a/src/rwd3d9.h b/src/rwd3d9.h index 9a9b87a..65fad26 100644 --- a/src/rwd3d9.h +++ b/src/rwd3d9.h @@ -1,7 +1,3 @@ -#ifdef RW_D3D9 -#include -#endif - namespace rw { namespace d3d9 { @@ -53,20 +49,8 @@ struct InstanceDataHeader : rw::InstanceDataHeader InstanceData *inst; }; -#ifdef RW_D3D9 -extern IDirect3DDevice9 *device; -#endif - -extern int vertFormatMap[]; - -uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags); -void unlockIndices(void *indexBuffer); -uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags); -void unlockVertices(void *vertexBuffer); void *createVertexDeclaration(VertexElement *elements); uint32 getDeclaration(void *declaration, VertexElement *elements); -void *createIndexBuffer(uint32 length); -void *createVertexBuffer(uint32 length, int32 pool); void *destroyNativeData(void *object, int32, int32); void readNativeData(Stream *stream, int32 len, void *object, int32, int32); diff --git a/src/rwpipeline.h b/src/rwpipeline.h index 5502ccf..d59371e 100644 --- a/src/rwpipeline.h +++ b/src/rwpipeline.h @@ -30,7 +30,7 @@ public: virtual void render(Atomic *atomic); }; -void findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices); +void findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, int32 *numVertices); // everything xbox, d3d8 and d3d9 may want to use enum { @@ -46,9 +46,6 @@ enum { VERT_COMPNORM }; -#define COLOR_ARGB(a,r,g,b) \ - ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) - void instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride); void instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride); bool32 instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride); diff --git a/src/xbox.cpp b/src/xbox.cpp index e91591e..a8329cd 100644 --- a/src/xbox.cpp +++ b/src/xbox.cpp @@ -180,7 +180,7 @@ ObjPipeline::instance(Atomic *atomic) uint8 *indexbuf = (uint8*)header->data + ((0x18 + 0x24 + header->numMeshes*0x18 + 0xF)&~0xF); for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, - &inst->minVert, (uint32*)&inst->numVertices); + &inst->minVert, &inst->numVertices); inst->numIndices = mesh->numIndices; inst->indexBuffer = indexbuf; memcpy(inst->indexBuffer, mesh->indices, inst->numIndices*sizeof(uint16)); diff --git a/tools/d3d9/d3dInit.cpp b/tools/d3d9/d3dInit.cpp index 727e1b8..5b748b5 100644 --- a/tools/d3d9/d3dInit.cpp +++ b/tools/d3d9/d3dInit.cpp @@ -12,7 +12,8 @@ IDirect3DDevice9 *Device = 0; Camera *camera; namespace rw { -namespace d3d9 { + +namespace d3d { int32 nativeRasterOffset; @@ -127,6 +128,11 @@ setMaterial(Material *mat) Device->SetMaterial(&mat9); } +} + +namespace d3d9 { +using namespace d3d; + void drawAtomic(Atomic *atomic) { @@ -156,13 +162,51 @@ drawAtomic(Atomic *atomic) if(geo->geoflags & Geometry::PRELIT) Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); Device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, - 0/*inst->minVert*/, inst->numVertices, + 0, inst->numVertices, inst->startIndex, inst->numPrimitives); inst++; } } - } + +namespace d3d8 { +using namespace d3d; + +void +drawAtomic(Atomic *atomic) +{ + Geometry *geo = atomic->geometry; + if((geo->geoflags & Geometry::NATIVE) == 0) + return; + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; + + atomic->frame->updateLTM(); + Device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)atomic->frame->ltm); + + InstanceData *inst = header->inst; + for(uint32 i = 0; i < header->numMeshes; i++){ + if(inst->material->texture) + setTexture(inst->material->texture); + else + Device->SetTexture(0, NULL); + setMaterial(inst->material); + Device->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40)); + Device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); + Device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); + if(geo->geoflags & Geometry::PRELIT) + Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); + + Device->SetFVF(inst->vertexShader); + Device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride); + Device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer); + uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3; + Device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex, + 0, inst->numVertices, 0, numPrim); + inst++; + } +} +} + } rw::Clump *clump; @@ -189,15 +233,16 @@ initrw(void) rw::registerNativeDataPlugin(); rw::registerMeshPlugin(); rw::Atomic::init(); - rw::d3d9::registerNativeRaster(); + rw::d3d::registerNativeRaster(); - rw::d3d9::device = Device; + rw::platform = rw::PLATFORM_D3D8; + 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 = "out.dff"; + char *filename = "out2.dff"; rw::StreamFile in; if(in.open(filename, "rb") == NULL){ MessageBox(0, "couldn't open file\n", 0, 0); @@ -284,7 +329,10 @@ Display(float timeDelta) gta::nodeNameOffset); if(strstr(name, "_dam") || strstr(name, "_vlo")) continue; - rw::d3d9::drawAtomic(clump->atomicList[i]); + 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]); } Device->EndScene();