From eedf096b392101b59ba964a0ba6a14090881f397 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 9 Sep 2015 23:28:37 +0200 Subject: [PATCH] forgot file --- src/anim.cpp | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 src/anim.cpp diff --git a/src/anim.cpp b/src/anim.cpp new file mode 100644 index 0000000..823da00 --- /dev/null +++ b/src/anim.cpp @@ -0,0 +1,307 @@ +#include +#include +#include +#include + +#include + +#include "rwbase.h" +#include "rwplugin.h" +#include "rwpipeline.h" +#include "rwobjects.h" + +using namespace std; + +namespace rw { + +#define MAXINTERPINFO 10 + +static AnimInterpolatorInfo *interpInfoList[MAXINTERPINFO]; + +void +registerAnimInterpolatorInfo(AnimInterpolatorInfo *interpInfo) +{ + for(int32 i = 0; i < MAXINTERPINFO; i++) + if(interpInfoList[i] == NULL){ + interpInfoList[i] = interpInfo; + return; + } + assert(0 && "no room for interpolatorInfo"); +} + +AnimInterpolatorInfo* +findAnimInterpolatorInfo(int32 id) +{ + for(int32 i = 0; i < MAXINTERPINFO; i++){ + if(interpInfoList[i] && interpInfoList[i]->id == id) + return interpInfoList[i]; + } + return NULL; +} + +Animation::Animation(AnimInterpolatorInfo *interpInfo, int32 numFrames, int32 flags, float duration) +{ + this->interpInfo = interpInfo; + this->numFrames = numFrames; + this->flags = flags; + this->duration = duration; + uint8 *data = new uint8[this->numFrames*interpInfo->keyFrameSize + interpInfo->customDataSize]; + this->keyframes = data; + data += this->numFrames*interpInfo->keyFrameSize; + this->customData = data; +} + +Animation* +Animation::streamRead(Stream *stream) +{ + Animation *anim; + assert(stream->readI32() == 0x100); + int32 typeID = stream->readI32(); + AnimInterpolatorInfo *interpInfo = findAnimInterpolatorInfo(typeID); + int32 numFrames = stream->readI32(); + int32 flags = stream->readI32(); + float duration = stream->readF32(); + anim = new Animation(interpInfo, numFrames, flags, duration); + interpInfo->streamRead(stream, anim); + return anim; +} + +bool +Animation::streamWrite(Stream *stream) +{ + stream->writeI32(0x100); + stream->writeI32(this->interpInfo->id); + stream->writeI32(this->numFrames); + stream->writeI32(this->flags); + stream->writeF32(this->duration); + this->interpInfo->streamWrite(stream, this); + return true; +} + +uint32 +Animation::streamGetSize(void) +{ + uint32 size = 4 + 4 + 4 + 4 + 4; + size += this->interpInfo->streamGetSize(this); + return size; +} + +AnimInterpolator::AnimInterpolator(Animation *anim) +{ + this->anim = anim; +} + +UVAnimDictionary *currentUVAnimDictionary; + +UVAnimDictionary* +UVAnimDictionary::streamRead(Stream *stream) +{ + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + UVAnimDictionary *dict = new UVAnimDictionary; + dict->numAnims = stream->readI32(); + dict->anims = new Animation*[dict->numAnims]; + for(int32 i = 0; i < dict->numAnims; i++){ + assert(findChunk(stream, ID_ANIMANIMATION, NULL, NULL)); + dict->anims[i] = Animation::streamRead(stream); + } + return dict; +} + +bool +UVAnimDictionary::streamWrite(Stream *stream) +{ + uint32 size = this->streamGetSize(); + writeChunkHeader(stream, ID_UVANIMDICT, size); + writeChunkHeader(stream, ID_STRUCT, 4); + stream->writeI32(this->numAnims); + for(int32 i = 0; i < this->numAnims; i++){ + writeChunkHeader(stream, ID_ANIMANIMATION, this->anims[i]->streamGetSize()); + this->anims[i]->streamWrite(stream); + } + return true; +} + +uint32 +UVAnimDictionary::streamGetSize(void) +{ + uint32 size = 12 + 4; + for(int32 i = 0; i < this->numAnims; i++) + size += 12 + this->anims[i]->streamGetSize(); + return size; +} + +Animation* +UVAnimDictionary::find(const char *name) +{ + for(int32 i = 0; i < this->numAnims; i++){ + Animation *anim = this->anims[i]; + UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; + if(strncmp(custom->name, name, 32) == 0) // strncmp correct? + return anim; + } + return NULL; +} + +static void +uvAnimStreamRead(Stream *stream, Animation *anim) +{ + UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; + UVAnimKeyFrame *frames = (UVAnimKeyFrame*)anim->keyframes; + stream->readI32(); + stream->read(custom->name, 32); + stream->read(custom->nodeToUVChannel, 8*4); + + for(int32 i = 0; i < anim->numFrames; i++){ + frames[i].time = stream->readF32(); + stream->read(frames[i].uv, 6*4); + int32 prev = stream->readI32(); + frames[i].prev = &frames[prev]; + } +} + +static void +uvAnimStreamWrite(Stream *stream, Animation *anim) +{ + UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; + UVAnimKeyFrame *frames = (UVAnimKeyFrame*)anim->keyframes; + stream->writeI32(0); + stream->write(custom->name, 32); + stream->write(custom->nodeToUVChannel, 8*4); + + for(int32 i = 0; i < anim->numFrames; i++){ + stream->writeF32(frames[i].time); + stream->write(frames[i].uv, 6*4); + stream->writeI32(frames[i].prev - frames); + } +} + +static uint32 +uvAnimStreamGetSize(Animation *anim) +{ + return 4 + 32 + 8*4 + anim->numFrames*(4 + 6*4 + 4); +} + +static void +registerUVAnimInterpolator(void) +{ + // Linear + AnimInterpolatorInfo *info = new AnimInterpolatorInfo; + info->id = 0x1C0; + info->keyFrameSize = sizeof(UVAnimKeyFrame); + info->customDataSize = sizeof(UVAnimCustomData); + info->streamRead = uvAnimStreamRead; + info->streamWrite = uvAnimStreamWrite; + info->streamGetSize = uvAnimStreamGetSize; + registerAnimInterpolatorInfo(info); + + // Param + info = new AnimInterpolatorInfo; + info->id = 0x1C1; + info->keyFrameSize = sizeof(UVAnimKeyFrame); + info->customDataSize = sizeof(UVAnimCustomData); + info->streamRead = uvAnimStreamRead; + info->streamWrite = uvAnimStreamWrite; + info->streamGetSize = uvAnimStreamGetSize; + registerAnimInterpolatorInfo(info); +} + +int32 uvAnimOffset; + +struct UVAnim +{ + AnimInterpolator *interp[8]; +}; + +static void* +createUVAnim(void *object, int32 offset, int32) +{ + UVAnim *uvanim; + uvanim = PLUGINOFFSET(UVAnim, object, offset); + memset(uvanim, 0, sizeof(*uvanim)); + return object; +} + +static void* +destroyUVAnim(void *object, int32 offset, int32) +{ + UVAnim *uvanim; + uvanim = PLUGINOFFSET(UVAnim, object, offset); + // TODO: ref counts &c. + return object; +} + +static void* +copyUVAnim(void *dst, void *src, int32 offset, int32) +{ + UVAnim *srcuvanim, *dstuvanim; + dstuvanim = PLUGINOFFSET(UVAnim, dst, offset); + srcuvanim = PLUGINOFFSET(UVAnim, src, offset); + memcpy(dstuvanim, srcuvanim, sizeof(*srcuvanim)); + // TODO: ref counts &c. + return dst; +} + +static void +readUVAnim(Stream *stream, int32, void *object, int32 offset, int32) +{ + UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + char name[32]; + uint32 mask = stream->readI32(); + uint32 bit = 1; + for(int32 i = 0; i < 8; i++){ + if(mask & bit){ + stream->read(name, 32); + assert(currentUVAnimDictionary != NULL); + Animation *anim = currentUVAnimDictionary->find(name); + AnimInterpolator *interp = new AnimInterpolator(anim); + uvanim->interp[i] = interp; + } + bit <<= 1; + } +} + +static void +writeUVAnim(Stream *stream, int32 size, void *object, int32 offset, int32) +{ + UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset); + writeChunkHeader(stream, ID_STRUCT, size-12); + uint32 mask = 0; + uint32 bit = 1; + for(int32 i = 0; i < 8; i++){ + if(uvanim->interp[i]) + mask |= bit; + bit <<= 1; + } + stream->writeI32(mask); + for(int32 i = 0; i < 8; i++){ + if(uvanim->interp[i]){ + UVAnimCustomData *custom = + (UVAnimCustomData*)uvanim->interp[i]->anim->customData; + stream->write(custom->name, 32); + } + } +} + +static int32 +getSizeUVAnim(void *object, int32 offset, int32) +{ + UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset); + int32 size = 12 + 4; + for(int32 i = 0; i < 8; i++) + if(uvanim->interp[i]) + size += 32; + return size; +} + + +void +registerUVAnimPlugin(void) +{ + registerUVAnimInterpolator(); + uvAnimOffset = Material::registerPlugin(sizeof(UVAnim), ID_UVANIMATION, + createUVAnim, destroyUVAnim, copyUVAnim); + Material::registerPluginStream(ID_UVANIMATION, readUVAnim, writeUVAnim, getSizeUVAnim); +} + +}