#include #include #include "dff.h" #define VCNORMSCALE (float) 1/127 float *CalculateNormal(float *vect0, float *vect1, float *vect2) { float *normal; float a[3], b[3]; float len; normal = malloc(3*sizeof(float)); /* Calculate the normal */ a[0] = vect1[0]-vect0[0]; a[1] = vect1[1]-vect0[1]; a[2] = vect1[2]-vect0[2]; b[0] = vect2[0]-vect0[0]; b[1] = vect2[1]-vect0[1]; b[2] = vect2[2]-vect0[2]; normal[0] = a[1]*b[2] - a[2]*b[1]; normal[1] = a[2]*b[0] - a[0]*b[2]; normal[2] = a[0]*b[1] - a[1]*b[0]; /* Make it 1 unit long */ len = sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); if (len == 0) len = 1; normal[0] /= len; normal[1] /= len; normal[2] /= len; return normal; } void MakeNormals(geometry *geo) { int i, j; float *normal; split *cursplit; /* Return if normals are already included */ if ((geo->flags & HASNORMALS) != 0) { geo->normaltype = 0; return; } for (i = 0; i < geo->splitcount; i++) { cursplit = &geo->splt[i]; /* Tristrip */ if (geo->facetype == 1) { geo->normaltype = 1; cursplit->normals = malloc((cursplit->indexcount-2) * sizeof(float *)); for (j = 0; j < cursplit->indexcount-2; j++) { normal = CalculateNormal( geo->vertices[cursplit->indices[j]], geo->vertices[cursplit->indices[j+1+(j % 2)]], geo->vertices[cursplit->indices[j+2-(j % 2)]] ); cursplit->normals[j] = normal; } /* Trilist */ } else { geo->normaltype = 2; cursplit->normals = malloc(cursplit->indexcount/3 * sizeof(float *)); for (j = 0; j < cursplit->indexcount-2; j += 3) { normal = CalculateNormal( geo->vertices[cursplit->indices[j]], geo->vertices[cursplit->indices[j+2]], geo->vertices[cursplit->indices[j+2]] ); cursplit->normals[j/3] = normal; } } } } /* Convert data we read from Native Data PLG to PC format */ void Ps2ToPc(geometry *geo) { int volatile i, j, k; int faceinc; /* Correct index count */ for (i = 0; i < geo->splitcount; i++) geo->splt[i].indexcount = geo->splt[i].vertexcount; /* calculate vertex count and save in structure */ for (j = i = 0; i < geo->splitcount; i++) j += geo->splt[i].indexcount; geo->vertexc = j; geo->vertices = malloc(geo->vertexc*4); geo->uv[0] = malloc(geo->vertexc*4); geo->uv[1] = malloc(geo->vertexc*4); geo->vc = malloc(geo->vertexc*4); geo->normals = malloc(geo->vertexc*4); /* Write Vertex colors into Geometry Struct */ k = 0; for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount; j++) { geo->vc[j+k] = (unsigned char *) malloc(4); geo->vc[j+k][R] = geo->splt[i].vc[j][R]; geo->vc[j+k][G] = geo->splt[i].vc[j][G]; geo->vc[j+k][B] = geo->splt[i].vc[j][B]; geo->vc[j+k][A] = geo->splt[i].vc[j][A]; } k += j; } /* Write UV coordinates into Geometry Struct */ k = 0; for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount; j++) { for (k = 0; k < geo->newuvsets; k++) { geo->uv[k][j+k] = malloc(2*sizeof(float)); geo->uv[k][j+k][U] = geo->splt[i].uv[k][j][U]; geo->uv[k][j+k][V] = geo->splt[i].uv[k][j][V]; } } k += j; } /* The first loop merely counts faces */ k = 0; for (i = 0; i < geo->splitcount; i++) { for (j = 2; j < geo->splt[i].indexcount; j++) { if (IsSameVert(geo->splt[i].vertices[j], geo->splt[i].vertices[j-1]) || IsSameVert(geo->splt[i].vertices[j], geo->splt[i].vertices[j-2]) || IsSameVert(geo->splt[i].vertices[j-1], geo->splt[i].vertices[j-2])) continue; k++; } } geo->facec = k; /* The second loop actually writes them */ k = 0; faceinc = 0; geo->faces = (unsigned short **) malloc(geo->facec*4); for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount-2; j++) { if (IsSameVert(geo->splt[i].vertices[j], geo->splt[i].vertices[j+1]) || IsSameVert(geo->splt[i].vertices[j], geo->splt[i].vertices[j+2]) || IsSameVert(geo->splt[i].vertices[j+1], geo->splt[i].vertices[j+2])) continue; geo->faces[k] = (unsigned short *) malloc(4*sizeof(short)); if (geo->splt[i].winding[j] % 2 != 0 || j % 2 != 0) { geo->faces[k][0] = j+faceinc+1; geo->faces[k][1] = j+faceinc; geo->faces[k][2] = 0; geo->faces[k][3] = j+faceinc+2; } else { geo->faces[k][0] = j+faceinc; geo->faces[k][1] = j+faceinc+1; geo->faces[k][2] = 0; geo->faces[k][3] = j+faceinc+2; } k++; } faceinc += j+2; } /* Write Vertices into Geometry Struct */ k = 0; for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount; j++) { geo->vertices[j+k] = malloc(3*sizeof(float)); geo->vertices[j+k][X] = geo->splt[i].vertices[j][X]; geo->vertices[j+k][Y] = geo->splt[i].vertices[j][Y]; geo->vertices[j+k][Z] = geo->splt[i].vertices[j][Z]; } k += j; } /* Write Normals into Geometry Struct */ k = 0; for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount; j++) { geo->normals[j+k] = malloc(3*4); geo->normals[j+k][X]=geo->splt[i].normals[j][X]; geo->normals[j+k][Y]=geo->splt[i].normals[j][Y]; geo->normals[j+k][Z]=geo->splt[i].normals[j][Z]; } k += j; } /* Write an index list */ faceinc = 0; for (i = 0; i < geo->splitcount; i++) { geo->splt[i].indices = malloc(geo->splt[i].indexcount*sizeof(int)); for (j = 0; j < geo->splt[i].indexcount; j++) { geo->splt[i].indices[j] = j+faceinc; } faceinc += geo->splt[i].indexcount; } /* Free everything */ for (i = 0; i < geo->splitcount; i++) { for (j = 0; j < geo->splt[i].indexcount; j++) { free(geo->splt[i].vertices[j]); free(geo->splt[i].uv[0][j]); if (geo->flags & HASMULUV) free(geo->splt[i].uv[1][j]); free(geo->splt[i].vc[j]); free(geo->splt[i].normals[j]); } free(geo->splt[i].vertices); free(geo->splt[i].uv[0]); if (geo->flags & HASMULUV) free(geo->splt[i].uv[1]); free(geo->splt[i].vc); free(geo->splt[i].normals); free(geo->splt[i].winding); } } void ReadNativeDataSAPS2(geometry *geo, FILE *dff) { int i, j, k; float scale; int unk; int doubleflag; split *cursplit; int blocksize, nextblock; short comp_vert[4]; /* Not correct */ if ((geo->flags & 0x40) != 0) scale = (float) 1 / (float) 1024; else scale = (float) 1 / (float) 128; /* Struct - incorrect size in header */ ReadHeader(dff); /* Skip platform ID, we deal with ps2 anyway */ fseek(dff, 4, SEEK_CUR); for (i = 0; i < geo->splitcount; i++) { cursplit = &geo->splt[i]; cursplit->saindexcount = cursplit->indexcount; fread(&blocksize, 4, 1, dff); nextblock = blocksize + 4 + ftell(dff); fseek(dff, 8, SEEK_CUR); fread(&unk, 4, 1, dff); fseek(dff, unk*16-8, SEEK_CUR); cursplit->savertices=(float **)malloc(cursplit->saindexcount*4); cursplit->sauv[0] = (float **)malloc(cursplit->saindexcount*4); cursplit->sanormals =(float **)malloc(cursplit->saindexcount*4); cursplit->savc = (unsigned char **)malloc(cursplit->saindexcount*4); cursplit->saflags = (int *) malloc(cursplit->saindexcount*4); doubleflag = 0; for (j = 0; j < cursplit->saindexcount; j++) { cursplit->savertices[j] = (float *) malloc(3 * sizeof(float)); fread(&comp_vert, 4, 2, dff); cursplit->savertices[j][0] = (float) comp_vert[0]*scale; cursplit->savertices[j][1] = (float) comp_vert[1]*scale; cursplit->savertices[j][2] = (float) comp_vert[2]*scale; cursplit->saflags[j] = comp_vert[3]; cursplit->saflags[j] &= 0x0000ffff; if (cursplit->saflags[j] == 0x8000) doubleflag++; } cursplit->indexcount = cursplit->saindexcount + doubleflag; cursplit->vertices = (float **) malloc(cursplit->indexcount*4); cursplit->uv[0] = (float **)malloc(cursplit->indexcount*4); cursplit->normals =(float **)malloc(cursplit->indexcount*4); cursplit->vc = (unsigned char **)malloc(cursplit->indexcount*4); for (j = 0, k = 0; j < cursplit->saindexcount; j++, k++) { cursplit->vertices[k] =(float *)malloc(3*sizeof(float)); cursplit->uv[0][k] = (float *) malloc(2*sizeof(float)); cursplit->normals[k] = (float *)malloc(3*sizeof(float)); cursplit->vc[k] = (unsigned char *)malloc(4*1); cursplit->vertices[k][0] = cursplit->savertices[j][0]; cursplit->vertices[k][1] = cursplit->savertices[j][1]; cursplit->vertices[k][2] = cursplit->savertices[j][2]; /* Convert the double face flag to a second face * so the vertex data is in the same format like * PC and VC PS2 format. */ if (cursplit->saflags[j+1] == 0x8000) { k++; cursplit->vertices[k] = (float *)malloc(3*sizeof(float)); cursplit->uv[0][k] = (float *) malloc(2*sizeof(float)); cursplit->normals[k] = (float *)malloc(3*sizeof(float)); cursplit->vc[k] = (unsigned char *)malloc(4*1); cursplit->vertices[k][0] = cursplit->savertices[j][0]; cursplit->vertices[k][1] = cursplit->savertices[j][1]; cursplit->vertices[k][2] = cursplit->savertices[j][2]; } } cursplit->vertexcount = cursplit->indexcount; fseek(dff, nextblock, 0); } } void ReadNativeDataVCPS2(geometry *geo, FILE *dff) { int i, j, k, l; split *cursplit; int blockvertcount, oldvertcount; int isnotactor; int islast; int subsecthdr; int splitsize, nextsplit; char normal; FILE *log; FILE *obj; char filename[32]; if ((log = fopen("/dev/null", "w")) == NULL) { fprintf(stderr, "Couldn't open log file\n"); exit(1); } /* Struct - incorrect size in header */ ReadHeader(dff); fprintf(log, "Native Data Struct: %lX\n", ftell(dff)); /* Skip platform ID, we deal with ps2 anyway */ fseek(dff, 4, SEEK_CUR); for (i = 0; i < geo->splitcount; i++) { cursplit = &geo->splt[i]; fread(&splitsize, 4, 1, dff); nextsplit = splitsize + ftell(dff) + 4; fread(&isnotactor, 4, 1, dff); if (isnotactor) fseek(dff, 16, SEEK_CUR); cursplit->vertices = (float **) malloc(4); cursplit->uv[0] = (float **) malloc(4); cursplit->vc = (unsigned char **) malloc(4); cursplit->normals = (float **) malloc(4); cursplit->winding = (int *) malloc(4); /* Loop through blocks */ cursplit->vertexcount = 0; for (l = 0, islast = 0; !islast; l++) { sprintf(filename, "%d-%d.obj", i, l); if ((obj = fopen(filename, "w")) == NULL) { fprintf(stderr, "Couldn't open file: %s\n", filename); exit(10); } if (!isnotactor) /* is actor */ fseek(dff, 48, SEEK_CUR); /* */ /* Vertex header */ /* */ fprintf(log, "Vertex header at: %lX\n", ftell(dff)); fseek(dff, 12, SEEK_CUR); fread(&subsecthdr, 4, 1, dff); if ((subsecthdr & 0xff00ffff) != 0x68008000) { fprintf(stderr, "Vertex section not found\n"); exit(3); } blockvertcount = (subsecthdr & 0x00ff0000) >> 16; /* read Vertices * Add block vertex count to total split vertex count */ oldvertcount = cursplit->vertexcount; cursplit->vertexcount += blockvertcount; cursplit->vertices = (float **) realloc(cursplit->vertices, cursplit->vertexcount*4); cursplit->winding = (int *) realloc(cursplit->winding, cursplit->vertexcount*4); j = 0; for (k = oldvertcount; k < cursplit->vertexcount; k++) { cursplit->vertices[k] = (float *) malloc(3*4); fread(&cursplit->vertices[k][X], 4, 1, dff); fread(&cursplit->vertices[k][Y], 4, 1, dff); fread(&cursplit->vertices[k][Z], 4, 1, dff); cursplit->winding[k] = j++; fprintf(obj, "v %f %f %f%c%c", cursplit->vertices[k][X], cursplit->vertices[k][Y], cursplit->vertices[k][Z], 0xd, 0xa); } for (k = 0; k < cursplit->vertexcount-2-oldvertcount; k++) fprintf(obj, "f %d %d %d%c%c", k+1, k+2+(k % 2), k+3-(k % 2), 0xd, 0xa); if ((blockvertcount*12 % 16) != 0) fseek(dff, 16 - (blockvertcount*12 % 16), SEEK_CUR); /* skip padding */ /* */ /* UV Coordinate header */ /* */ fprintf(log, "UV header at: %lX\n", ftell(dff)); fseek(dff, 12, SEEK_CUR); fread(&subsecthdr, 4, 1, dff); if ((subsecthdr & 0xff00ffff) != 0x64008001) { fprintf(stderr, "UV section not found\n"); exit(3); } /* read UV Coordinates */ cursplit->uv[0] = (float **) realloc(cursplit->uv[0], cursplit->vertexcount*4); for (k = oldvertcount; k < cursplit->vertexcount; k++) { cursplit->uv[0][k] = (float *) malloc(2*4); fread(&cursplit->uv[0][k][U], 4, 1, dff); fread(&cursplit->uv[0][k][V], 4, 1, dff); } if ((blockvertcount*8 % 16) != 0) fseek(dff, 16 - (blockvertcount*8 % 16), SEEK_CUR); /* skip padding */ /* */ /* Vertexcolor header */ /* */ fprintf(log, "Vertex color header at: %lX\n", ftell(dff)); fseek(dff, 12, SEEK_CUR); fread(&subsecthdr, 4, 1, dff); if ((subsecthdr & 0xff00ffff) != 0x6E00C002) { fprintf(stderr, "Vertexcolor section not found\n"); exit(3); } /* read Vertexcolors */ cursplit->vc = (unsigned char **) realloc(cursplit->vc, cursplit->vertexcount*4); for (k = oldvertcount; k < cursplit->vertexcount; k++) { cursplit->vc[k] = (unsigned char *) malloc(1*4); cursplit->vc[k][R] = getc(dff); cursplit->vc[k][G] = getc(dff); cursplit->vc[k][B] = getc(dff); cursplit->vc[k][A] = getc(dff); } if ((blockvertcount*4 % 16) != 0) fseek(dff, 16 - (blockvertcount*4 % 16), SEEK_CUR); /* skip padding */ /* */ /* Normal header */ /* */ fprintf(log, "Normal header at:%lX\n", ftell(dff)); fseek(dff, 12, SEEK_CUR); fread(&subsecthdr, 4, 1, dff); if ((subsecthdr & 0xff00ffff) != 0x6A008003) { fprintf(stderr, "Normal section not found\n"); exit(3); } /* read Normals */ cursplit->normals = (float **) realloc(cursplit->normals, cursplit->vertexcount*4); for (k = oldvertcount; k < cursplit->vertexcount; k++) { cursplit->normals[k] = (float *) malloc(3*4); normal = getc(dff); cursplit->normals[k][X] = normal * VCNORMSCALE; normal = getc(dff); cursplit->normals[k][Y] = normal * VCNORMSCALE; normal = getc(dff); cursplit->normals[k][Z] = normal * VCNORMSCALE; } if ((blockvertcount*3 % 16) != 0) fseek(dff, 16 - (blockvertcount*3 % 16), SEEK_CUR); /* skip padding */ /* skip end of block, but read if this block was the last */ fseek(dff, 8, SEEK_CUR); fread(&islast, 4, 1, dff); if (islast == 0x11000000) islast = 1; else islast = 0; fseek(dff, 4, SEEK_CUR); fprintf(log, "Split end: %d\n\n", islast); fclose(obj); } /* Jump to next split and skip unknowns */ fseek(dff, nextsplit, 0); } Ps2ToPc(geo); MakeNormals(geo); fclose(log); } void ReadBinMesh(geometry *geo, FILE *dff) { int i, j; split *cursplit; fread(&geo->facetype, 4, 1, dff); fread(&geo->splitcount, 4, 1, dff); fread(&geo->indexcount, 4, 1, dff); /* Loop through splits. * PS2 Version doesn't use indices here. */ geo->splt = (split *) malloc(geo->splitcount*sizeof(split)); for (i = 0; i < geo->splitcount; i++) { cursplit = &geo->splt[i]; fread(&cursplit->indexcount, 4, 1, dff); fread(&cursplit->matindex, 4, 1, dff); if (!geo->isps2) { cursplit->indices = (int *) malloc(cursplit->indexcount*sizeof(int)); for (j = 0; j < cursplit->indexcount; j++) fread(&cursplit->indices[j], 4, 1, dff); cursplit->vertexcount = cursplit->indexcount; } } if (!geo->isps2) MakeNormals(geo); }