#include #include #include #include "../rw.h" #include "dff.h" int rwvers; void writedword(int dword, FILE *file) { fwrite(&dword, 4, 1, file); } void writefloat(float dword, FILE *file) { fwrite(&dword, 4, 1, file); } void writeword(short word, FILE *file) { fwrite(&word, 2, 1, file); } void UpdateClumpSize(FILE *dff) { int oldpos; int size; oldpos = ftell(dff); fseek(dff, 0, SEEK_END); size = ftell(dff); fseek(dff, 4, 0); writedword(size-12, dff); fseek(dff, oldpos, 0); } int WriteFrameList(clump *clp, FILE *dff) { int i; int sectsize, headeraddr; int oldpos; sectsize = 0; headeraddr = ftell(dff); WriteHeader(FRAMELIST, 0, rwvers, dff); WriteHeader(STRUCT, 0, rwvers, dff); sectsize += 12; writedword(clp->frmcount, dff); sectsize += 4; for (i = 0; i < clp->frmcount; i++) { writefloat(clp->frm[i].rotmatrix[0][0], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[0][1], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[0][2], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[1][0], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[1][1], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[1][2], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[2][0], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[2][1], dff); sectsize += 4; writefloat(clp->frm[i].rotmatrix[2][2], dff); sectsize += 4; writefloat(clp->frm[i].posmatrix[0][3], dff); sectsize += 4; writefloat(clp->frm[i].posmatrix[1][3], dff); sectsize += 4; writefloat(clp->frm[i].posmatrix[2][3], dff); sectsize += 4; writedword(clp->frm[i].parent, dff); sectsize += 4; writedword(clp->frm[i].unknown, dff); sectsize += 4; } oldpos = ftell(dff); fseek(dff, headeraddr+12, 0); WriteHeader(STRUCT, sectsize-12, rwvers, dff); fseek(dff, oldpos, 0); for (i = 0; i < clp->frmcount; i++) { int len; if (clp->frm[i].name == 0) { WriteHeader(EXTENSION, 16, rwvers, dff); sectsize += 12; WriteHeader(FRAME, 4, rwvers, dff); sectsize += 12; writedword(0x656e6f6e, dff); continue; } len = strlen(clp->frm[i].name); WriteHeader(EXTENSION, len+12, rwvers, dff); sectsize += 12; WriteHeader(FRAME, len, rwvers, dff); sectsize += 12; fwrite(clp->frm[i].name, 1, len, dff); sectsize += len; } fseek(dff, headeraddr, 0); WriteHeader(FRAMELIST, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize+12; } int WriteTexture(material *mat, int i, FILE *dff) { int j; int sectsize, headeraddr; int len; texture *tex = &mat->tex[i]; sectsize = 0; headeraddr = ftell(dff); WriteHeader(TEXTURE, 12, rwvers, dff); WriteHeader(STRUCT, 4, rwvers, dff); sectsize += 12; writeword(tex->filterflags, dff); writeword(tex->unknown, dff); sectsize += 4; len = strlen(tex->tex); len += 4 - (len % 4); WriteHeader(STRING, len, rwvers, dff); sectsize += 12; for (j = 0; j < strlen(tex->tex); j++) putc(tex->tex[j], dff); for (; j < len; j++) putc(0, dff); sectsize += len; len = strlen(tex->alpha); len += 4 - (len % 4); WriteHeader(STRING, len, rwvers, dff); sectsize += 12; for (j = 0; j < strlen(tex->alpha); j++) putc(tex->alpha[j], dff); for (; j < len; j++) putc(0, dff); sectsize += len; WriteHeader(EXTENSION, 0, rwvers, dff); sectsize += 12; fseek(dff, headeraddr, 0); WriteHeader(TEXTURE, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } int WriteMaterial(geometry *geo, int i, FILE *dff) { int sectsize, headeraddr; material *mat = &geo->mat[i]; sectsize = 0; headeraddr = ftell(dff); WriteHeader(MATERIAL, 12, rwvers, dff); WriteHeader(STRUCT, 0, rwvers, dff); sectsize += 12; writedword(mat->unknown0, dff); sectsize += 4; putc(mat->color[0], dff); putc(mat->color[1], dff); putc(mat->color[2], dff); putc(mat->color[3], dff); sectsize += 4; writedword(mat->unknown1, dff); sectsize += 4; writedword(mat->texcount, dff); sectsize += 4; writefloat(mat->unknown2, dff); sectsize += 4; writefloat(mat->unknown3, dff); sectsize += 4; writefloat(mat->unknown4, dff); sectsize += 4; fseek(dff, headeraddr+12, 0); WriteHeader(STRUCT, sectsize-12, rwvers, dff); fseek(dff, 0, SEEK_END); for (i = 0; i < mat->texcount; i++) { sectsize += WriteTexture(mat, i, dff); } WriteHeader(EXTENSION, 0, rwvers, dff); sectsize += 12; fseek(dff, headeraddr, 0); WriteHeader(MATERIAL, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } int WriteMaterialList(geometry *geo, FILE *dff) { int i; int sectsize, headeraddr; sectsize = 0; headeraddr = ftell(dff); WriteHeader(MATERIALLIST, 0, rwvers, dff); WriteHeader(STRUCT, 4+geo->matcount*4, rwvers, dff); sectsize += 12; writedword(geo->matcount, dff); sectsize += 4; for (i = 0; i < geo->matcount; i++) { writedword(-1, dff); sectsize += 4; } for (i = 0; i < geo->matcount; i++) { sectsize += WriteMaterial(geo, i, dff); } fseek(dff, headeraddr, 0); WriteHeader(MATERIALLIST, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } int WriteGeometry(clump *clp, int l, FILE *dff) { int i, j, k; int sectsize, headeraddr; int extsize, extaddr; int facecountaddr, oldaddr; int faceinc; int vertexcount; short flags; geometry *geo; geo = &clp->geo[l]; sectsize = 0; faceinc = 0; vertexcount = 0; headeraddr = ftell(dff); WriteHeader(GEOMETRY, 12, rwvers, dff); WriteHeader(STRUCT, 0, rwvers, dff); sectsize += 12; flags = geo->flags; writeword(flags , dff); sectsize += 2; putc(geo->uvsets, dff); sectsize++; putc(0, dff); sectsize++; facecountaddr = ftell(dff); writedword(1, dff); sectsize += 4; for (j = 0; j < geo->splitcount; j++) vertexcount += geo->splt[j].vertexcount; writedword(vertexcount, dff); sectsize += 4; writedword(geo->framec, dff); sectsize += 4; if (rwvers == 0x0C02FFFF || rwvers == 0x310) { writefloat(geo->ambient, dff); sectsize += 4; writefloat(geo->diffuse, dff); sectsize += 4; writefloat(geo->specular, dff); sectsize += 4; } /* Vertex colors */ if ((flags & HASVCOLORS) != 0) for (j = 0; j < geo->splitcount; j++) { for (i = 0; i < geo->splt[j].vertexcount; i++) { putc(geo->splt[j].vc[i][R], dff); sectsize ++; putc(geo->splt[j].vc[i][G], dff); sectsize ++; putc(geo->splt[j].vc[i][B], dff); sectsize ++; putc(geo->splt[j].vc[i][A], dff); sectsize ++; } } /* UV coordinates */ if ((flags & HASUV) != 0) for (j = 0; j < geo->splitcount; j++) { for (i = 0; i < geo->splt[j].vertexcount; i++) { writefloat(geo->splt[j].uv[0][i][U], dff); sectsize += 4; writefloat(geo->splt[j].uv[0][i][V], dff); sectsize += 4; } } /* Faces */ k = 0; for (j = 0; j < geo->splitcount; j++) { for (i = 2; i < geo->splt[j].vertexcount; i++) { if (IsSameVert(geo->splt[j].vertices[i], geo->splt[j].vertices[i-1]) || IsSameVert(geo->splt[j].vertices[i], geo->splt[j].vertices[i-2]) || IsSameVert(geo->splt[j].vertices[i-1], geo->splt[j].vertices[i-2])) continue; if (i % 2 == 0) { writeword(i-1+faceinc, dff); sectsize += 2; writeword(i-2+faceinc, dff); sectsize += 2; writeword(0, dff); sectsize += 2; writeword(i+faceinc, dff); sectsize += 2; } else { writeword(i-2+faceinc, dff); sectsize += 2; writeword(i-1+faceinc, dff); sectsize += 2; writeword(0, dff); sectsize += 2; writeword(i+faceinc, dff); sectsize += 2; } k++; } faceinc += geo->splt[j].vertexcount; } oldaddr = ftell(dff); fseek(dff, facecountaddr, 0); writedword(k, dff); fseek(dff, oldaddr, 0); /* Bounding sphere */ writefloat(geo->bs[0], dff); sectsize += 4; writefloat(geo->bs[1], dff); sectsize += 4; writefloat(geo->bs[2], dff); sectsize += 4; writefloat(geo->bs[3], dff); sectsize += 4; writedword(geo->bspos, dff); sectsize += 4; writedword(geo->bsnor, dff); sectsize += 4; /* Vertices */ for (j = 0; j < geo->splitcount; j++) for (i = 0; i < geo->splt[j].vertexcount; i++) { writefloat(geo->splt[j].vertices[i][X], dff); sectsize += 4; writefloat(geo->splt[j].vertices[i][Y], dff); sectsize += 4; writefloat(geo->splt[j].vertices[i][Z], dff); sectsize += 4; } /* Normals */ if ((flags & HASNORMALS) != 0) { for (j = 0; j < geo->splitcount; j++) for (i = 0; i < geo->splt[j].vertexcount; i++) { writefloat(geo->splt[j].normals[i][X], dff); sectsize += 4; writefloat(geo->splt[j].normals[i][Y], dff); sectsize += 4; writefloat(geo->splt[j].normals[i][Z], dff); sectsize += 4; } } fseek(dff, headeraddr+12, 0); WriteHeader(STRUCT, sectsize-12, rwvers, dff); fseek(dff, 0, SEEK_END); sectsize += WriteMaterialList(geo, dff); extaddr = ftell(dff); extsize = 0; WriteHeader(EXTENSION, 12, rwvers, dff); sectsize += 12; WriteHeader(BINMESH, 0, rwvers, dff); extsize += 12; writedword(geo->facetype, dff); extsize += 4; writedword(geo->splitcount, dff); extsize += 4; /* Use previously calculated vertex count */ writedword(vertexcount, dff); extsize += 4; faceinc = 0; for (j = 0; j < geo->splitcount; j++) { writedword(geo->splt[j].vertexcount, dff); extsize += 4; writedword(geo->splt[j].matindex, dff); extsize += 4; for (i = 0; i < geo->splt[j].vertexcount; i++) { writedword(i+faceinc, dff); extsize += 4; } faceinc += geo->splt[j].vertexcount; } fseek(dff, extaddr, 0); WriteHeader(EXTENSION, extsize, rwvers, dff); WriteHeader(BINMESH, extsize-12, rwvers, dff); sectsize += extsize; fseek(dff, headeraddr, 0); WriteHeader(GEOMETRY, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } int WriteGeometryList(clump *clp, FILE *dff) { int i; int sectsize, headeraddr; sectsize = 0; headeraddr = ftell(dff); WriteHeader(GEOMETRYLIST, 0, rwvers, dff); WriteHeader(STRUCT, 4, rwvers, dff); sectsize += 12; writedword(clp->geocount, dff); sectsize += 4; for (i = 0; i < clp->geocount; i++) { sectsize += WriteGeometry(clp, i, dff); } fseek(dff, headeraddr, 0); WriteHeader(GEOMETRYLIST, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } int WriteAtomic(clump *clp, int i, FILE *dff) { int sectsize, headeraddr; sectsize = 0; headeraddr = ftell(dff); WriteHeader(ATOMIC, 0, rwvers, dff); WriteHeader(STRUCT, 16, rwvers, dff); sectsize += 12; writedword(clp->atm[i].frameindex, dff); sectsize += 4; writedword(clp->atm[i].geometryindex, dff); sectsize += 4; writedword(clp->atm[i].unknown0, dff); sectsize += 4; writedword(clp->atm[i].unknown1, dff); sectsize += 4; WriteHeader(EXTENSION, 0, rwvers, dff); sectsize += 12; fseek(dff, headeraddr, 0); WriteHeader(ATOMIC, sectsize, rwvers, dff); fseek(dff, 0, SEEK_END); return sectsize + 12; } void WriteDff(clump *clp, FILE *dff) { int i; int sectsize; rwvers = 0x0C02FFFF; sectsize = 0; WriteHeader(CLUMP, 0, rwvers, dff); WriteHeader(STRUCT, 12, rwvers, dff); sectsize += 12; writedword(clp->objcount, dff); sectsize += 4; writedword(0, dff); sectsize += 4; writedword(0, dff); sectsize += 4; sectsize += WriteFrameList(clp, dff); sectsize += WriteGeometryList(clp, dff); for (i = 0; i < clp->objcount; i++) sectsize += WriteAtomic(clp, i, dff); WriteHeader(EXTENSION, 0, rwvers, dff); sectsize += 12; fseek(dff, 4, 0); writedword(sectsize, dff); }