added correction of face winding in tristrips

This commit is contained in:
aap 2017-03-09 11:45:26 +01:00
parent 4d5bbb8ccd
commit c2780d56e9
6 changed files with 68 additions and 8 deletions

View File

@ -269,7 +269,7 @@
<PreprocessorDefinitions>_USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories> <AdditionalIncludeDirectories>
</AdditionalIncludeDirectories> </AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -433,7 +433,7 @@ Raster*
readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels) readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels)
{ {
uint8 palette[256*4]; uint8 palette[256*4];
uint8 *data; uint8 *data = nil;
Image *img = Image::create(width, height, 32); Image *img = Image::create(width, height, 32);
img->allocate(); img->allocate();
@ -443,7 +443,7 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format
else if(format & Raster::PAL8) else if(format & Raster::PAL8)
stream->read(palette, 4*256); stream->read(palette, 4*256);
// Only read one mipmap // Only read one mipmap
for(int32 i = 0; i < numLevels; i++){ for(int32 i = 0; i < numLevels; i++){
uint32 size = stream->readU32(); uint32 size = stream->readU32();
if(i == 0){ if(i == 0){

View File

@ -380,7 +380,7 @@ Geometry::generateTriangles(int8 *adc)
m++; m++;
continue; continue;
} }
if(header->flags == 1){ // tristrip if(header->flags == MeshHeader::TRISTRIP){
for(uint32 j = 0; j < m->numIndices-2; j++){ for(uint32 j = 0; j < m->numIndices-2; j++){
if(!(adc && adcbits[j+2]) && if(!(adc && adcbits[j+2]) &&
!isDegenerate(&m->indices[j])) !isDegenerate(&m->indices[j]))
@ -407,7 +407,7 @@ Geometry::generateTriangles(int8 *adc)
int32 matid = findPointer((void*)m->material, int32 matid = findPointer((void*)m->material,
(void**)this->materialList, (void**)this->materialList,
this->numMaterials); this->numMaterials);
if(header->flags == 1) // tristrip if(header->flags == MeshHeader::TRISTRIP)
for(uint32 j = 0; j < m->numIndices-2; j++){ for(uint32 j = 0; j < m->numIndices-2; j++){
if(adc && adcbits[j+2] || if(adc && adcbits[j+2] ||
isDegenerate(&m->indices[j])) 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 // HAS to be called with an existing mesh
void void
Geometry::removeUnusedMaterials(void) Geometry::removeUnusedMaterials(void)
@ -479,6 +535,9 @@ Geometry::removeUnusedMaterials(void)
if(this->meshHeader == nil) if(this->meshHeader == nil)
return; return;
MeshHeader *mh = this->meshHeader; 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]; int32 *map = new int32[this->numMaterials];
Material **matlist = new Material*[this->numMaterials]; Material **matlist = new Material*[this->numMaterials];
int32 numMaterials = 0; int32 numMaterials = 0;

View File

@ -161,7 +161,7 @@ registerPluginPDSPipes(void)
pipe->attribs[2] = &attribNormal; pipe->attribs[2] = &attribNormal;
vertCount = 0x50; vertCount = 0x50;
pipe->setTriBufferSizes(3, vertCount); pipe->setTriBufferSizes(3, vertCount);
pipe->vifOffset = pipe->inputStride*vertCount; pipe->vifOffset = pipe->inputStride*vertCount; // 0xF0
pipe->uninstanceCB = genericUninstanceCB; pipe->uninstanceCB = genericUninstanceCB;
pipe->preUninstCB = genericPreCB; pipe->preUninstCB = genericPreCB;
registerPDSPipe(pipe); registerPDSPipe(pipe);
@ -175,7 +175,7 @@ registerPluginPDSPipes(void)
pipe->attribs[2] = &attribNormal; pipe->attribs[2] = &attribNormal;
pipe->attribs[3] = &attribWeights; pipe->attribs[3] = &attribWeights;
vertCount = 0x30; vertCount = 0x30;
pipe->setTriBufferSizes(4, vertCount); pipe->setTriBufferSizes(4, vertCount); // 0xC0
pipe->vifOffset = pipe->inputStride*vertCount; pipe->vifOffset = pipe->inputStride*vertCount;
pipe->instanceCB = skinInstanceCB; pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = genericUninstanceCB; pipe->uninstanceCB = genericUninstanceCB;

View File

@ -409,6 +409,7 @@ struct Geometry : PluginBase<Geometry>
void allocateData(void); void allocateData(void);
void generateTriangles(int8 *adc = nil); void generateTriangles(int8 *adc = nil);
void buildMeshes(void); void buildMeshes(void);
void correctTristripWinding(void);
void removeUnusedMaterials(void); void removeUnusedMaterials(void);
enum Flags enum Flags

View File

@ -212,7 +212,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<AdditionalIncludeDirectories>..\..\</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>