mirror of
https://github.com/aap/librw.git
synced 2024-11-28 22:55:42 +00:00
userdata changes; hanim fixes; support for reading old skins
This commit is contained in:
parent
26a5502ee1
commit
171e737842
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
50
src/skin.cpp
50
src/skin.cpp
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user