From c2780d56e97967f098c4d0a0face3a8b0926ed5f Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 9 Mar 2017 11:45:26 +0100 Subject: [PATCH] added correction of face winding in tristrips --- librw.vcxproj | 2 +- src/d3d/d3d8.cpp | 4 +- src/geometry.cpp | 63 ++++++++++++++++++++++++++++- src/ps2/pds.cpp | 4 +- src/rwobjects.h | 1 + tools/dumprwtree/dumprwtree.vcxproj | 2 +- 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/librw.vcxproj b/librw.vcxproj index f6e4209..4368db4 100644 --- a/librw.vcxproj +++ b/librw.vcxproj @@ -269,7 +269,7 @@ _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions) - MultiThreaded + MultiThreadedDLL true diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index a2953e7..1dcb621 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -433,7 +433,7 @@ Raster* readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels) { uint8 palette[256*4]; - uint8 *data; + uint8 *data = nil; Image *img = Image::create(width, height, 32); img->allocate(); @@ -443,7 +443,7 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format else if(format & Raster::PAL8) stream->read(palette, 4*256); - // Only read one mipmap + // Only read one mipmap for(int32 i = 0; i < numLevels; i++){ uint32 size = stream->readU32(); if(i == 0){ diff --git a/src/geometry.cpp b/src/geometry.cpp index b194039..7e9a707 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -380,7 +380,7 @@ Geometry::generateTriangles(int8 *adc) m++; continue; } - if(header->flags == 1){ // tristrip + if(header->flags == MeshHeader::TRISTRIP){ for(uint32 j = 0; j < m->numIndices-2; j++){ if(!(adc && adcbits[j+2]) && !isDegenerate(&m->indices[j])) @@ -407,7 +407,7 @@ Geometry::generateTriangles(int8 *adc) int32 matid = findPointer((void*)m->material, (void**)this->materialList, this->numMaterials); - if(header->flags == 1) // tristrip + if(header->flags == MeshHeader::TRISTRIP) for(uint32 j = 0; j < m->numIndices-2; j++){ if(adc && adcbits[j+2] || isDegenerate(&m->indices[j])) @@ -472,6 +472,62 @@ Geometry::buildMeshes(void) } } +/* The idea is that even in meshes where winding is not preserved + * every tristrip starts at an even vertex. So find the start of + * strips and insert duplicate vertices if necessary. */ +void +Geometry::correctTristripWinding(void) +{ + MeshHeader *header = this->meshHeader; + if(header == nil || header->flags != MeshHeader::TRISTRIP || + this->geoflags & NATIVE) + return; + MeshHeader *newhead = new MeshHeader; + newhead->flags = header->flags; + newhead->numMeshes = header->numMeshes; + newhead->totalIndices = 0; + newhead->mesh = new Mesh[newhead->numMeshes]; + /* get a temporary working buffer */ + uint16 *indices = new uint16[header->totalIndices*2]; + + Mesh *mesh = header->mesh; + Mesh *newmesh = newhead->mesh; + for(uint16 i = 0; i < header->numMeshes; i++){ + newmesh->numIndices = 0; + newmesh->indices = &indices[newhead->totalIndices]; + newmesh->material = mesh->material; + + bool inStrip = 0; + uint32 j; + for(j = 0; j < mesh->numIndices-2; j++){ + /* Duplicate vertices indicate end of strip */ + if(mesh->indices[j] == mesh->indices[j+1] || + mesh->indices[j+1] == mesh->indices[j+2]) + inStrip = 0; + else if(!inStrip){ + /* Entering strip now, + * make sure winding is correct */ + inStrip = 1; + if(newmesh->numIndices % 2) + newmesh->indices[newmesh->numIndices++] = + newmesh->indices[newmesh->numIndices-1]; + } + newmesh->indices[newmesh->numIndices++] = mesh->indices[j]; + } + for(; j < mesh->numIndices; j++) + newmesh->indices[newmesh->numIndices++] = mesh->indices[j]; + newhead->totalIndices += newmesh->numIndices; + + mesh++; + newmesh++; + } + newhead->allocateIndices(); + memcpy(newhead->mesh[0].indices, indices, newhead->totalIndices*2); + delete[] indices; + this->meshHeader = newhead; + delete header; +} + // HAS to be called with an existing mesh void Geometry::removeUnusedMaterials(void) @@ -479,6 +535,9 @@ Geometry::removeUnusedMaterials(void) if(this->meshHeader == nil) return; MeshHeader *mh = this->meshHeader; + for(uint32 i = 0; i < mh->numMeshes; i++) + if(mh->mesh[i].indices == nil) + return; int32 *map = new int32[this->numMaterials]; Material **matlist = new Material*[this->numMaterials]; int32 numMaterials = 0; diff --git a/src/ps2/pds.cpp b/src/ps2/pds.cpp index 346d0e8..449a2f4 100644 --- a/src/ps2/pds.cpp +++ b/src/ps2/pds.cpp @@ -161,7 +161,7 @@ registerPluginPDSPipes(void) pipe->attribs[2] = &attribNormal; vertCount = 0x50; pipe->setTriBufferSizes(3, vertCount); - pipe->vifOffset = pipe->inputStride*vertCount; + pipe->vifOffset = pipe->inputStride*vertCount; // 0xF0 pipe->uninstanceCB = genericUninstanceCB; pipe->preUninstCB = genericPreCB; registerPDSPipe(pipe); @@ -175,7 +175,7 @@ registerPluginPDSPipes(void) pipe->attribs[2] = &attribNormal; pipe->attribs[3] = &attribWeights; vertCount = 0x30; - pipe->setTriBufferSizes(4, vertCount); + pipe->setTriBufferSizes(4, vertCount); // 0xC0 pipe->vifOffset = pipe->inputStride*vertCount; pipe->instanceCB = skinInstanceCB; pipe->uninstanceCB = genericUninstanceCB; diff --git a/src/rwobjects.h b/src/rwobjects.h index 7239da1..3081f5d 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -409,6 +409,7 @@ struct Geometry : PluginBase void allocateData(void); void generateTriangles(int8 *adc = nil); void buildMeshes(void); + void correctTristripWinding(void); void removeUnusedMaterials(void); enum Flags diff --git a/tools/dumprwtree/dumprwtree.vcxproj b/tools/dumprwtree/dumprwtree.vcxproj index 402d34c..71e9dbc 100644 --- a/tools/dumprwtree/dumprwtree.vcxproj +++ b/tools/dumprwtree/dumprwtree.vcxproj @@ -212,7 +212,7 @@ true true true - MultiThreaded + MultiThreadedDLL ..\..\