support for < 0x30400 dffs

This commit is contained in:
aap 2015-08-16 23:23:41 +02:00
parent 3639ada1c3
commit 3698d97c50
6 changed files with 176 additions and 54 deletions

View File

@ -16,6 +16,7 @@ main(int argc, char *argv[])
// rw::build = 0;
// rw::version = 0x33002;
// rw::version = 0x30200;
gta::registerEnvSpecPlugin();
rw::registerMatFXPlugin();

View File

@ -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];

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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
{