diff --git a/src/anim.cpp b/src/anim.cpp index 2e52a60..2517000 100644 --- a/src/anim.cpp +++ b/src/anim.cpp @@ -132,7 +132,7 @@ Animation::streamReadLegacy(Stream *stream) stream->read32(&frames[i].t, 3*4); frames[i].time = stream->readF32(); int32 prev = stream->readI32(); - frames[i].prevFrame = &frames[prev]; + frames[i].prev = &frames[prev]; } return anim; } @@ -162,7 +162,7 @@ Animation::streamWriteLegacy(Stream *stream) stream->write32(&frames[i].q, 4*4); stream->write32(&frames[i].t, 3*4); stream->writeF32(frames[i].time); - stream->writeI32(frames[i].prevFrame - frames); + stream->writeI32(frames[i].prev - frames); } return true; } diff --git a/src/base.cpp b/src/base.cpp index 189d45c..de3706b 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -488,8 +488,10 @@ Matrix::lookAt(const V3d &dir, const V3d &up) this->flags = TYPEORTHONORMAL; } -/* For a row-major representation, this calculates src1 * src. - * For colum-major src2 * src1 */ +/* For a row-major representation, this calculates src1 * src2. + * For column-major src2 * src1. + * i.e. a vector is first xformed by src1, then by src2 + */ void Matrix::mult_(Matrix *dst, const Matrix *src1, const Matrix *src2) { diff --git a/src/hanim.cpp b/src/hanim.cpp index 900843c..3f1ecb6 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -102,7 +102,8 @@ HAnimHierarchy::attachByIndex(int32 idx) int32 id = this->nodeInfo[idx].id; // Frame *f = findById(this->parentFrame, id); Frame *f = findUnattachedById(this, this->parentFrame, id); - this->nodeInfo[idx].frame = f; + if(f) + this->nodeInfo[idx].frame = f; } void @@ -172,8 +173,13 @@ HAnimHierarchy::updateMatrices(void) HAnimNodeInfo *node = this->nodeInfo; for(i = 0; i < this->numNodes; i++){ anim->applyCB(&animMat, anim->getInterpFrame(i)); + + // TODO: here we could update local matrices + Matrix::mult(curMat, &animMat, parentMat); + // TODO: here we could update LTM + if(node->flags & PUSH) *sp++ = parentMat; parentMat = curMat; @@ -317,7 +323,7 @@ hAnimFrameRead(Stream *stream, Animation *anim) stream->read32(&frames[i].q, 4*4); stream->read32(&frames[i].t, 3*4); int32 prev = stream->readI32()/0x24; - frames[i].prevFrame = &frames[prev]; + frames[i].prev = &frames[prev]; } } @@ -329,7 +335,7 @@ hAnimFrameWrite(Stream *stream, Animation *anim) stream->writeF32(frames[i].time); stream->write32(&frames[i].q, 4*4); stream->write32(&frames[i].t, 3*4); - stream->writeI32((frames[i].prevFrame - frames)*0x24); + stream->writeI32((frames[i].prev - frames)*0x24); } } diff --git a/src/rwanim.h b/src/rwanim.h index 8967ea7..e6dd1d5 100644 --- a/src/rwanim.h +++ b/src/rwanim.h @@ -63,6 +63,10 @@ struct Animation int32 flags, float duration); void destroy(void); int32 getNumNodes(void); + KeyFrameHeader *getAnimFrame(int32 n){ + return (KeyFrameHeader*)((uint8*)this->keyframes + + n*this->interpInfo->animKeyFrameSize); + } static Animation *streamRead(Stream *stream); static Animation *streamReadLegacy(Stream *stream); bool streamWrite(Stream *stream); diff --git a/src/rwplugins.h b/src/rwplugins.h index defc3be..4b90c87 100644 --- a/src/rwplugins.h +++ b/src/rwplugins.h @@ -6,7 +6,7 @@ namespace rw { struct HAnimKeyFrame { - HAnimKeyFrame *prevFrame; + HAnimKeyFrame *prev; float32 time; Quat q; V3d t; diff --git a/src/rwuserdata.h b/src/rwuserdata.h index 29c9ec6..00d7355 100644 --- a/src/rwuserdata.h +++ b/src/rwuserdata.h @@ -64,7 +64,18 @@ struct UserDataExtension int32 numArrays; UserDataArray *arrays; - // TODO: static accessors + int32 add(const char *name, int32 datatype, int32 numElements); + void remove(int32 n); + int32 getCount(void) { return numArrays; } + UserDataArray *get(int32 n) { return n >= numArrays ? nil : &arrays[n]; } + int32 findIndex(const char *name); + + static UserDataExtension *get(Geometry *geo); + static UserDataExtension *get(Frame *frame); + static UserDataExtension *get(Camera *cam); + static UserDataExtension *get(Light *light); + static UserDataExtension *get(Material *mat); + static UserDataExtension *get(Texture *tex); }; struct UserDataGlobals diff --git a/src/skin.cpp b/src/skin.cpp index 5ede2cc..75ed1e0 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -252,6 +252,55 @@ getSizeSkin(void *object, int32 offset, int32) return size; } +static Stream* +readSkinLegacy(Stream *stream, int32 len, void *object, int32, int32) +{ + Atomic *atomic = (Atomic*)object; + Geometry *geometry = atomic->geometry; + + int32 numBones = stream->readI32(); + int32 numVertices = stream->readI32(); + assert(numVertices == geometry->numVertices); + + Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); + *PLUGINOFFSET(Skin*, geometry, skinGlobals.geoOffset) = skin; + skin->init(numBones, numBones, numVertices); + skin->numWeights = 4; + + stream->read8(skin->indices, numVertices*4); + stream->read32(skin->weights, numVertices*16); + + HAnimHierarchy *hier = HAnimHierarchy::create(numBones, nil, nil, 0, 36); + + for(int i = 0; i < numBones; i++){ + hier->nodeInfo[i].id = stream->readI32(); + hier->nodeInfo[i].index = stream->readI32(); + hier->nodeInfo[i].flags = stream->readI32() & 3; +// printf("%d %d %d %d\n", i, hier->nodeInfo[i].id, hier->nodeInfo[i].index, hier->nodeInfo[i].flags); + stream->read32(&skin->inverseMatrices[i*16], 64); + + Matrix mat; + Matrix::invert(&mat, (Matrix*)&skin->inverseMatrices[i*16]); +// printf("[ [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" +// " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" +// " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" +// " [ %8.4f, %8.4f, %8.4f, %8.4f ] ]\n" +// " %08x == flags\n", +// mat.right.x, mat.up.x, mat.at.x, mat.pos.x, +// mat.right.y, mat.up.y, mat.at.y, mat.pos.y, +// mat.right.z, mat.up.z, mat.at.z, mat.pos.z, +// 0.0f, 0.0f, 0.0f, 1.0f, +// mat.flags); + } + Frame *frame = atomic->getFrame()->child; + assert(frame->next == nil); // in old files atomic is above hierarchy it seems + assert(frame->count() == numBones); // assuming one frame per node this should also be true + HAnimData::get(frame)->hierarchy = hier; + hier->parentFrame = frame; + + return stream; +} + static void skinRights(void *object, int32, int32, uint32) { @@ -317,6 +366,7 @@ registerSkinPlugin(void) o = Atomic::registerPlugin(sizeof(HAnimHierarchy*),ID_SKIN, createSkinAtm, destroySkinAtm, copySkinAtm); skinGlobals.atomicOffset = o; + Atomic::registerPluginStream(ID_SKIN, readSkinLegacy, nil, nil); Atomic::setStreamRightsCallback(ID_SKIN, skinRights); } diff --git a/src/userdata.cpp b/src/userdata.cpp index ec4ad03..e17a3d5 100644 --- a/src/userdata.cpp +++ b/src/userdata.cpp @@ -226,27 +226,27 @@ getSizeUserData(void *object, int32 offset, int32) return size; } -static int32 -add(UserDataExtension *ext, const char *name, int32 datatype, int32 numElements) +int32 +UserDataExtension::add(const char *name, int32 datatype, int32 numElements) { int32 i; int32 len; int32 typesz; UserDataArray *a; // try to find empty slot - for(i = 0; i < ext->numArrays; i++) - if(ext->arrays[i].datatype == USERDATANA) + for(i = 0; i < this->numArrays; i++) + if(this->arrays[i].datatype == USERDATANA) goto alloc; // have to realloc - a = (UserDataArray*)udMalloc((ext->numArrays+1)*sizeof(UserDataArray)); + a = (UserDataArray*)udMalloc((this->numArrays+1)*sizeof(UserDataArray)); if(a == nil) return -1; - memcpy(a, ext->arrays, ext->numArrays*sizeof(UserDataArray)); - rwFree(ext->arrays); - ext->arrays = a; - i = ext->numArrays++; + memcpy(a, this->arrays, this->numArrays*sizeof(UserDataArray)); + rwFree(this->arrays); + this->arrays = a; + i = this->numArrays++; alloc: - a = &ext->arrays[i]; + a = &this->arrays[i]; len = (int32)strlen(name)+1; a->name = (char*)udMalloc(len+1); assert(a->name); @@ -262,11 +262,11 @@ alloc: return i; } -static void -remove(UserDataExtension *ext, int32 n) +void +UserDataExtension::remove(int32 n) { int32 i; - UserDataArray *a = &ext->arrays[n]; + UserDataArray *a = &this->arrays[n]; if(a->name){ rwFree(a->name); a->name = nil; @@ -282,39 +282,39 @@ remove(UserDataExtension *ext, int32 n) a->numElements = 0; } +int32 +UserDataExtension::findIndex(const char *name) { + for(int32 i = 0; i < this->numArrays; i++) + if(strcmp(this->arrays[i].name, name) == 0) + return i; + return -1; +} + #define ACCESSOR(TYPE, NAME) \ int32 \ UserDataArray::NAME##Add(TYPE *t, const char *name, int32 datatype, int32 numElements) \ { \ - return add(PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset), \ - name, datatype, numElements); \ + return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->add(name, datatype, numElements); \ } \ void \ UserDataArray::NAME##Remove(TYPE *t, int32 n) \ { \ - remove(PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset), n); \ + PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->remove(n); \ } \ int32 \ UserDataArray::NAME##GetCount(TYPE *t) \ { \ - return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->numArrays; \ + return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->getCount(); \ } \ UserDataArray* \ UserDataArray::NAME##Get(TYPE *t, int32 n) \ { \ - if(n >= PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->numArrays) \ - return nil; \ - return &PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->arrays[n]; \ + return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->get(n); \ } \ int32 \ UserDataArray::NAME##FindIndex(TYPE *t, const char *name) \ { \ - int32 i; \ - UserDataExtension *ext = PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset); \ - for(i = 0; i < ext->numArrays; i++) \ - if(strcmp(ext->arrays[i].name, name) == 0) \ - return i; \ - return -1; \ + return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->findIndex(name); \ } ACCESSOR(Geometry, geometry) @@ -324,6 +324,13 @@ ACCESSOR(Light, light) ACCESSOR(Material, material) ACCESSOR(Texture, texture) +UserDataExtension *UserDataExtension::get(Geometry *geo) { return PLUGINOFFSET(UserDataExtension, geo, userDataGlobals.geometryOffset); } +UserDataExtension *UserDataExtension::get(Frame *frame) { return PLUGINOFFSET(UserDataExtension, frame, userDataGlobals.frameOffset); } +UserDataExtension *UserDataExtension::get(Camera *cam) { return PLUGINOFFSET(UserDataExtension, cam, userDataGlobals.cameraOffset); } +UserDataExtension *UserDataExtension::get(Light *light) { return PLUGINOFFSET(UserDataExtension, light, userDataGlobals.lightOffset); } +UserDataExtension *UserDataExtension::get(Material *mat) { return PLUGINOFFSET(UserDataExtension, mat, userDataGlobals.materialOffset); } +UserDataExtension *UserDataExtension::get(Texture *tex) { return PLUGINOFFSET(UserDataExtension, tex, userDataGlobals.textureOffset); } + void registerUserDataPlugin(void) {