userdata changes; hanim fixes; support for reading old skins

This commit is contained in:
aap 2020-08-06 09:14:32 +02:00
parent 26a5502ee1
commit 171e737842
8 changed files with 115 additions and 35 deletions

View File

@ -132,7 +132,7 @@ Animation::streamReadLegacy(Stream *stream)
stream->read32(&frames[i].t, 3*4); stream->read32(&frames[i].t, 3*4);
frames[i].time = stream->readF32(); frames[i].time = stream->readF32();
int32 prev = stream->readI32(); int32 prev = stream->readI32();
frames[i].prevFrame = &frames[prev]; frames[i].prev = &frames[prev];
} }
return anim; return anim;
} }
@ -162,7 +162,7 @@ Animation::streamWriteLegacy(Stream *stream)
stream->write32(&frames[i].q, 4*4); stream->write32(&frames[i].q, 4*4);
stream->write32(&frames[i].t, 3*4); stream->write32(&frames[i].t, 3*4);
stream->writeF32(frames[i].time); stream->writeF32(frames[i].time);
stream->writeI32(frames[i].prevFrame - frames); stream->writeI32(frames[i].prev - frames);
} }
return true; return true;
} }

View File

@ -488,8 +488,10 @@ Matrix::lookAt(const V3d &dir, const V3d &up)
this->flags = TYPEORTHONORMAL; this->flags = TYPEORTHONORMAL;
} }
/* For a row-major representation, this calculates src1 * src. /* For a row-major representation, this calculates src1 * src2.
* For colum-major src2 * src1 */ * For column-major src2 * src1.
* i.e. a vector is first xformed by src1, then by src2
*/
void void
Matrix::mult_(Matrix *dst, const Matrix *src1, const Matrix *src2) Matrix::mult_(Matrix *dst, const Matrix *src1, const Matrix *src2)
{ {

View File

@ -102,7 +102,8 @@ HAnimHierarchy::attachByIndex(int32 idx)
int32 id = this->nodeInfo[idx].id; int32 id = this->nodeInfo[idx].id;
// Frame *f = findById(this->parentFrame, id); // Frame *f = findById(this->parentFrame, id);
Frame *f = findUnattachedById(this, this->parentFrame, id); Frame *f = findUnattachedById(this, this->parentFrame, id);
this->nodeInfo[idx].frame = f; if(f)
this->nodeInfo[idx].frame = f;
} }
void void
@ -172,8 +173,13 @@ HAnimHierarchy::updateMatrices(void)
HAnimNodeInfo *node = this->nodeInfo; HAnimNodeInfo *node = this->nodeInfo;
for(i = 0; i < this->numNodes; i++){ for(i = 0; i < this->numNodes; i++){
anim->applyCB(&animMat, anim->getInterpFrame(i)); anim->applyCB(&animMat, anim->getInterpFrame(i));
// TODO: here we could update local matrices
Matrix::mult(curMat, &animMat, parentMat); Matrix::mult(curMat, &animMat, parentMat);
// TODO: here we could update LTM
if(node->flags & PUSH) if(node->flags & PUSH)
*sp++ = parentMat; *sp++ = parentMat;
parentMat = curMat; parentMat = curMat;
@ -317,7 +323,7 @@ hAnimFrameRead(Stream *stream, Animation *anim)
stream->read32(&frames[i].q, 4*4); stream->read32(&frames[i].q, 4*4);
stream->read32(&frames[i].t, 3*4); stream->read32(&frames[i].t, 3*4);
int32 prev = stream->readI32()/0x24; 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->writeF32(frames[i].time);
stream->write32(&frames[i].q, 4*4); stream->write32(&frames[i].q, 4*4);
stream->write32(&frames[i].t, 3*4); stream->write32(&frames[i].t, 3*4);
stream->writeI32((frames[i].prevFrame - frames)*0x24); stream->writeI32((frames[i].prev - frames)*0x24);
} }
} }

View File

@ -63,6 +63,10 @@ struct Animation
int32 flags, float duration); int32 flags, float duration);
void destroy(void); void destroy(void);
int32 getNumNodes(void); int32 getNumNodes(void);
KeyFrameHeader *getAnimFrame(int32 n){
return (KeyFrameHeader*)((uint8*)this->keyframes +
n*this->interpInfo->animKeyFrameSize);
}
static Animation *streamRead(Stream *stream); static Animation *streamRead(Stream *stream);
static Animation *streamReadLegacy(Stream *stream); static Animation *streamReadLegacy(Stream *stream);
bool streamWrite(Stream *stream); bool streamWrite(Stream *stream);

View File

@ -6,7 +6,7 @@ namespace rw {
struct HAnimKeyFrame struct HAnimKeyFrame
{ {
HAnimKeyFrame *prevFrame; HAnimKeyFrame *prev;
float32 time; float32 time;
Quat q; Quat q;
V3d t; V3d t;

View File

@ -64,7 +64,18 @@ struct UserDataExtension
int32 numArrays; int32 numArrays;
UserDataArray *arrays; 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 struct UserDataGlobals

View File

@ -252,6 +252,55 @@ getSizeSkin(void *object, int32 offset, int32)
return size; 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 static void
skinRights(void *object, int32, int32, uint32) skinRights(void *object, int32, int32, uint32)
{ {
@ -317,6 +366,7 @@ registerSkinPlugin(void)
o = Atomic::registerPlugin(sizeof(HAnimHierarchy*),ID_SKIN, o = Atomic::registerPlugin(sizeof(HAnimHierarchy*),ID_SKIN,
createSkinAtm, destroySkinAtm, copySkinAtm); createSkinAtm, destroySkinAtm, copySkinAtm);
skinGlobals.atomicOffset = o; skinGlobals.atomicOffset = o;
Atomic::registerPluginStream(ID_SKIN, readSkinLegacy, nil, nil);
Atomic::setStreamRightsCallback(ID_SKIN, skinRights); Atomic::setStreamRightsCallback(ID_SKIN, skinRights);
} }

View File

@ -226,27 +226,27 @@ getSizeUserData(void *object, int32 offset, int32)
return size; return size;
} }
static int32 int32
add(UserDataExtension *ext, const char *name, int32 datatype, int32 numElements) UserDataExtension::add(const char *name, int32 datatype, int32 numElements)
{ {
int32 i; int32 i;
int32 len; int32 len;
int32 typesz; int32 typesz;
UserDataArray *a; UserDataArray *a;
// try to find empty slot // try to find empty slot
for(i = 0; i < ext->numArrays; i++) for(i = 0; i < this->numArrays; i++)
if(ext->arrays[i].datatype == USERDATANA) if(this->arrays[i].datatype == USERDATANA)
goto alloc; goto alloc;
// have to realloc // have to realloc
a = (UserDataArray*)udMalloc((ext->numArrays+1)*sizeof(UserDataArray)); a = (UserDataArray*)udMalloc((this->numArrays+1)*sizeof(UserDataArray));
if(a == nil) if(a == nil)
return -1; return -1;
memcpy(a, ext->arrays, ext->numArrays*sizeof(UserDataArray)); memcpy(a, this->arrays, this->numArrays*sizeof(UserDataArray));
rwFree(ext->arrays); rwFree(this->arrays);
ext->arrays = a; this->arrays = a;
i = ext->numArrays++; i = this->numArrays++;
alloc: alloc:
a = &ext->arrays[i]; a = &this->arrays[i];
len = (int32)strlen(name)+1; len = (int32)strlen(name)+1;
a->name = (char*)udMalloc(len+1); a->name = (char*)udMalloc(len+1);
assert(a->name); assert(a->name);
@ -262,11 +262,11 @@ alloc:
return i; return i;
} }
static void void
remove(UserDataExtension *ext, int32 n) UserDataExtension::remove(int32 n)
{ {
int32 i; int32 i;
UserDataArray *a = &ext->arrays[n]; UserDataArray *a = &this->arrays[n];
if(a->name){ if(a->name){
rwFree(a->name); rwFree(a->name);
a->name = nil; a->name = nil;
@ -282,39 +282,39 @@ remove(UserDataExtension *ext, int32 n)
a->numElements = 0; 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) \ #define ACCESSOR(TYPE, NAME) \
int32 \ int32 \
UserDataArray::NAME##Add(TYPE *t, const char *name, int32 datatype, int32 numElements) \ UserDataArray::NAME##Add(TYPE *t, const char *name, int32 datatype, int32 numElements) \
{ \ { \
return add(PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset), \ return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->add(name, datatype, numElements); \
name, datatype, numElements); \
} \ } \
void \ void \
UserDataArray::NAME##Remove(TYPE *t, int32 n) \ UserDataArray::NAME##Remove(TYPE *t, int32 n) \
{ \ { \
remove(PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset), n); \ PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->remove(n); \
} \ } \
int32 \ int32 \
UserDataArray::NAME##GetCount(TYPE *t) \ UserDataArray::NAME##GetCount(TYPE *t) \
{ \ { \
return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->numArrays; \ return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->getCount(); \
} \ } \
UserDataArray* \ UserDataArray* \
UserDataArray::NAME##Get(TYPE *t, int32 n) \ UserDataArray::NAME##Get(TYPE *t, int32 n) \
{ \ { \
if(n >= PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->numArrays) \ return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->get(n); \
return nil; \
return &PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->arrays[n]; \
} \ } \
int32 \ int32 \
UserDataArray::NAME##FindIndex(TYPE *t, const char *name) \ UserDataArray::NAME##FindIndex(TYPE *t, const char *name) \
{ \ { \
int32 i; \ return PLUGINOFFSET(UserDataExtension, t, userDataGlobals.NAME##Offset)->findIndex(name); \
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; \
} }
ACCESSOR(Geometry, geometry) ACCESSOR(Geometry, geometry)
@ -324,6 +324,13 @@ ACCESSOR(Light, light)
ACCESSOR(Material, material) ACCESSOR(Material, material)
ACCESSOR(Texture, texture) 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 void
registerUserDataPlugin(void) registerUserDataPlugin(void)
{ {