diff --git a/librw.sln b/librw.sln index d2e140e..521ed17 100644 --- a/librw.sln +++ b/librw.sln @@ -65,7 +65,6 @@ Global {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.ActiveCfg = Release|Win32 {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.Build.0 = Release|Win32 {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.ActiveCfg = Release|x64 - {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.Build.0 = Release|x64 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|x64.ActiveCfg = Debug - null|x64 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -74,8 +73,8 @@ Global {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.ActiveCfg = Release|Win32 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.Build.0 = Release|Win32 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.ActiveCfg = Release|x64 - {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.Build.0 = Release|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 + {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.Build.0 = Debug - null|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.ActiveCfg = Debug - null|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64 @@ -83,7 +82,6 @@ Global {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64 - {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.Build.0 = Release|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -93,7 +91,6 @@ Global {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.ActiveCfg = Release|Win32 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.Build.0 = Release|Win32 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.ActiveCfg = Release|x64 - {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.Build.0 = Release|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|x64.ActiveCfg = Debug - null|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -102,7 +99,6 @@ Global {403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.ActiveCfg = Release|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.Build.0 = Release|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.ActiveCfg = Release|x64 - {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.Build.0 = Release|x64 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.Build.0 = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|x64.ActiveCfg = Debug - null|Win32 diff --git a/librw.vcxproj b/librw.vcxproj index baf04fc..6444b73 100644 --- a/librw.vcxproj +++ b/librw.vcxproj @@ -193,7 +193,6 @@ - diff --git a/rw.h b/rw.h index 8f1c24e..e633a40 100644 --- a/rw.h +++ b/rw.h @@ -8,4 +8,3 @@ #include "src/rwd3d8.h" #include "src/rwd3d9.h" #include "src/rwogl.h" -#include "src/mdl.h" diff --git a/src/clump.cpp b/src/clump.cpp index d1a5c91..8697963 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -31,6 +31,7 @@ Frame::Frame(void) this->matrix[5] = 1.0f; this->matrix[10] = 1.0f; this->matrix[15] = 1.0f; + this->matflag = 0; this->dirty = true; constructPlugins(); } diff --git a/src/geometry.cpp b/src/geometry.cpp index 9ba6b3d..4348069 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -41,6 +41,10 @@ Geometry::Geometry(int32 numVerts, int32 numTris, uint32 flags) } this->morphTargets = new MorphTarget[1]; MorphTarget *m = this->morphTargets; + m->boundingSphere[0] = 0.0f; + m->boundingSphere[1] = 0.0f; + m->boundingSphere[2] = 0.0f; + m->boundingSphere[3] = 0.0f; m->vertices = NULL; m->normals = NULL; if(!(this->geoflags & NATIVE) && this->numVertices){ diff --git a/src/gtaplg.cpp b/src/gtaplg.cpp index 1e98f1b..c9a8612 100644 --- a/src/gtaplg.cpp +++ b/src/gtaplg.cpp @@ -12,7 +12,6 @@ #include "rwps2.h" #include "rwd3d.h" #include "rwxbox.h" -#include "mdl.h" #include "gtaplg.h" using namespace std; @@ -82,8 +81,6 @@ attachPlugins(void) gta::register2dEffectPlugin(); gta::registerPipelinePlugin(); - registerRslPlugin(); - rw::Atomic::init(); } @@ -156,6 +153,12 @@ registerNodeNamePlugin(void) getSizeNodeName); } +char* +getNodeName(Frame *f) +{ + return PLUGINOFFSET(char, f, nodeNameOffset); +} + // // Geometry // diff --git a/src/gtaplg.h b/src/gtaplg.h index b31a51d..3a81ad8 100644 --- a/src/gtaplg.h +++ b/src/gtaplg.h @@ -25,6 +25,7 @@ void attachPlugins(void); extern int32 nodeNameOffset; void registerNodeNamePlugin(void); +char *getNodeName(Frame *f); // Breakable model diff --git a/src/image.cpp b/src/image.cpp index fb4f2d0..2ee80a7 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -130,18 +130,19 @@ Texture::read(const char *name, const char *mask) tex = new Texture; strncpy(tex->name, name, 32); strncpy(tex->mask, mask, 32); - char *n = (char*)malloc(strlen(name) + 5); - strcpy(n, name); - strcat(n, ".tga"); - Image *img = readTGA(n); - free(n); - if(img){ - raster = Raster::createFromImage(img); - delete img; - }else +// char *n = (char*)malloc(strlen(name) + 5); +// strcpy(n, name); +// strcat(n, ".tga"); +// Image *img = readTGA(n); +// free(n); +// if(img){ +// //raster = Raster::createFromImage(img); +// raster = new Raster(0, 0, 0, 0x80); +// delete img; +// }else raster = new Raster(0, 0, 0, 0x80); tex->raster = raster; - if(currentTexDictionary && img) + if(currentTexDictionary /*&& img*/) currentTexDictionary->add(tex); return tex; } diff --git a/src/mdl.cpp b/src/mdl.cpp deleted file mode 100644 index e2f4886..0000000 --- a/src/mdl.cpp +++ /dev/null @@ -1,602 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "rwbase.h" -#include "rwplugin.h" -#include "rwpipeline.h" -#include "rwobjects.h" -#include "rwps2.h" -#include "rwogl.h" -#include "rwxbox.h" -#include "rwd3d8.h" -#include "rwd3d9.h" -#include "mdl.h" - -using namespace std; -using namespace rw; - -enum { - ID_RSL = 0xf00d0000 -}; -int32 rslPluginOffset; - -struct RslMesh -{ - float32 bound[4]; // ? - float32 uvScale[2]; - uint32 unknown; - uint32 dmaOffset; - uint16 numTriangles; - int16 matID; - float32 pos[3]; // ? -}; - -struct RslGeometry -{ - float32 bound[4]; - uint32 size; - int32 flags; - int32 unknown[4]; - float32 scale[3]; - float32 pos[3]; - - uint32 numMeshes; - RslMesh *meshes; - uint32 dataSize; - uint8 *data; -}; - -float32 -halfFloat(uint16 half) -{ - uint32 f = (uint32)(half & 0x7fff) << 13; - uint32 sgn = (uint32)(half & 0x8000) << 16; - f += 0x38000000; - if((half & 0x7c00) == 0) f = 0; - f |= sgn; - return *(float32*)&f; -} - -static uint32 -unpackSize(uint32 unpack) -{ - if((unpack&0x6F000000) == 0x6F000000) - return 2; - static uint32 size[] = { 32, 16, 8, 16 }; - return ((unpack>>26 & 3)+1)*size[unpack>>24 & 3]/8; -} - -int -analyzeDMA(uint8 *p) -{ - uint32 *w = (uint32*)p; - uint32 *end; - end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10); - w += 4; - int flags = 0; - while(w < end){ - if((w[0] & 0x60000000) == 0x60000000){ -// printf("UNPACK %x %x\n", w[0], unpackSize(w[0])); - printf("UNPACK %x %x %x\n", w[0] & 0x7F004000, w[0], unpackSize(w[0])); - uint32 type = w[0] & 0x7F004000; - if(w[0] != 0x6c018000){ - if(type == 0x79000000) - flags |= 0x1; - if(type == 0x76004000) - flags |= 0x10; - if(type == 0x6a000000) - flags |= 0x100; - if(type == 0x6f000000) - flags |= 0x1000; - if(type == 0x6c000000) - flags |= 0x10000; - } - int32 n = (w[0] >> 16) & 0xFF; - p = (uint8*)(w+1); - p += (n*unpackSize(w[0])+3)&~3; - w = (uint32*)p; - continue; - } - switch(w[0] & 0x7F000000){ - case 0x20000000: // STMASK - printf("STMASK %x\n", w[1]); - w++; - break; - case 0x30000000: - printf("STROW %x %x %x %x\n", w[1], w[2], w[3], w[4]); - w+=4; - break; - case 0x31000000: - printf("STCOL %x %x %x %x\n", w[1], w[2], w[3], w[4]); - w+=4; - break; - case 0x14000000: - printf("MSCAL %x\n", w[0]&0xFFFF); - return flags; - break; - case 0: - break; - default: - printf("vif: %x\n", w[0]); - break; - } - w++; - } - return flags; -} - -uint32* -skipUnpack(uint32 *p) -{ - int32 n = (p[0] >> 16) & 0xFF; - return p + (n*unpackSize(p[0])+3 >> 2) + 1; -} - -void -convertRslMesh(Geometry *g, RslGeometry *rg, Mesh *m, RslMesh *rm) -{ - ps2::SkinVertex v; - uint32 mask = 0x1001; // tex coords, vertices - if(g->geoflags & Geometry::NORMALS) - mask |= 0x10; - if(g->geoflags & Geometry::PRELIT) - mask |= 0x100; - float32 *verts = &g->morphTargets[0].vertices[g->numVertices*3]; - float32 *norms = &g->morphTargets[0].normals[g->numVertices*3]; - uint8 *cols = &g->colors[g->numVertices*4]; - float32 *texCoords = &g->texCoords[0][g->numVertices*2]; - uint8 *indices = NULL; - float32 *weights = NULL; - Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); - if(skin){ - indices = &skin->indices[g->numVertices*4]; - weights = &skin->weights[g->numVertices*4]; - mask |= 0x10000; - } - - int16 *vuVerts = NULL; - int8 *vuNorms = NULL; - uint8 *vuTex = NULL; - uint16 *vuCols = NULL; - uint32 *vuSkin = NULL; - - uint8 *p = rg->data + rm->dmaOffset; - uint32 *w = (uint32*)p; - uint32 *end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10); - w += 4; - int flags = 0; - int32 nvert; - bool first = 1; - while(w < end){ - /* Get data pointers */ - - // GIFtag probably - assert(w[0] == 0x6C018000); // UNPACK - nvert = w[4] & 0x7FFF; - if(!first) nvert -=2; - w += 5; - - // positions - assert(w[0] == 0x20000000); // STMASK - w += 2; - assert(w[0] == 0x30000000); // STROW - w += 5; - assert((w[0] & 0xFF004000) == 0x79000000); - vuVerts = (int16*)(w+1); - if(!first) vuVerts += 2*3; - w = skipUnpack(w); - - // tex coords - assert(w[0] == 0x20000000); // STMASK - w += 2; - assert(w[0] == 0x30000000); // STROW - w += 5; - assert((w[0] & 0xFF004000) == 0x76004000); - vuTex = (uint8*)(w+1); - if(!first) vuTex += 2*2; - w = skipUnpack(w); - - if(g->geoflags & Geometry::NORMALS){ - assert((w[0] & 0xFF004000) == 0x6A000000); - vuNorms = (int8*)(w+1); - if(!first) vuNorms += 2*3; - w = skipUnpack(w); - } - - if(g->geoflags & Geometry::PRELIT){ - assert((w[0] & 0xFF004000) == 0x6F000000); - vuCols = (uint16*)(w+1); - if(!first) vuCols += 2; - w = skipUnpack(w); - } - - if(skin){ - assert((w[0] & 0xFF004000) == 0x6C000000); - vuSkin = w+1; - if(!first) vuSkin += 2*4; - w = skipUnpack(w); - } - - assert(w[0] == 0x14000006); // MSCAL - w++; - while(w[0] == 0) w++; - - /* Insert Data */ - for(int32 i = 0; i < nvert; i++){ - v.p[0] = vuVerts[0]/32768.0f*rg->scale[0] + rg->pos[0]; - v.p[1] = vuVerts[1]/32768.0f*rg->scale[1] + rg->pos[1]; - v.p[2] = vuVerts[2]/32768.0f*rg->scale[2] + rg->pos[2]; - v.t[0] = vuTex[0]/128.0f*rm->uvScale[0]; - v.t[1] = vuTex[1]/128.0f*rm->uvScale[1]; - if(mask & 0x10){ - v.n[0] = vuNorms[0]/127.0f; - v.n[1] = vuNorms[1]/127.0f; - v.n[2] = vuNorms[2]/127.0f; - } - if(mask & 0x100){ - v.c[0] = (vuCols[0] & 0x1f) * 255 / 0x1F; - v.c[1] = (vuCols[0]>>5 & 0x1f) * 255 / 0x1F; - v.c[2] = (vuCols[0]>>10 & 0x1f) * 255 / 0x1F; - v.c[3] = vuCols[0]&0x8000 ? 0xFF : 0; - } - if(mask & 0x10000){ - for(int j = 0; j < 4; j++){ - ((uint32*)v.w)[j] = vuSkin[j] & ~0x3FF; - v.i[j] = vuSkin[j] >> 2; - //if(v.i[j]) v.i[j]--; - if(v.w[j] == 0.0f) v.i[j] = 0; - } - } - - int32 idx = ps2::findVertexSkin(g, NULL, mask, &v); - if(idx < 0) - idx = g->numVertices++; - /* Insert mesh joining indices when we get the index of the first vertex - * in the first VU chunk of a non-first RslMesh. */ - if(i == 0 && first && rm != &rg->meshes[0] && (rm-1)->matID == rm->matID){ - m->indices[m->numIndices] = m->indices[m->numIndices-1]; - m->numIndices++; - m->indices[m->numIndices++] = idx; - if((rm-1)->numTriangles % 2) - m->indices[m->numIndices++] = idx; - } - m->indices[m->numIndices++] = idx; - ps2::insertVertexSkin(g, idx, mask, &v); - - vuVerts += 3; - vuTex += 2; - vuNorms += 3; - vuCols++; - vuSkin += 4; - } - first = 0; - } -} - -void -convertRslGeometry(Geometry *g) -{ - RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset); - assert(rg != NULL); - - g->meshHeader = new MeshHeader; - g->meshHeader->flags = 1; - g->meshHeader->numMeshes = g->numMaterials; - g->meshHeader->mesh = new Mesh[g->meshHeader->numMeshes]; - g->meshHeader->totalIndices = 0; - Mesh *meshes = g->meshHeader->mesh; - for(uint32 i = 0; i < g->meshHeader->numMeshes; i++) - meshes[i].numIndices = 0; - RslMesh *rm = rg->meshes; - int32 lastId = -1; - for(uint32 i = 0; i < rg->numMeshes; i++, rm++){ - Mesh *m = &meshes[rm->matID]; - g->numVertices += rm->numTriangles+2; - m->numIndices += rm->numTriangles+2; - // Extra indices since we're merging tristrip - // meshes with the same material. - // Be careful with face winding. - if(lastId == rm->matID) - m->numIndices += (rm-1)->numTriangles % 2 ? 3 : 2; - lastId = rm->matID; - } - for(uint32 i = 0; i < g->meshHeader->numMeshes; i++){ - g->meshHeader->mesh[i].material = g->materialList[i]; - g->meshHeader->totalIndices += meshes[i].numIndices; - } - g->geoflags = Geometry::TRISTRIP | - Geometry::POSITIONS | /* 0x01 ? */ - Geometry::TEXTURED | /* 0x04 ? */ - Geometry::LIGHT; - if(g->hasColoredMaterial()) - g->geoflags |= Geometry::MODULATE; - if(rg->flags & 0x2) - g->geoflags |= Geometry::NORMALS; - if(rg->flags & 0x8) - g->geoflags |= Geometry::PRELIT; - g->numTexCoordSets = 1; - - g->allocateData(); - g->meshHeader->allocateIndices(); - - Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); - if(rg->flags & 0x10) - assert(skin); - if(skin){ - uint8 *data = skin->data; - float *invMats = skin->inverseMatrices; - skin->init(skin->numBones, skin->numBones, g->numVertices); - memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; - } - - for(uint32 i = 0; i < g->meshHeader->numMeshes; i++) - meshes[i].numIndices = 0; - g->numVertices = 0; - rm = rg->meshes; - for(uint32 i = 0; i < rg->numMeshes; i++, rm++) - convertRslMesh(g, rg, &meshes[rm->matID], rm); - - if(skin){ - skin->findNumWeights(g->numVertices); - skin->findUsedBones(g->numVertices); - } - g->calculateBoundingSphere(); - g->generateTriangles(); -} - -Geometry* -geometryStreamReadRsl(Stream *stream) -{ - RslGeometry *rg = new RslGeometry; - stream->read(rg, 0x40); - rg->numMeshes = rg->size >> 20; - rg->size &= 0xFFFFF; - rg->meshes = new RslMesh[rg->numMeshes]; - rg->dataSize = rg->size - 0x40; - stream->read(rg->meshes, rg->numMeshes*sizeof(RslMesh)); - rg->dataSize -= rg->numMeshes*sizeof(RslMesh); - rg->data = new uint8[rg->dataSize]; - stream->read(rg->data, rg->dataSize); - - Geometry *g = new Geometry(0, 0, 0); - *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset) = rg; - - assert(findChunk(stream, ID_MATLIST, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - g->numMaterials = stream->readI32(); - g->materialList = new Material*[g->numMaterials]; - stream->seek(g->numMaterials*4); // unused (-1) - for(int32 i = 0; i < g->numMaterials; i++){ - assert(findChunk(stream, ID_MATERIAL, NULL, NULL)); - g->materialList[i] = Material::streamRead(stream); - // unimplemented by Rsl - g->materialList[i]->surfaceProps.ambient = 1.0f; - g->materialList[i]->surfaceProps.specular = 1.0f; - g->materialList[i]->surfaceProps.diffuse = 1.0f; - } - - g->streamReadPlugins(stream); - - return g; -} - -bool -geometryStreamWriteRsl(Stream *stream, Geometry *g) -{ - uint32 buf[3] = { ID_GEOMETRY, geometryStreamGetSizeRsl(g), 0xf00d }; - stream->write(&buf, 12); - - RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset); - assert(rg != NULL); - rg->size |= rg->numMeshes << 20; - stream->write(rg, 0x40); - rg->numMeshes = rg->size >> 20; - rg->size &= 0xFFFFF; - stream->write(rg->meshes, rg->numMeshes*sizeof(RslMesh)); - stream->write(rg->data, rg->dataSize); - - uint32 size = 12 + 4; - for(int32 i = 0; i < g->numMaterials; i++) - size += 4 + 12 + g->materialList[i]->streamGetSize(); - writeChunkHeader(stream, ID_MATLIST, size); - writeChunkHeader(stream, ID_STRUCT, 4 + g->numMaterials*4); - stream->writeI32(g->numMaterials); - for(int32 i = 0; i < g->numMaterials; i++) - stream->writeI32(-1); - for(int32 i = 0; i < g->numMaterials; i++) - g->materialList[i]->streamWrite(stream); - - g->streamWritePlugins(stream); - return true; -} - -uint32 -geometryStreamGetSizeRsl(Geometry *g) -{ - RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset); - assert(rg != NULL); - - uint32 size = rg->size; - size += 12 + 12 + 4; - for(int32 i = 0; i < g->numMaterials; i++) - size += 4 + 12 + g->materialList[i]->streamGetSize(); - size += 12 + g->streamGetPluginSize(); - return size; -} - -static uint32 atomicRights[2]; - -Atomic* -atomicStreamReadRsl(Stream *stream, Frame **frameList) -{ - int32 buf[4]; - uint32 version; - assert(findChunk(stream, ID_STRUCT, NULL, &version)); - stream->read(buf, 16); - Atomic *atomic = new Atomic; - atomic->frame = frameList[buf[0]]; - assert(findChunk(stream, ID_GEOMETRY, NULL, &version)); - assert(version == 0x00f00d00); - atomic->geometry = geometryStreamReadRsl(stream); - - atomicRights[0] = 0; - atomic->streamReadPlugins(stream); - if(atomicRights[0]) - atomic->assertRights(atomicRights[0], atomicRights[1]); - return atomic; -} - -bool -atomicStreamWriteRsl(Stream *stream, Atomic *a, Frame **frameList, int32 numFrames) -{ - int32 buf[4] = { 0, 0, 5, 0 }; - Clump *c = a->clump; - if(c == NULL) - return false; - writeChunkHeader(stream, ID_ATOMIC, atomicStreamGetSizeRsl(a)); - buf[0] = findPointer((void*)a->frame, (void**)frameList, numFrames); - writeChunkHeader(stream, ID_STRUCT, 16); - stream->write(buf, sizeof(buf)); - - geometryStreamWriteRsl(stream, a->geometry); - - a->streamWritePlugins(stream); - return true; -} - -uint32 -atomicStreamGetSizeRsl(Atomic *a) -{ - uint32 size = 12 + 12 + 12 + a->streamGetPluginSize(); - size += 16 + geometryStreamGetSizeRsl(a->geometry); - return size; -} - -Clump* -clumpStreamReadRsl(Stream *stream) -{ - uint32 length, version; - int32 buf[3]; - Clump *clump; - assert(findChunk(stream, ID_STRUCT, &length, &version)); - clump = new Clump; - stream->read(buf, length); - clump->numAtomics = buf[0]; - clump->numLights = 0; - clump->numCameras = 0; - - // Frame list - Frame **frameList; - int32 numFrames; - clump->frameListStreamRead(stream, &frameList, &numFrames); - clump->parent = (void*)frameList[0]; - - Geometry **geometryList = 0; - - // Atomics - if(clump->numAtomics) - clump->atomicList = new Atomic*[clump->numAtomics]; - for(int32 i = 0; i < clump->numAtomics; i++){ - assert(findChunk(stream, ID_ATOMIC, NULL, NULL)); - clump->atomicList[i] = atomicStreamReadRsl(stream, frameList); - clump->atomicList[i]->clump = clump; - } - - delete[] frameList; - - clump->streamReadPlugins(stream); - return clump; -} - -bool -clumpStreamWriteRsl(Stream *stream, Clump *c) -{ - int size = clumpStreamGetSizeRsl(c); - writeChunkHeader(stream, ID_CLUMP, size); - int buf[3] = { c->numAtomics, 0, 0 }; - writeChunkHeader(stream, ID_STRUCT, 4); - stream->write(buf, 4); - - int32 numFrames = ((Frame*)c->parent)->count(); - Frame **flist = new Frame*[numFrames]; - makeFrameList((Frame*)c->parent, flist); - - c->frameListStreamWrite(stream, flist, numFrames); - - for(int32 i = 0; i < c->numAtomics; i++) - atomicStreamWriteRsl(stream, c->atomicList[i], flist, numFrames); - - delete[] flist; - - c->streamWritePlugins(stream); - return true; -} - -static Frame* -sizeCB(Frame *f, void *size) -{ - *(int32*)size += f->streamGetPluginSize(); - f->forAllChildren(sizeCB, size); - return f; -} - -uint32 -clumpStreamGetSizeRsl(Clump *c) -{ - uint32 size = 0; - size += 12; // Struct - size += 4; // numAtomics - - // frame list - // TODO: make this into a function - int32 numFrames = ((Frame*)c->parent)->count(); - size += 12 + 12 + 4 + numFrames*(56+12); - sizeCB((Frame*)c->parent, (void*)&size); - - // atomics - for(int32 i = 0; i < c->numAtomics; i++) - size += 12 + atomicStreamGetSizeRsl(c->atomicList[i]); - - size += 12 + c->streamGetPluginSize(); - return size; -} - - -static void* -createRslGeo(void *object, int32 offset, int32) -{ - *PLUGINOFFSET(RslGeometry*, object, offset) = NULL; - return object; -} - -static void* -destroyRslGeo(void *object, int32 offset, int32) -{ - RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, object, offset); - delete rg->data; - delete rg->meshes; - delete rg; - *PLUGINOFFSET(RslGeometry*, object, offset) = NULL; - return object; -} - -static void* -copyRslGeo(void *dst, void *src, int32 offset, int32) -{ - // TODO - return dst; -} - -void -registerRslPlugin(void) -{ - rslPluginOffset = Geometry::registerPlugin(sizeof(RslGeometry*), ID_RSL, - createRslGeo, - destroyRslGeo, - copyRslGeo); -} diff --git a/src/mdl.h b/src/mdl.h deleted file mode 100644 index 7125685..0000000 --- a/src/mdl.h +++ /dev/null @@ -1,13 +0,0 @@ -rw::Clump *clumpStreamReadRsl(rw::Stream *stream); -bool clumpStreamWriteRsl(rw::Stream *stream, rw::Clump *c); -rw::uint32 clumpStreamGetSizeRsl(rw::Clump *c); - -rw::Atomic *atomicStreamReadRsl(rw::Stream *stream, rw::Frame **frameList); -rw::uint32 atomicStreamGetSizeRsl(rw::Atomic *a); - -rw::Geometry *geometryStreamReadRsl(rw::Stream *stream); -rw::uint32 geometryStreamGetSizeRsl(rw::Geometry *g); - -void convertRslGeometry(rw::Geometry *g); - -void registerRslPlugin(void); \ No newline at end of file diff --git a/src/plugins.cpp b/src/plugins.cpp index 4e88962..4f9eeea 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -499,7 +499,7 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32) skin->init(header[0], header[1], geometry->numVertices); skin->numWeights = header[2]; - if(!oldFormat && !skinGlobals.forceSkipUsedBones) + if(!oldFormat) stream->read(skin->usedBones, skin->numUsedBones); if(skin->indices) stream->read(skin->indices, geometry->numVertices*4); @@ -826,6 +826,22 @@ MatFX::getEffectIndex(uint32 type) return -1; } +void +MatFX::setEnvTexture(Texture *t) +{ + int32 i = this->getEffectIndex(ENVMAP); + if(i >= 0) + this->fx[i].env.tex = t; +} + +void +MatFX::setEnvCoefficient(float32 coef) +{ + int32 i = this->getEffectIndex(ENVMAP); + if(i >= 0) + this->fx[i].env.coefficient = coef; +} + static void* createMaterialMatFX(void *object, int32 offset, int32) { @@ -889,13 +905,7 @@ readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) *PLUGINOFFSET(MatFX*, object, offset) = matfx; matfx->setEffects(stream->readU32()); - if(matfx->type == MatFX::BUMPMAP && matFXGlobals.hack){ - stream->seek(12); - return; - } - - int32 n = matFXGlobals.hack ? 1 : 2; - for(int i = 0; i < n; i++){ + for(int i = 0; i < 2; i++){ uint32 type = stream->readU32(); switch(type){ case MatFX::BUMPMAP: @@ -920,10 +930,7 @@ readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) case MatFX::ENVMAP: coefficient = stream->readF32(); - if(matFXGlobals.hack) - fbAlpha = 0; - else - fbAlpha = stream->readI32(); + fbAlpha = stream->readI32(); tex = NULL; if(stream->readI32()){ assert(findChunk(stream, ID_TEXTURE, diff --git a/src/rwobjects.h b/src/rwobjects.h index 4de0506..9f119df 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -8,6 +8,7 @@ struct Object void *parent; }; +// TODO: missing: list of attached objects struct Frame : PluginBase, Object { typedef Frame *(*Callback)(Frame *f, void *data); @@ -270,6 +271,8 @@ struct MatFX void setEffects(uint32 flags); int32 getEffectIndex(uint32 type); + void setEnvTexture(Texture *t); + void setEnvCoefficient(float32 coef); }; struct MatFXGlobals @@ -277,7 +280,6 @@ struct MatFXGlobals int32 atomicOffset; int32 materialOffset; ObjPipeline *pipelines[NUM_PLATFORMS]; - bool32 hack; }; extern MatFXGlobals matFXGlobals; void registerMatFXPlugin(void); @@ -387,7 +389,6 @@ struct SkinGlobals { int32 offset; ObjPipeline *pipelines[NUM_PLATFORMS]; - bool32 forceSkipUsedBones; }; extern SkinGlobals skinGlobals; void registerSkinPlugin(void); diff --git a/tools/d3d9/d3dInit.cpp b/tools/d3d9/d3dInit.cpp index 7376296..93620ab 100644 --- a/tools/d3d9/d3dInit.cpp +++ b/tools/d3d9/d3dInit.cpp @@ -74,8 +74,8 @@ setMaterial(Material *mat) { D3DMATERIAL9 mat9; D3DCOLORVALUE black = { 0, 0, 0, 0 }; - float ambmult = mat->surfaceProps[0]/255.0f; - float diffmult = mat->surfaceProps[2]/255.0f; + float ambmult = mat->surfaceProps.ambient/255.0f; + float diffmult = mat->surfaceProps.diffuse/255.0f; mat9.Ambient.r = mat->color[0]*ambmult; mat9.Ambient.g = mat->color[1]*ambmult; mat9.Ambient.b = mat->color[2]*ambmult; diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index 08c6dcc..469bb54 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -25,37 +25,6 @@ struct { char *argv0; -Frame* -findHierCB(Frame *f, void *p) -{ - HAnimData *hanim = PLUGINOFFSET(HAnimData, f, hAnimOffset); - if(hanim->hierarchy){ - *(HAnimHierarchy**)p = hanim->hierarchy; - return NULL; - } - f->forAllChildren(findHierCB, p); - return f; -} - -HAnimHierarchy* -getHierarchy(Clump *c) -{ - HAnimHierarchy *hier = NULL; - findHierCB((Frame*)c->parent, &hier); - return hier; -} - -void -fixLcsHier(HAnimHierarchy *hier) -{ - hier->maxInterpKeyFrameSize = findAnimInterpolatorInfo(1)->keyFrameSize; - for(int32 i = 0; i < hier->numNodes; i++){ - int32 id = hier->nodeInfo[i].id; - if(id == 255) hier->nodeInfo[i].id = -1; - else if(id > 0x80) hier->nodeInfo[i].id |= 0x1300; - } -} - void usage(void) { @@ -64,7 +33,6 @@ usage(void) fprintf(stderr, "\t-i instance\n"); fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n"); fprintf(stderr, "\t-o output platform. ps2, xbox, mobile, d3d8, d3d9\n"); - fprintf(stderr, "\t-s expect iOS LCS dff as input\n"); exit(1); } @@ -84,7 +52,6 @@ main(int argc, char *argv[]) int uninstance = 0; int instance = 0; - int lcs = 0; int outplatform = rw::PLATFORM_D3D8; char *s; @@ -110,9 +77,6 @@ main(int argc, char *argv[]) outplatform = PLATFORM_D3D8; found: break; - case 's': - lcs++; - break; default: usage(); }ARGEND; @@ -122,9 +86,6 @@ main(int argc, char *argv[]) return 1; } - matFXGlobals.hack = lcs; - skinGlobals.forceSkipUsedBones = lcs; - if(argc < 1) usage(); @@ -145,10 +106,7 @@ main(int argc, char *argv[]) } assert(header.type == ID_CLUMP); debugFile = argv[0]; - if(lcs) - c = clumpStreamReadRsl(&in); - else - c = Clump::streamRead(&in); + c = Clump::streamRead(&in); assert(c != NULL); in.close(); @@ -173,18 +131,6 @@ main(int argc, char *argv[]) switchPipes(c, rw::platform); } - if(lcs){ - HAnimHierarchy *hier = getHierarchy(c); - if(hier) - fixLcsHier(hier); - for(int32 i = 0; i < c->numAtomics; i++){ - Skin *skin = *PLUGINOFFSET(Skin*, c->atomicList[i]->geometry, skinGlobals.offset); - convertRslGeometry(c->atomicList[i]->geometry); - if(skin) - c->atomicList[i]->pipeline = skinGlobals.pipelines[rw::platform]; - } - } - if(uninstance) for(int32 i = 0; i < c->numAtomics; i++){ Atomic *a = c->atomicList[i]; diff --git a/tools/rsltest/rsl.cpp b/tools/rsltest/rsl.cpp index 42f60b2..91027d0 100644 --- a/tools/rsltest/rsl.cpp +++ b/tools/rsltest/rsl.cpp @@ -28,15 +28,15 @@ RslMatrixSetIdentity(RslMatrix *matrix) void rslObjectHasFrameSetFrame(RslObjectHasFrame *object, RslFrame *f) { - if(object->object.parent){ - object->lFrame.prev->next = object->lFrame.next; - object->lFrame.next->prev = object->lFrame.prev; - } + if(object->object.parent){ + object->lFrame.prev->next = object->lFrame.next; + object->lFrame.next->prev = object->lFrame.prev; + } object->object.parent = f; - if(f){ - object->lFrame.prev = &f->objectList.link; - object->lFrame.next = f->objectList.link.next; - f->objectList.link.next->prev = &object->lFrame; + if(f){ + object->lFrame.prev = &f->objectList.link; + object->lFrame.next = f->objectList.link.next; + f->objectList.link.next->prev = &object->lFrame; f->objectList.link.next = &object->lFrame; f->root->object.privateFlags |= 1; @@ -49,8 +49,8 @@ RslFrameCreate(void) { RslFrame *f = new RslFrame; rslObjectInitialize(&f->object, 0, 0); - f->objectList.link.prev = &f->objectList.link; - f->objectList.link.next = &f->objectList.link; + f->objectList.link.prev = &f->objectList.link; + f->objectList.link.next = &f->objectList.link; RslMatrixSetIdentity(&f->modelling); RslMatrixSetIdentity(&f->ltm); f->child = NULL; @@ -71,15 +71,24 @@ RslFrameAddChild(RslFrame *parent, RslFrame *child) { RslFrame *p = (RslFrame*)child->object.parent; assert(p == NULL); - child->next = parent->child; - parent->child = child; - child->object.parent = parent; - child->root = parent->root; - child->root->object.privateFlags |= 1; + child->next = parent->child; + parent->child = child; + child->object.parent = parent; + child->root = parent->root; + child->root->object.privateFlags |= 1; child->object.privateFlags |= 2; return parent; } +int32 +RslFrameCount(RslFrame *f) +{ + int32 n = 1; + for(RslFrame *c = f->child; c; c = c->next) + n += RslFrameCount(c); + return n; +} + RslFrame* RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data) { @@ -99,7 +108,7 @@ struct StreamFrame }; void -rwFrameListStreamRead(Stream *stream, rslFrameList *framelist) +rslFrameListStreamRead(Stream *stream, rslFrameList *framelist) { uint32 length; StreamFrame strfrm; @@ -140,6 +149,25 @@ rwFrameListStreamRead(Stream *stream, rslFrameList *framelist) } } +static RslFrame** +rslFrameListFill(RslFrame *f, RslFrame **flist) +{ + *flist++ = f; + if(f->next) + flist = rslFrameListFill(f->next, flist); + if(f->child) + flist = rslFrameListFill(f->child, flist); + return flist; +} + +void +rslFrameListInitialize(rslFrameList *frameList, RslFrame *root) +{ + frameList->numFrames = RslFrameCount(root); + frameList->frames = new RslFrame*[frameList->numFrames]; + rslFrameListFill(root, frameList->frames); +} + RslHAnimHierarchy* RslHAnimHierarchyCreate(int32 numNodes, uint32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize) { @@ -147,10 +175,10 @@ RslHAnimHierarchyCreate(int32 numNodes, uint32 *nodeFlags, int32 *nodeIDs, int32 memset(hier, 0, sizeof(RslHAnimHierarchy)); if(maxKeySize < 0x24) maxKeySize = 0x24; - hier->flags = flags; - hier->numNodes = numNodes; - hier->parentFrame = 0; - hier->maxKeyFrameSize = maxKeySize; + hier->flags = flags; + hier->numNodes = numNodes; + hier->parentFrame = 0; + hier->maxKeyFrameSize = maxKeySize; hier->currentKeyFrameSize = 0x24; int32 msz = numNodes*0x40 + 0x3f; @@ -320,7 +348,7 @@ RslClumpStreamRead(Stream *stream) clump = RslClumpCreate(); assert(findChunk(stream, ID_FRAMELIST, NULL, NULL)); - rwFrameListStreamRead(stream, &framelist); + rslFrameListStreamRead(stream, &framelist); clump->object.parent = framelist.frames[0]; for(int32 i = 0; i < numAtomics; i++){ @@ -336,16 +364,17 @@ RslClumpStreamRead(Stream *stream) stream->seek(header.length); length -= 12 + header.length; } + delete[] framelist.frames; return clump; } RslClump* RslClumpAddAtomic(RslClump *clump, RslAtomic *a) -{ - a->inClumpLink.prev = &clump->atomicList.link; - a->inClumpLink.next = clump->atomicList.link.next; - clump->atomicList.link.next->prev = &a->inClumpLink; - clump->atomicList.link.next = &a->inClumpLink; +{ + a->inClumpLink.prev = &clump->atomicList.link; + a->inClumpLink.next = clump->atomicList.link.next; + clump->atomicList.link.next->prev = &a->inClumpLink; + clump->atomicList.link.next = &a->inClumpLink; a->clump = clump; return clump; } @@ -365,6 +394,18 @@ RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData) return clump; } +int32 +RslClumpGetNumAtomics(RslClump *clump) +{ + int32 n = 0; + RslLLLink *link; + for(link = rslLLLinkGetNext(&clump->atomicList.link); + link != &clump->atomicList.link; + link = link->next) + n++; + return n; +} + RslGeometry* RslGeometryCreatePS2(uint32 sz) { @@ -385,13 +426,13 @@ RslGeometryForAllMaterials(RslGeometry *geometry, RslMaterialCallBack fpCallBack return geometry; } -struct RslMaterialChunkInfo -{ - int32 flags; - RslRGBA color; // used - int32 unused; - bool32 textured; // used - SurfaceProperties surfaceProps; +struct RslMaterialChunkInfo +{ + int32 flags; + RslRGBA color; // used + int32 unused; + bool32 textured; // used + SurfaceProperties surfaceProps; }; RslMaterial* @@ -479,11 +520,11 @@ void rpMaterialListAppendMaterial(RslMaterialList *matlist, RslMaterial *mat) { if(matlist->space <= matlist->numMaterials){ - matlist->space += 16; RslMaterial **mats = matlist->materials; - matlist->materials = new RslMaterial*[matlist->space]; - if(matlist->space-16) - memcpy(matlist->materials, mats, (matlist->space+16)*sizeof(RslMaterial*)); + matlist->materials = new RslMaterial*[matlist->space+16]; + if(matlist->space) + memcpy(matlist->materials, mats, matlist->space*sizeof(RslMaterial*)); + matlist->space += 16; delete[] mats; } matlist->materials[matlist->numMaterials++] = mat; diff --git a/tools/rsltest/rsl.h b/tools/rsltest/rsl.h index 10a8292..d821c9d 100644 --- a/tools/rsltest/rsl.h +++ b/tools/rsltest/rsl.h @@ -42,12 +42,12 @@ typedef RslAtomic *(*RslAtomicCallBack)(RslAtomic *atomic, void *data); typedef RslMaterial *(*RslMaterialCallBack)(RslMaterial *material, void *data); typedef RslTexture *(*RslTextureCallBack)(RslTexture *texture, void *pData); -struct RslRGBA -{ - uint8 red; - uint8 green; - uint8 blue; - uint8 alpha; +struct RslRGBA +{ + uint8 red; + uint8 green; + uint8 blue; + uint8 alpha; }; struct RslV3d @@ -57,13 +57,13 @@ struct RslV3d struct RslMatrix { - RslV3d right; - uint32 flags; - RslV3d up; - uint32 pad1; - RslV3d at; - uint32 pad2; - RslV3d pos; + RslV3d right; + uint32 flags; + RslV3d up; + uint32 pad1; + RslV3d at; + uint32 pad2; + RslV3d pos; uint32 pad3; }; @@ -104,16 +104,17 @@ struct RslObject { void *parent; }; -#define rslObjectInitialize(o, t, s) \ -{ \ - ((RslObject*)(o))->type = (uint8)(t); \ - ((RslObject*)(o))->subType = (uint8)(s); \ - ((RslObject*)(o))->flags = 0; \ - ((RslObject*)(o))->privateFlags = 0; \ - ((RslObject*)(o))->parent = NULL; \ +#define rslObjectInitialize(o, t, s) \ +{ \ + ((RslObject*)(o))->type = (uint8)(t); \ + ((RslObject*)(o))->subType = (uint8)(s); \ + ((RslObject*)(o))->flags = 0; \ + ((RslObject*)(o))->privateFlags = 0; \ + ((RslObject*)(o))->parent = NULL; \ } -#define rslObjectGetParent(object) (((const RslObject *)(object))->parent) +#define rslObjectGetParent(object) (((RslObject*)(object))->parent) +#define rslObjectSetParent(c,p) (((RslObject*)(c))->parent) = (void*)(p) struct RslObjectHasFrame { RslObject object; @@ -197,6 +198,7 @@ struct RslFrame { RslFrame *RslFrameCreate(void); RslFrame *RslFrameAddChild(RslFrame *parent, RslFrame *child); +int32 RslFrameCount(RslFrame *f); RslFrame *RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data); struct rslFrameList @@ -205,16 +207,25 @@ struct rslFrameList int32 numFrames; }; +void rslFrameListStreamRead(Stream *stream, rslFrameList *framelist); +void rslFrameListInitialize(rslFrameList *frameList, RslFrame *root); + struct RslClump { RslObject object; RslLinkList atomicList; }; #define RslClumpGetFrame(_clump) \ - ((RslFrame *) rslObjectGetParent(_clump)) + ((RslFrame*)rslObjectGetParent(_clump)) +#define RslClumpSetFrame(_clump, _frame) \ + (rslObjectSetParent(_clump, _frame), \ + (_clump)) + +RslClump *RslClumpCreate(void); RslClump *RslClumpStreamRead(Stream *stream); RslClump *RslClumpAddAtomic(RslClump *clump, RslAtomic *a); +int32 RslClumpGetNumAtomics(RslClump *clump); RslClump *RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData); struct RslAtomic { @@ -234,7 +245,7 @@ struct RslAtomic { }; #define RslAtomicGetFrame(_atomic) \ - ((RslFrame *) rslObjectGetParent(_atomic)) + ((RslFrame*)rslObjectGetParent(_atomic)) RslAtomic *RslAtomicCreate(void); RslAtomic *RslAtomicSetFrame(RslAtomic *atomic, RslFrame *frame); diff --git a/tools/rsltest/rsltest.cpp b/tools/rsltest/rsltest.cpp index 31d4b73..8098891 100644 --- a/tools/rsltest/rsltest.cpp +++ b/tools/rsltest/rsltest.cpp @@ -40,7 +40,8 @@ RslFrame *dumpFrameCB(RslFrame *frame, void *data) RslMaterial *dumpMaterialCB(RslMaterial *material, void*) { - printf(" mat: %s %x\n", material->texname, material->refCount); + printf(" mat: %d %d %d %d %s %x\n", material->color.red, material->color.green, material->color.blue, material->color.alpha, + material->texname, material->refCount); if(material->matfx){ RslMatFX *fx = material->matfx; printf(" matfx: ", fx->effectType); @@ -59,6 +60,411 @@ RslAtomic *dumpAtomicCB(RslAtomic *atomic, void*) return atomic; } +int32 +mapID(int32 id) +{ + if(id == 255) return -1; + if(id > 0x80) id |= 0x1300; + return id; +} + +Frame* +convertFrame(RslFrame *f) +{ + Frame *rwf = new Frame; + rwf->matrix[0] = f->modelling.right.x; + rwf->matrix[1] = f->modelling.right.y; + rwf->matrix[2] = f->modelling.right.z; + rwf->matrix[4] = f->modelling.up.x; + rwf->matrix[5] = f->modelling.up.y; + rwf->matrix[6] = f->modelling.up.z; + rwf->matrix[8] = f->modelling.at.x; + rwf->matrix[9] = f->modelling.at.y; + rwf->matrix[10] = f->modelling.at.z; + rwf->matrix[12] = f->modelling.pos.x; + rwf->matrix[13] = f->modelling.pos.y; + rwf->matrix[14] = f->modelling.pos.z; + + if(f->name) + strncpy(gta::getNodeName(rwf), f->name, 24); + + HAnimData *hanim = PLUGINOFFSET(HAnimData, rwf, hAnimOffset); + hanim->id = f->nodeId; + if(f->hier){ + HAnimHierarchy *hier; + hanim->hierarchy = hier = new HAnimHierarchy; + hier->numNodes = f->hier->numNodes; + hier->flags = f->hier->flags; + hier->maxInterpKeyFrameSize = f->hier->maxKeyFrameSize; + hier->parentFrame = rwf; + hier->parentHierarchy = hier; + hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; + for(int32 i = 0; i < hier->numNodes; i++){ + hier->nodeInfo[i].id = mapID((uint8)f->hier->pNodeInfo[i].id); + hier->nodeInfo[i].index = f->hier->pNodeInfo[i].index; + hier->nodeInfo[i].flags = f->hier->pNodeInfo[i].flags; + hier->nodeInfo[i].frame = NULL; + } + } + return rwf; +} + +Texture* +convertTexture(RslTexture *t) +{ + Texture *tex = Texture::read(t->name, t->mask); + //tex->refCount++; // ?? + if(tex->refCount == 1) + tex->filterAddressing = (Texture::WRAP << 12) | (Texture::WRAP << 8) | Texture::LINEAR; + return tex; +} + +Material* +convertMaterial(RslMaterial *m) +{ + Material *rwm; + rwm = new Material; + + rwm->color[0] = m->color.red; + rwm->color[1] = m->color.green; + rwm->color[2] = m->color.blue; + rwm->color[3] = m->color.alpha; + if(m->texture) + rwm->texture = convertTexture(m->texture); + + if(m->matfx){ + MatFX *matfx = new MatFX; + matfx->setEffects(m->matfx->effectType); + matfx->setEnvCoefficient(m->matfx->env.intensity); + if(m->matfx->env.texture) + matfx->setEnvTexture(convertTexture(m->matfx->env.texture)); + *PLUGINOFFSET(MatFX*, rwm, matFXGlobals.materialOffset) = matfx; + } + return rwm; +} + +static uint32 +unpackSize(uint32 unpack) +{ + if((unpack&0x6F000000) == 0x6F000000) + return 2; + static uint32 size[] = { 32, 16, 8, 16 }; + return ((unpack>>26 & 3)+1)*size[unpack>>24 & 3]/8; +} + +static uint32* +skipUnpack(uint32 *p) +{ + int32 n = (p[0] >> 16) & 0xFF; + return p + (n*unpackSize(p[0])+3 >> 2) + 1; +} + +void +convertMesh(Geometry *rwg, RslGeometry *g, int32 ii) +{ + RslPS2ResEntryHeader *resHeader = (RslPS2ResEntryHeader*)(g+1); + RslPS2InstanceData *inst = (RslPS2InstanceData*)(resHeader+1); + int32 numInst = resHeader->size >> 20; + uint8 *p = (uint8*)(inst+numInst); + inst += ii; + p += inst->dmaPacket; + Mesh *m = &rwg->meshHeader->mesh[inst->matID]; + + ps2::SkinVertex v; + uint32 mask = 0x1001; // tex coords, vertices + if(rwg->geoflags & Geometry::NORMALS) + mask |= 0x10; + if(rwg->geoflags & Geometry::PRELIT) + mask |= 0x100; + float32 *verts = &rwg->morphTargets[0].vertices[rwg->numVertices*3]; + float32 *norms = &rwg->morphTargets[0].normals[rwg->numVertices*3]; + uint8 *cols = &rwg->colors[rwg->numVertices*4]; + float32 *texCoords = &rwg->texCoords[0][rwg->numVertices*2]; + uint8 *indices = NULL; + float32 *weights = NULL; + Skin *skin = *PLUGINOFFSET(Skin*, rwg, skinGlobals.offset); + if(skin){ + indices = &skin->indices[rwg->numVertices*4]; + weights = &skin->weights[rwg->numVertices*4]; + mask |= 0x10000; + } + + int16 *vuVerts = NULL; + int8 *vuNorms = NULL; + uint8 *vuTex = NULL; + uint16 *vuCols = NULL; + uint32 *vuSkin = NULL; + + uint32 *w = (uint32*)p; + uint32 *end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10); + w += 4; + int flags = 0; + int32 nvert; + bool first = 1; + while(w < end){ + /* Get data pointers */ + + // GIFtag probably + assert(w[0] == 0x6C018000); // UNPACK + nvert = w[4] & 0x7FFF; + if(!first) nvert -=2; + w += 5; + + // positions + assert(w[0] == 0x20000000); // STMASK + w += 2; + assert(w[0] == 0x30000000); // STROW + w += 5; + assert((w[0] & 0xFF004000) == 0x79000000); + vuVerts = (int16*)(w+1); + if(!first) vuVerts += 2*3; + w = skipUnpack(w); + + // tex coords + assert(w[0] == 0x20000000); // STMASK + w += 2; + assert(w[0] == 0x30000000); // STROW + w += 5; + assert((w[0] & 0xFF004000) == 0x76004000); + vuTex = (uint8*)(w+1); + if(!first) vuTex += 2*2; + w = skipUnpack(w); + + if(rwg->geoflags & Geometry::NORMALS){ + assert((w[0] & 0xFF004000) == 0x6A000000); + vuNorms = (int8*)(w+1); + if(!first) vuNorms += 2*3; + w = skipUnpack(w); + } + + if(rwg->geoflags & Geometry::PRELIT){ + assert((w[0] & 0xFF004000) == 0x6F000000); + vuCols = (uint16*)(w+1); + if(!first) vuCols += 2; + w = skipUnpack(w); + } + + if(skin){ + assert((w[0] & 0xFF004000) == 0x6C000000); + vuSkin = w+1; + if(!first) vuSkin += 2*4; + w = skipUnpack(w); + } + + assert(w[0] == 0x14000006); // MSCAL + w++; + while(w[0] == 0) w++; + + /* Insert Data */ + for(int32 i = 0; i < nvert; i++){ + v.p[0] = vuVerts[0]/32768.0f*resHeader->scale[0] + resHeader->pos[0]; + v.p[1] = vuVerts[1]/32768.0f*resHeader->scale[1] + resHeader->pos[1]; + v.p[2] = vuVerts[2]/32768.0f*resHeader->scale[2] + resHeader->pos[2]; + v.t[0] = vuTex[0]/128.0f*inst->uvScale[0]; + v.t[1] = vuTex[1]/128.0f*inst->uvScale[1]; + if(mask & 0x10){ + v.n[0] = vuNorms[0]/127.0f; + v.n[1] = vuNorms[1]/127.0f; + v.n[2] = vuNorms[2]/127.0f; + } + if(mask & 0x100){ + v.c[0] = (vuCols[0] & 0x1f) * 255 / 0x1F; + v.c[1] = (vuCols[0]>>5 & 0x1f) * 255 / 0x1F; + v.c[2] = (vuCols[0]>>10 & 0x1f) * 255 / 0x1F; + v.c[3] = vuCols[0]&0x8000 ? 0xFF : 0; + } + if(mask & 0x10000){ + for(int j = 0; j < 4; j++){ + ((uint32*)v.w)[j] = vuSkin[j] & ~0x3FF; + v.i[j] = vuSkin[j] >> 2; + //if(v.i[j]) v.i[j]--; + if(v.w[j] == 0.0f) v.i[j] = 0; + } + } + + int32 idx = ps2::findVertexSkin(rwg, NULL, mask, &v); + if(idx < 0) + idx = rwg->numVertices++; + /* Insert mesh joining indices when we get the index of the first vertex + * in the first VU chunk of a non-first RslMesh. */ + if(i == 0 && first && ii != 0 && inst[-1].matID == inst->matID){ + m->indices[m->numIndices] = m->indices[m->numIndices-1]; + m->numIndices++; + m->indices[m->numIndices++] = idx; + if(inst[-1].numTriangles % 2) + m->indices[m->numIndices++] = idx; + } + m->indices[m->numIndices++] = idx; + ps2::insertVertexSkin(rwg, idx, mask, &v); + + vuVerts += 3; + vuTex += 2; + vuNorms += 3; + vuCols++; + vuSkin += 4; + } + first = 0; + } +} + +Atomic* +convertAtomic(RslAtomic *atomic) +{ + Atomic *rwa = new Atomic; + RslGeometry *g = atomic->geometry; + Geometry *rwg = new Geometry(0, 0, 0); + rwa->geometry = rwg; + + rwg->numMaterials = g->matList.numMaterials; + rwg->materialList = new Material*[rwg->numMaterials]; + for(int32 i = 0; i < rwg->numMaterials; i++) + rwg->materialList[i] = convertMaterial(g->matList.materials[i]); + + rwg->meshHeader = new MeshHeader; + rwg->meshHeader->flags = 1; + rwg->meshHeader->numMeshes = rwg->numMaterials; + rwg->meshHeader->mesh = new Mesh[rwg->meshHeader->numMeshes]; + rwg->meshHeader->totalIndices = 0; + Mesh *meshes = rwg->meshHeader->mesh; + for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++) + meshes[i].numIndices = 0; + + RslPS2ResEntryHeader *resHeader = (RslPS2ResEntryHeader*)(g+1); + RslPS2InstanceData *inst = (RslPS2InstanceData*)(resHeader+1); + int32 numInst = resHeader->size >> 20; + + int32 lastId = -1; + for(int32 i = 0; i < numInst; i++){ + Mesh *m = &meshes[inst[i].matID]; + rwg->numVertices += inst[i].numTriangles+2; + m->numIndices += inst[i].numTriangles+2; + // Extra indices since we're merging tristrip + // meshes with the same material. + // Be careful with face winding. + if(lastId == inst[i].matID) + m->numIndices += inst[i-1].numTriangles % 2 ? 3 : 2; + lastId = inst[i].matID; + } + for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++){ + rwg->meshHeader->mesh[i].material = rwg->materialList[i]; + rwg->meshHeader->totalIndices += meshes[i].numIndices; + } + rwg->geoflags = Geometry::TRISTRIP | + Geometry::POSITIONS | /* 0x01 ? */ + Geometry::TEXTURED | /* 0x04 ? */ + Geometry::LIGHT; + if(rwg->hasColoredMaterial()) + rwg->geoflags |= Geometry::MODULATE; + if(resHeader->flags & 0x2) + rwg->geoflags |= Geometry::NORMALS; + if(resHeader->flags & 0x8) + rwg->geoflags |= Geometry::PRELIT; + rwg->numTexCoordSets = 1; + + rwg->allocateData(); + rwg->meshHeader->allocateIndices(); + + Skin *skin = NULL; + if(resHeader->flags & 0x10) + assert(g->skin); + if(g->skin){ + skin = new Skin; + *PLUGINOFFSET(Skin*, rwg, skinGlobals.offset) = skin; + skin->init(g->skin->numBones, g->skin->numBones, rwg->numVertices); + memcpy(skin->inverseMatrices, g->skin->invMatrices, skin->numBones*64); + } + + for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++) + meshes[i].numIndices = 0; + rwg->meshHeader->totalIndices = rwg->numVertices = 0; + for(int32 i = 0; i < numInst; i++) + convertMesh(rwg, g, i); + for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++) + rwg->meshHeader->totalIndices += meshes[i].numIndices; + if(skin){ + skin->findNumWeights(rwg->numVertices); + skin->findUsedBones(rwg->numVertices); + } + rwg->calculateBoundingSphere(); + rwg->generateTriangles(); + return rwa; +} + +RslAtomic* +collectAtomics(RslAtomic *atomic, void *data) +{ + RslAtomic ***alist = (RslAtomic***)data; + *(*alist)++ = atomic; + return atomic; +} + +Clump* +convertClump(RslClump *c) +{ + Clump *rwc; + Frame *rwf; + Atomic *rwa; + rslFrameList frameList; + + rwc = new Clump; + rslFrameListInitialize(&frameList, (RslFrame*)c->object.parent); + Frame **rwframes = new Frame*[frameList.numFrames]; + for(int32 i = 0; i < frameList.numFrames; i++){ + rwf = convertFrame(frameList.frames[i]); + rwframes[i] = rwf; + void *par = frameList.frames[i]->object.parent; + int32 parent = findPointer(par, (void**)frameList.frames, frameList.numFrames); + if(parent >= 0) + rwframes[parent]->addChild(rwf); + } + rwc->parent = rwframes[0]; + + rwc->numAtomics = RslClumpGetNumAtomics(c); + rwc->atomicList = new Atomic*[rwc->numAtomics]; + RslAtomic **alist = new RslAtomic*[rwc->numAtomics]; + RslAtomic **ap = &alist[0]; + RslClumpForAllAtomics(c, collectAtomics, &ap); + for(int32 i = 0; i < rwc->numAtomics; i++){ + rwa = convertAtomic(alist[i]); + rwc->atomicList[i] = rwa; + int32 fi = findPointer(alist[i]->object.object.parent, (void**)frameList.frames, frameList.numFrames); + rwa->frame = rwframes[fi]; + rwa->clump = rwc; + } + + delete[] alist; + delete[] rwframes; + delete[] frameList.frames; + return rwc; +} + +RslAtomic* +makeTextures(RslAtomic *atomic, void*) +{ + RslGeometry *g = atomic->geometry; + RslMaterial *m; + for(int32 i = 0; i < g->matList.numMaterials; i++){ + m = g->matList.materials[i]; + if(m->texname){ + RslTexture *tex = RslTextureCreate(NULL); + strncpy(tex->name, m->texname, 32); + strncpy(tex->mask, m->texname, 32); + m->texture = tex; + } + if(m->matfx && m->matfx->effectType == MatFX::ENVMAP && + m->matfx->env.texname){ + RslTexture *tex = RslTextureCreate(NULL); + strncpy(tex->name, m->matfx->env.texname, 32); + strncpy(tex->mask, m->matfx->env.texname, 32); + m->matfx->env.texture = tex; + } + } + return atomic; +} + + + + uint8* getPalettePS2(RslRaster *raster) { @@ -356,10 +762,10 @@ convertTXD(RslTexDictionary *txd) void usage(void) { - fprintf(stderr, "%s [-v version] [-x] [-s] input [output.txd]\n", argv0); + fprintf(stderr, "%s [-v version] [-x] [-s] input [output.{txd|dff}]\n", argv0); fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n"); - fprintf(stderr, "\t-x extract to tga\n"); - fprintf(stderr, "\t-s don't unswizzle\n"); + fprintf(stderr, "\t-x extract textures to tga\n"); + fprintf(stderr, "\t-s don't unswizzle textures\n"); exit(1); } @@ -368,6 +774,7 @@ main(int argc, char *argv[]) { gta::attachPlugins(); rw::version = 0x34003; + rw::platform = PLATFORM_D3D8; assert(sizeof(void*) == 4); int extract = 0; @@ -389,10 +796,11 @@ main(int argc, char *argv[]) if(argc < 1) usage(); - World *world; - Sector *sector; - RslClump *clump; - RslTexDictionary *txd; + World *world = NULL; + Sector *sector = NULL; + RslClump *clump = NULL; + RslAtomic *atomic = NULL; + RslTexDictionary *txd = NULL; StreamFile stream; @@ -408,11 +816,12 @@ main(int argc, char *argv[]) assert(txd); goto writeTxd; } - if(ident == 0x10){ + if(ident == ID_CLUMP){ findChunk(&stream, ID_CLUMP, NULL, NULL); clump = RslClumpStreamRead(&stream); stream.close(); - return 0; + assert(clump); + goto writeDff; } RslStream *rslstr = new RslStream; @@ -486,14 +895,30 @@ main(int argc, char *argv[]) }else if(rslstr->ident == MDL_IDENT){ uint8 *p = *rslstr->hashTab; p -= 0x24; - RslAtomic *a = (RslAtomic*)p; - clump = a->clump; - if(clump) + atomic = (RslAtomic*)p; + clump = atomic->clump; + Clump *rwc; + if(clump){ + RslClumpForAllAtomics(clump, makeTextures, NULL); //RslClumpForAllAtomics(clump, dumpAtomicCB, NULL); - RslFrameForAllChildren(RslClumpGetFrame(clump), dumpFrameCB, NULL); - else + //RslFrameForAllChildren(RslClumpGetFrame(clump), dumpFrameCB, NULL); + }else{ + makeTextures(atomic, NULL); + clump = RslClumpCreate(); + RslAtomicSetFrame(atomic, RslFrameCreate()); + RslClumpSetFrame(clump, RslAtomicGetFrame(atomic)); + RslClumpAddAtomic(clump, atomic); //dumpAtomicCB(a, NULL); - RslFrameForAllChildren(RslAtomicGetFrame(a), dumpFrameCB, NULL); + //RslFrameForAllChildren(RslAtomicGetFrame(atomic), dumpFrameCB, NULL); + } + writeDff: + rwc = convertClump(clump); + if(argc > 1) + assert(stream.open(argv[1], "wb")); + else + assert(stream.open("out.dff", "wb")); + rwc->streamWrite(&stream); + stream.close(); }else if(rslstr->ident == TEX_IDENT){ txd = (RslTexDictionary*)rslstr->data; writeTxd: