From 90b2d98b97a7055b52f1111ae41a89f469b81a91 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 20 Dec 2015 01:04:31 +0100 Subject: [PATCH] fixed more bugs and implemented better lcs conversion --- src/clump.cpp | 14 +-- src/d3d9.cpp | 2 +- src/mdl.cpp | 2 +- src/ps2.cpp | 4 +- src/rwbase.cpp | 128 ++++++++++++++++++++ src/rwbase.h | 3 + src/rwobjects.h | 1 + tools/dffwrite/dffwrite.cpp | 232 +++++++++++++++++++++++++++++++++++- 8 files changed, 365 insertions(+), 21 deletions(-) diff --git a/src/clump.cpp b/src/clump.cpp index 95e4989..d1a5c91 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -114,19 +114,7 @@ Frame::updateLTM(void) Frame *parent = (Frame*)this->parent; if(parent){ parent->updateLTM(); -// TODO: replace with platform optimized code -#define L(i,j) this->ltm[i*4+j] -#define A(i,j) parent->ltm[i*4+j] -#define B(i,j) this->matrix[i*4+j] - for(int i = 0; i < 4; i++) - for(int j = 0; j < 4; j++) - L(i,j) = A(0,j)*B(i,0) - + A(1,j)*B(i,1) - + A(2,j)*B(i,2) - + A(3,j)*B(i,3); -#undef L -#undef A -#undef B + matrixMult(this->ltm, parent->ltm, this->matrix); this->dirty = false; }else{ memcpy(this->ltm, this->matrix, 16*4); diff --git a/src/d3d9.cpp b/src/d3d9.cpp index 591a6fd..96cee7b 100644 --- a/src/d3d9.cpp +++ b/src/d3d9.cpp @@ -338,7 +338,7 @@ ObjPipeline::uninstance(Atomic *atomic) if(inst->minVert == 0) memcpy(mesh->indices, &indices[inst->startIndex], inst->numIndex*2); else - for(int32 j = 0; j < inst->numIndex; j++) + for(uint32 j = 0; j < inst->numIndex; j++) mesh->indices[j] = indices[inst->startIndex+j] + inst->minVert; mesh++; inst++; diff --git a/src/mdl.cpp b/src/mdl.cpp index 730b377..cdef228 100644 --- a/src/mdl.cpp +++ b/src/mdl.cpp @@ -260,7 +260,7 @@ convertRslMesh(Geometry *g, RslGeometry *rg, Mesh *m, RslMesh *rm) 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.i[j]) v.i[j]--; if(v.w[j] == 0.0f) v.i[j] = 0; } } diff --git a/src/ps2.cpp b/src/ps2.cpp index 0c0edec..7f67494 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -1205,9 +1205,9 @@ static int debugadc(Geometry *g, MeshHeader *mh, ADCData *adc) { int n = 0; - for(int i = 0; i < mh->numMeshes; i++){ + for(uint32 i = 0; i < mh->numMeshes; i++){ uint16 *idx = mh->mesh[i].indices; - for(int j = 0; j < mh->mesh[i].numIndices-2; j++){ + for(uint32 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]); diff --git a/src/rwbase.cpp b/src/rwbase.cpp index f95c4dd..9cf401b 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -25,6 +25,134 @@ int build = 0xFFFF; #endif char *debugFile = NULL; +void +matrixMult(float32 *out, float32 *a, float32 *b) +{ + // TODO: replace with platform optimized code + #define L(i,j) out[i*4+j] + #define A(i,j) a[i*4+j] + #define B(i,j) b[i*4+j] + for(int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + L(i,j) = A(0,j)*B(i,0) + + A(1,j)*B(i,1) + + A(2,j)*B(i,2) + + A(3,j)*B(i,3); + #undef L + #undef A + #undef B +} + +void +matrixInvert(float32 *out, float32 *m) +{ + float32 inv[16], det; + int i; + + inv[0] = m[5] * m[10] * m[15] - + m[5] * m[11] * m[14] - + m[9] * m[6] * m[15] + + m[9] * m[7] * m[14] + + m[13] * m[6] * m[11] - + m[13] * m[7] * m[10]; + inv[4] = -m[4] * m[10] * m[15] + + m[4] * m[11] * m[14] + + m[8] * m[6] * m[15] - + m[8] * m[7] * m[14] - + m[12] * m[6] * m[11] + + m[12] * m[7] * m[10]; + inv[8] = m[4] * m[9] * m[15] - + m[4] * m[11] * m[13] - + m[8] * m[5] * m[15] + + m[8] * m[7] * m[13] + + m[12] * m[5] * m[11] - + m[12] * m[7] * m[9]; + inv[12] = -m[4] * m[9] * m[14] + + m[4] * m[10] * m[13] + + m[8] * m[5] * m[14] - + m[8] * m[6] * m[13] - + m[12] * m[5] * m[10] + + m[12] * m[6] * m[9]; + inv[1] = -m[1] * m[10] * m[15] + + m[1] * m[11] * m[14] + + m[9] * m[2] * m[15] - + m[9] * m[3] * m[14] - + m[13] * m[2] * m[11] + + m[13] * m[3] * m[10]; + inv[5] = m[0] * m[10] * m[15] - + m[0] * m[11] * m[14] - + m[8] * m[2] * m[15] + + m[8] * m[3] * m[14] + + m[12] * m[2] * m[11] - + m[12] * m[3] * m[10]; + inv[9] = -m[0] * m[9] * m[15] + + m[0] * m[11] * m[13] + + m[8] * m[1] * m[15] - + m[8] * m[3] * m[13] - + m[12] * m[1] * m[11] + + m[12] * m[3] * m[9]; + inv[13] = m[0] * m[9] * m[14] - + m[0] * m[10] * m[13] - + m[8] * m[1] * m[14] + + m[8] * m[2] * m[13] + + m[12] * m[1] * m[10] - + m[12] * m[2] * m[9]; + inv[2] = m[1] * m[6] * m[15] - + m[1] * m[7] * m[14] - + m[5] * m[2] * m[15] + + m[5] * m[3] * m[14] + + m[13] * m[2] * m[7] - + m[13] * m[3] * m[6]; + inv[6] = -m[0] * m[6] * m[15] + + m[0] * m[7] * m[14] + + m[4] * m[2] * m[15] - + m[4] * m[3] * m[14] - + m[12] * m[2] * m[7] + + m[12] * m[3] * m[6]; + inv[10] = m[0] * m[5] * m[15] - + m[0] * m[7] * m[13] - + m[4] * m[1] * m[15] + + m[4] * m[3] * m[13] + + m[12] * m[1] * m[7] - + m[12] * m[3] * m[5]; + inv[14] = -m[0] * m[5] * m[14] + + m[0] * m[6] * m[13] + + m[4] * m[1] * m[14] - + m[4] * m[2] * m[13] - + m[12] * m[1] * m[6] + + m[12] * m[2] * m[5]; + inv[3] = -m[1] * m[6] * m[11] + + m[1] * m[7] * m[10] + + m[5] * m[2] * m[11] - + m[5] * m[3] * m[10] - + m[9] * m[2] * m[7] + + m[9] * m[3] * m[6]; + inv[7] = m[0] * m[6] * m[11] - + m[0] * m[7] * m[10] - + m[4] * m[2] * m[11] + + m[4] * m[3] * m[10] + + m[8] * m[2] * m[7] - + m[8] * m[3] * m[6]; + inv[11] = -m[0] * m[5] * m[11] + + m[0] * m[7] * m[9] + + m[4] * m[1] * m[11] - + m[4] * m[3] * m[9] - + m[8] * m[1] * m[7] + + m[8] * m[3] * m[5]; + inv[15] = m[0] * m[5] * m[10] - + m[0] * m[6] * m[9] - + m[4] * m[1] * m[10] + + m[4] * m[2] * m[9] + + m[8] * m[1] * m[6] - + m[8] * m[2] * m[5]; + det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; + if(det == 0) + return; + det = 1.0f / det; + for(i = 0; i < 16; i++) + out[i] = inv[i] * det; +} + int32 Stream::writeI8(int8 val) { diff --git a/src/rwbase.h b/src/rwbase.h index e5b87e2..963d9b9 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -151,6 +151,9 @@ extern int build; extern int platform; extern char *debugFile; +void matrixMult(float32 *out, float32 *a, float32 *b); +void matrixInvert(float32 *out, float32 *in); + // 0x04000000 3.1 // 0x08000000 3.2 // 0x0C000000 3.3 diff --git a/src/rwobjects.h b/src/rwobjects.h index ec6e678..8e3780f 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -470,6 +470,7 @@ struct AnimInterpolatorInfo }; void registerAnimInterpolatorInfo(AnimInterpolatorInfo *interpInfo); +AnimInterpolatorInfo *findAnimInterpolatorInfo(int32 id); struct Animation { diff --git a/tools/dffwrite/dffwrite.cpp b/tools/dffwrite/dffwrite.cpp index e9f852a..5263e25 100644 --- a/tools/dffwrite/dffwrite.cpp +++ b/tools/dffwrite/dffwrite.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -10,15 +11,220 @@ using namespace std; using namespace rw; +struct bone { + int32 id; + char *name; +}; + +bone idMapVC[] = { + { 0, "Root" }, + { 1, "Pelvis" }, + { 2, "Spine" }, + { 3, "Spine1" }, + { 4, "Neck" }, + { 5, "Head" }, + { 31, "Bip01 L Clavicle" }, + { 32, "L UpperArm" }, + { 33, "L Forearm" }, + { 34, "L Hand" }, + { 35, "L Finger" }, + { 21, "Bip01 R Clavicle" }, + { 22, "R UpperArm" }, + { 23, "R Forearm" }, + { 24, "R Hand" }, + { 25, "R Finger" }, + { 41, "L Thigh" }, + { 42, "L Calf" }, + { 43, "L Foot" }, + { 2000, "L Toe0" }, + { 51, "R Thigh" }, + { 52, "R Calf" }, + { 53, "R Foot" }, + { 2001, "R Toe0" }, +}; + +bone csIdMapVC[] = { + { 0, "Root" }, + { 1, "Pelvis" }, + { 2, "Spine" }, + { 3, "Spine1" }, + { 4, "Neck" }, + { 5, "Head" }, + { 2000, "HeadNub" }, // "Bip01 HeadNub" + { 5006, "llid" }, + { 5005, "rlid" }, + { 5001, "rbrow1" }, + { 5002, "rbrow2" }, + { 5004, "lbrow1" }, + { 5003, "lbrow2" }, + { 5008, "lcheek" }, + { 5015, "rcorner" }, + { 5016, "lcorner" }, + { 5017, "jaw1" }, + { 5018, "jaw2" }, + { 5019, "llip" }, + { 5020, "llip01" }, + { 5012, "ltlip1" }, + { 5013, "ltlip2" }, + { 5014, "ltlip3" }, + { 5009, "rtlip1" }, + { 5010, "rtlip2" }, + { 5011, "rtlip3" }, + { 5007, "rcheek" }, + { 5021, "reye" }, + { 5022, "leye" }, + { 31, "L Clavicle" }, // "Bip01 L Clavicle" + { 32, "L UpperArm" }, + { 33, "L Forearm" }, + { 34, "L Hand" }, + { 35, "L Finger0" }, // "L Finger" + { 36, "L Finger01" }, // "Root L Finger01" + { 2001, "L Finger0Nub" }, // "Bip01 L Finger0Nub" + { 21, "R Clavicle" }, // "Bip01 R Clavicle" + { 22, "R UpperArm" }, + { 23, "R Forearm" }, + { 24, "R Hand" }, + { 25, "R Finger0" }, // "R Finger" + { 26, "R Finger01" }, // "Root R Finger01" + { 2002, "R Finger0Nub" }, // "Bip01 R Finger0Nub" + { 41, "L Thigh" }, + { 42, "L Calf" }, + { 43, "L Foot" }, + { 2003, "L Toe0" }, + { 2004, "L Toe0Nub" }, // "Bip01 L Toe0Nub" + { 51, "R Thigh" }, + { 52, "R Calf" }, + { 53, "R Foot" }, + { 2005, "R Toe0" }, + { 2006, "R Toe0Nub" }, // "Bip01 R Toe0Nub" +}; + +int +strcmpci(const char *s, const char *t) +{ + while(*s && *t && tolower(*s) == tolower(*t)){ + s++; + t++; + } + return *s-*t; +} + +Frame* +assignIdCB(Frame *f, void *p) +{ + HAnimData *hanim = PLUGINOFFSET(HAnimData, f, hAnimOffset); + char *name = PLUGINOFFSET(char, f, gta::nodeNameOffset); + HAnimHierarchy *hier = (HAnimHierarchy*)p; + bone *map = hier->numNodes == 24 ? idMapVC : csIdMapVC; + for(int32 i = 0; i < hier->numNodes; i++){ + if(strcmpci(name, map[i].name) == 0){ + hanim->id = map[i].id; + break; + } + } + f->forAllChildren(assignIdCB, hier); + return f; +} + +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 +assignNodeIDs(Clump *c) +{ + HAnimHierarchy *hier = getHierarchy(c); + if(hier == NULL || (hier->numNodes != 24 && hier->numNodes != 53)) + return; + bone *map = hier->numNodes == 24 ? idMapVC : csIdMapVC; + for(int32 i = 0; i < hier->numNodes; i++) + hier->nodeInfo[i].id = map[hier->nodeInfo[i].index].id; + assignIdCB((Frame*)c->parent, hier); +} + +void +mirrorFrameHier(Frame *f) +{ + if(f->next){ + Frame *n = f->next; + Frame *p = (Frame*)f->parent; + f->removeChild(); + mirrorFrameHier(n); + p->addChild(f); + } + if(f->child) + mirrorFrameHier(f->child); +} + +void +generateInvBoneMats(Atomic *a) +{ + float32 rootInv[16], tmp[16]; + HAnimHierarchy *h = getHierarchy(a->clump); + Frame *root = h->parentFrame; + root->updateLTM(); + matrixInvert(rootInv, root->ltm); + Skin *skin = *PLUGINOFFSET(Skin*, a->geometry, skinGlobals.offset); + assert(skin->numBones == h->numNodes); + for(int32 i = 0; i < h->numNodes; i++){ + //assert(h->nodeInfo[i].frame); + if(h->nodeInfo[i].frame == NULL){ + printf("warning: no node for node %d/%d\n", i, h->nodeInfo[i].id); + continue; + } + h->nodeInfo[i].frame->updateLTM(); + float32 *m = &skin->inverseMatrices[i*16]; + matrixMult(tmp, rootInv, h->nodeInfo[i].frame->ltm); + matrixInvert(m, tmp); + } +} + +Frame* +findFrameById(Frame *f, int32 id) +{ + if(f == NULL) + return NULL; + HAnimData *hanim = PLUGINOFFSET(HAnimData, f, hAnimOffset); + if(hanim->id == id) + return f; + Frame *ff = findFrameById(f->next, id); + if(ff) return ff; + return findFrameById(f->child, id); +} + +void +attachFrames(Clump *c) +{ + HAnimHierarchy *h = getHierarchy(c); + for(int32 i = 0; i < h->numNodes; i++) + h->nodeInfo[i].frame = findFrameById(h->parentFrame, h->nodeInfo[i].id); +} + int main(int argc, char *argv[]) { // rw::version = 0x31000; // rw::build = 0; - rw::version = 0; +// rw::version = 0; // rw::version = 0x32000; -// rw::version = 0x33002; + rw::version = 0x33002; rw::platform = PLATFORM_D3D8; // rw::version = 0x30200; @@ -29,6 +235,11 @@ main(int argc, char *argv[]) rw::Clump *c; + if(argc < 2){ + printf("usage: %s input.dff [output.dff]\n", argv[0]); + return 0; + } + // rw::StreamFile in; // in.open(argv[1], "rb"); @@ -73,9 +284,22 @@ main(int argc, char *argv[]) assert(c != NULL); } - if(lcs) - for(int32 i = 0; i < c->numAtomics; i++) + if(lcs){ + HAnimHierarchy *hier = getHierarchy(c); + if(hier) + hier->maxInterpKeyFrameSize = findAnimInterpolatorInfo(1)->keyFrameSize; + mirrorFrameHier((Frame*)c->parent); + assignNodeIDs(c); + attachFrames(c); + 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]; + generateInvBoneMats(c->atomicList[i]); + } + } + } if(rw::version == 0){ rw::version = header.version;