diff --git a/dffwrite.cpp b/dffwrite.cpp index 910c524..4cd0723 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -16,6 +16,7 @@ main(int argc, char *argv[]) // rw::build = 0; // rw::version = 0x33002; +// rw::version = 0x30200; gta::registerEnvSpecPlugin(); rw::registerMatFXPlugin(); diff --git a/src/clump.cpp b/src/clump.cpp index 84ac9bb..11f0396 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -216,17 +216,19 @@ Clump::streamRead(Stream *stream) clump->frameListStreamRead(stream, &frameList, &numFrames); clump->parent = (void*)frameList[0]; - // Geometry list - int32 numGeometries = 0; - assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - numGeometries = stream->readI32(); Geometry **geometryList = 0; - if(numGeometries) - geometryList = new Geometry*[numGeometries]; - for(int32 i = 0; i < numGeometries; i++){ - assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); - geometryList[i] = Geometry::streamRead(stream); + if(version >= 0x30400){ + // Geometry list + int32 numGeometries = 0; + assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + numGeometries = stream->readI32(); + if(numGeometries) + geometryList = new Geometry*[numGeometries]; + for(int32 i = 0; i < numGeometries; i++){ + assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); + geometryList[i] = Geometry::streamRead(stream); + } } // Atomics @@ -274,14 +276,17 @@ Clump::streamWrite(Stream *stream) this->frameListStreamWrite(stream, flist, numFrames); - size = 12+4; - for(int32 i = 0; i < this->numAtomics; i++) - size += 12 + this->atomicList[i]->geometry->streamGetSize(); - writeChunkHeader(stream, ID_GEOMETRYLIST, size); - writeChunkHeader(stream, ID_STRUCT, 4); - stream->writeI32(this->numAtomics); // same as numGeometries - for(int32 i = 0; i < this->numAtomics; i++) - this->atomicList[i]->geometry->streamWrite(stream); + if(rw::version >= 0x30400){ + size = 12+4; + for(int32 i = 0; i < this->numAtomics; i++) + size += 12 + + this->atomicList[i]->geometry->streamGetSize(); + writeChunkHeader(stream, ID_GEOMETRYLIST, size); + writeChunkHeader(stream, ID_STRUCT, 4); + stream->writeI32(this->numAtomics); // same as numGeometries + for(int32 i = 0; i < this->numAtomics; i++) + this->atomicList[i]->geometry->streamWrite(stream); + } for(int32 i = 0; i < this->numAtomics; i++) this->atomicList[i]->streamWriteClump(stream, flist, numFrames); @@ -324,10 +329,13 @@ Clump::streamGetSize(void) size += 12 + 12 + 4 + numFrames*(sizeof(FrameStreamData)+12); sizeCB((Frame*)this->parent, (void*)&size); - // geometry list - size += 12 + 12 + 4; - for(int32 i = 0; i < this->numAtomics; i++) - size += 12 + this->atomicList[i]->geometry->streamGetSize(); + if(rw::version >= 0x30400){ + // geometry list + size += 12 + 12 + 4; + for(int32 i = 0; i < this->numAtomics; i++) + size += 12 + + this->atomicList[i]->geometry->streamGetSize(); + } // atomics for(int32 i = 0; i < this->numAtomics; i++) @@ -449,11 +457,16 @@ Atomic::streamReadClump(Stream *stream, Frame **frameList, Geometry **geometryList) { int32 buf[4]; - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - stream->read(buf, 16); + uint32 version; + assert(findChunk(stream, ID_STRUCT, NULL, &version)); + stream->read(buf, version < 0x30400 ? 12 : 16); Atomic *atomic = new Atomic; atomic->frame = frameList[buf[0]]; - atomic->geometry = geometryList[buf[1]]; + if(version < 0x30400){ + assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); + atomic->geometry = Geometry::streamRead(stream); + }else + atomic->geometry = geometryList[buf[1]]; atomicRights[0] = 0; atomic->streamReadPlugins(stream); @@ -470,17 +483,22 @@ Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames) if(c == NULL) return false; writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, 16); + writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16); buf[0] = findPointer((void*)this->frame, (void**)frameList, numFrames); -// TODO - for(buf[1] = 0; buf[1] < c->numAtomics; buf[1]++) - if(c->atomicList[buf[1]]->geometry == this->geometry) - goto foundgeo; - return false; -foundgeo: + if(version < 0x30400){ + stream->write(buf, sizeof(int[3])); + this->geometry->streamWrite(stream); + }else{ + // TODO + for(buf[1] = 0; buf[1] < c->numAtomics; buf[1]++) + if(c->atomicList[buf[1]]->geometry == this->geometry) + goto foundgeo; + return false; + foundgeo: + stream->write(buf, sizeof(buf)); + } - stream->write(buf, sizeof(buf)); this->streamWritePlugins(stream); return true; } @@ -488,7 +506,12 @@ foundgeo: uint32 Atomic::streamGetSize(void) { - return 12 + 16 + 12 + this->streamGetPluginSize(); + uint32 size = 12 + 12 + 12 + this->streamGetPluginSize(); + if(rw::version < 0x30400) + size += 12 + this->geometry->streamGetSize(); + else + size += 4; + return size; } ObjPipeline *defaultPipelines[NUM_PLATFORMS]; diff --git a/src/geometry.cpp b/src/geometry.cpp index 0121cd1..d4fa0fa 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -24,7 +24,6 @@ Geometry::Geometry(int32 numVerts, int32 numTris, uint32 flags) this->numTriangles = numTris; this->numVertices = numVerts; this->numMorphTargets = 1; -printf("geometry: %X %X\n", this->numTriangles, this->numVertices); this->colors = NULL; for(int32 i = 0; i < this->numTexCoordSets; i++) @@ -317,7 +316,6 @@ Geometry::generateTriangles(void) delete[] this->triangles; this->triangles = new uint16[4*this->numTriangles]; - printf("%d %p\n", this->numTriangles, this->triangles); uint16 *f = this->triangles; m = header->mesh; @@ -395,7 +393,6 @@ struct MatStreamData uint8 color[4]; int32 unused; int32 textured; - float32 surfaceProps[3]; }; static uint32 materialRights[2]; @@ -403,18 +400,26 @@ static uint32 materialRights[2]; Material* Material::streamRead(Stream *stream) { - uint32 length; + uint32 length, version; MatStreamData buf; - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, NULL, &version)); stream->read(&buf, sizeof(buf)); Material *mat = new Material; mat->color[0] = buf.color[0]; mat->color[1] = buf.color[1]; mat->color[2] = buf.color[2]; mat->color[3] = buf.color[3]; - mat->surfaceProps[0] = buf.surfaceProps[0]; - mat->surfaceProps[1] = buf.surfaceProps[1]; - mat->surfaceProps[2] = buf.surfaceProps[2]; + if(version < 0x30400){ + mat->surfaceProps[0] = 1.0f; + mat->surfaceProps[1] = 1.0f; + mat->surfaceProps[2] = 1.0f; + }else{ + float32 surfaceProps[3]; + stream->read(surfaceProps, sizeof(surfaceProps)); + mat->surfaceProps[0] = surfaceProps[0]; + mat->surfaceProps[1] = surfaceProps[1]; + mat->surfaceProps[2] = surfaceProps[2]; + } if(buf.textured){ assert(findChunk(stream, ID_TEXTURE, &length, NULL)); @@ -434,20 +439,26 @@ Material::streamWrite(Stream *stream) MatStreamData buf; writeChunkHeader(stream, ID_MATERIAL, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, sizeof(MatStreamData)); + writeChunkHeader(stream, ID_STRUCT, sizeof(MatStreamData) + + (rw::version >= 0x30400 ? 12 : 0)); buf.color[0] = this->color[0]; buf.color[1] = this->color[1]; buf.color[2] = this->color[2]; buf.color[3] = this->color[3]; - buf.surfaceProps[0] = this->surfaceProps[0]; - buf.surfaceProps[1] = this->surfaceProps[1]; - buf.surfaceProps[2] = this->surfaceProps[2]; buf.flags = 0; buf.unused = 0; buf.textured = this->texture != NULL; stream->write(&buf, sizeof(buf)); + if(rw::version >= 0x30400){ + float32 surfaceProps[3]; + surfaceProps[0] = this->surfaceProps[0]; + surfaceProps[1] = this->surfaceProps[1]; + surfaceProps[2] = this->surfaceProps[2]; + stream->write(surfaceProps, sizeof(surfaceProps)); + } + if(this->texture) this->texture->streamWrite(stream); @@ -460,6 +471,8 @@ Material::streamGetSize(void) { uint32 size = 0; size += 12 + sizeof(MatStreamData); + if(rw::version >= 0x30400) + size += 12; if(this->texture) size += 12 + this->texture->streamGetSize(); size += 12 + this->streamGetPluginSize(); diff --git a/src/plugins.cpp b/src/plugins.cpp index f4e0372..500929f 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -159,7 +159,6 @@ readMesh(Stream *stream, int32 len, void *object, int32, int32) geo->meshHeader->flags = buf[0]; geo->meshHeader->numMeshes = buf[1]; geo->meshHeader->totalIndices = buf[2]; -printf("total: %X\n", geo->meshHeader->totalIndices); geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; Mesh *mesh = geo->meshHeader->mesh; bool hasData = len > 12+geo->meshHeader->numMeshes*8; diff --git a/src/ps2.cpp b/src/ps2.cpp index f529ddd..f659c77 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -800,6 +800,86 @@ skinInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data, int32 n) // TODO: look at PC SA rccam.dff bloodrb.dff, Xbox csbigbear.dff +static void +rotateface(int f[]) +{ + int tmp; + while(f[0] > f[1] || f[0] > f[2]){ + tmp = f[0]; + f[0] = f[1]; + f[1] = f[2]; + f[2] = tmp; + } + +/* + if(f[0] > f[1]){ + tmp = f[0]; + f[0] = f[1]; + f[1] = tmp; + } + if(f[0] > f[2]){ + tmp = f[0]; + f[0] = f[2]; + f[2] = tmp; + } + if(f[1] > f[2]){ + tmp = f[1]; + f[1] = f[2]; + f[2] = tmp; + } +*/ +} + +static int +validFace(Geometry *g, uint16 *f, int j, int m) +{ + int f1[3], f2[3]; + f1[0] = f[j+0 + (j%2)]; + f1[1] = f[j+1 - (j%2)]; + f1[2] = f[j+2]; +//printf("-> %d %d %d\n", f1[0], f1[1], f1[2]); + rotateface(f1); + uint16 *fs = g->triangles; + for(int i = 0; i < g->numTriangles; i++, fs += 4){ + if(fs[2] != m) + continue; + f2[0] = fs[1]; + f2[1] = fs[0]; + f2[2] = fs[3]; +//printf("<- %d %d %d\n", f2[0], f2[1], f2[2]); + rotateface(f2); + if(f1[0] == f2[0] && + f1[1] == f2[1] && + f1[2] == f2[2]) + return 1; + } + return 0; +} + +static int +isdegenerate(uint16 *f) +{ + return f[0] == f[1] || + f[0] == f[2] || + f[1] == f[2]; +} + +static int +debugadc(Geometry *g, MeshHeader *mh, ADCData *adc) +{ + int n = 0; + for(int i = 0; i < mh->numMeshes; i++){ + uint16 *idx = mh->mesh[i].indices; + for(int j = 0; j < mh->mesh[i].numIndices-2; j++){ + if(!validFace(g, idx, j, i) && !isdegenerate(idx+j)){ + n++; +// printf("> %d %d %d %d\n", i, idx[j+0], idx[j+1], idx[j+2]); + } + } + } + return n; +} + static void* createADC(void *object, int32 offset, int32) { @@ -847,18 +927,21 @@ readADC(Stream *stream, int32, void *object, int32 offset, int32) adc->adcBits = new int8[size]; stream->read(adc->adcBits, size); +/* Geometry *geometry = (Geometry*)object; int ones = 0, zeroes = 0; for(int i = 0; i < adc->numBits; i++) - if(adc->adcBits[i] == 0) - zeroes++; - else if(adc->adcBits[i] == 1) + if(adc->adcBits[i]) ones++; else - fprintf(stderr, "what the fuck man\n"); - printf("%X %X %X\n", adc->numBits, zeroes, ones); + zeroes++; MeshHeader *meshHeader = geometry->meshHeader; - printf("%X\n", meshHeader->totalIndices); + int n = debugadc(geometry, meshHeader, adc); + printf("%X %X | %X %X %X\n", + meshHeader->totalIndices, + meshHeader->totalIndices + n, + adc->numBits, zeroes, ones); +*/ } static void diff --git a/src/rwps2.h b/src/rwps2.h index c10af7a..59866b5 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -86,7 +86,10 @@ int32 getSizeNativeSkin(void *object, int32 offset); // Each element in adcBits corresponds to an index in Mesh->indices, // this assumes the Mesh indices are ADC formatted. -// For some reason ADCData->numBits != Mesh->numIndices +// ADCData->numBits != Mesh->numIndices. ADCData->numBits is probably +// equal to Mesh->numIndices before the Mesh gets ADC formatted. +// +// Can't convert between ADC-formatted and non-ADC-formatted yet :( struct ADCData {