From 56e48f4d7641e1d9a1de32c683f0049adf24ad17 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 14 Jan 2016 23:49:00 +0100 Subject: [PATCH] improved uv animation code --- librw.sln | 1 + src/anim.cpp | 138 +++++++++++++++++++++++++------- src/clump.cpp | 69 +++++++--------- src/image.cpp | 13 +-- src/rwobjects.h | 78 +++++++++++++----- tools/insttest/insttest.cpp | 10 +++ tools/insttest/insttest.vcxproj | 4 +- 7 files changed, 211 insertions(+), 102 deletions(-) diff --git a/librw.sln b/librw.sln index 440aafe..8dea99e 100644 --- a/librw.sln +++ b/librw.sln @@ -78,6 +78,7 @@ Global {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.Build.0 = Debug - null|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.ActiveCfg = Debug - null|x64 + {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.Build.0 = Debug - null|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.Build.0 = Debug|x64 diff --git a/src/anim.cpp b/src/anim.cpp index 038b191..31be01c 100644 --- a/src/anim.cpp +++ b/src/anim.cpp @@ -39,16 +39,27 @@ findAnimInterpolatorInfo(int32 id) return NULL; } -Animation::Animation(AnimInterpolatorInfo *interpInfo, int32 numFrames, int32 flags, float duration) +Animation* +Animation::create(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 *anim = (Animation*)malloc(sizeof(*anim)); + anim->interpInfo = interpInfo; + anim->numFrames = numFrames; + anim->flags = flags; + anim->duration = duration; + uint8 *data = new uint8[anim->numFrames*interpInfo->keyFrameSize + interpInfo->customDataSize]; + anim->keyframes = data; + data += anim->numFrames*interpInfo->keyFrameSize; + anim->customData = data; + return anim; +} + +void +Animation::destroy(void) +{ + uint8 *c = (uint8*)this->keyframes; + delete[] c; + free(this); } Animation* @@ -61,7 +72,7 @@ Animation::streamRead(Stream *stream) int32 numFrames = stream->readI32(); int32 flags = stream->readI32(); float duration = stream->readF32(); - anim = new Animation(interpInfo, numFrames, flags, duration); + anim = Animation::create(interpInfo, numFrames, flags, duration); interpInfo->streamRead(stream, anim); return anim; } @@ -74,7 +85,7 @@ Animation::streamReadLegacy(Stream *stream) int32 numFrames = stream->readI32(); int32 flags = stream->readI32(); float duration = stream->readF32(); - anim = new Animation(interpInfo, numFrames, flags, duration); + anim = Animation::create(interpInfo, numFrames, flags, duration); HAnimKeyFrame *frames = (HAnimKeyFrame*)anim->keyframes; for(int32 i = 0; i < anim->numFrames; i++){ stream->read(frames[i].q, 4*4); @@ -129,18 +140,58 @@ AnimInterpolator::AnimInterpolator(Animation *anim) this->anim = anim; } +// +// UVAnim +// + +void +UVAnimCustomData::destroy(Animation *anim) +{ + this->refCount--; + if(this->refCount <= 0) + anim->destroy(); +} + UVAnimDictionary *currentUVAnimDictionary; +UVAnimDictionary* +UVAnimDictionary::create(void) +{ + UVAnimDictionary *dict = (UVAnimDictionary*)malloc(sizeof(*dict)); + dict->animations.init(); + return dict; +} + +void +UVAnimDictionary::destroy(void) +{ + FORLIST(lnk, this->animations){ + UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk); + UVAnimCustomData *cust = (UVAnimCustomData*)de->anim->customData; + cust->destroy(de->anim); + delete de; + } + free(this); +} + +void +UVAnimDictionary::add(Animation *anim) +{ + UVAnimDictEntry *de = new UVAnimDictEntry; + UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; + de->anim = anim; + this->animations.append(&de->inDict); +} + 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++){ + UVAnimDictionary *dict = UVAnimDictionary::create(); + int32 numAnims = stream->readI32(); + for(int32 i = 0; i < numAnims; i++){ assert(findChunk(stream, ID_ANIMANIMATION, NULL, NULL)); - dict->anims[i] = Animation::streamRead(stream); + dict->add(Animation::streamRead(stream)); } return dict; } @@ -151,9 +202,12 @@ 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++) - this->anims[i]->streamWrite(stream); + int32 numAnims = this->count(); + stream->writeI32(numAnims); + FORLIST(lnk, this->animations){ + UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk); + de->anim->streamWrite(stream); + } return true; } @@ -161,16 +215,19 @@ uint32 UVAnimDictionary::streamGetSize(void) { uint32 size = 12 + 4; - for(int32 i = 0; i < this->numAnims; i++) - size += 12 + this->anims[i]->streamGetSize(); + int32 numAnims = this->count(); + FORLIST(lnk, this->animations){ + UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk); + size += 12 + de->anim->streamGetSize(); + } return size; } Animation* UVAnimDictionary::find(const char *name) { - for(int32 i = 0; i < this->numAnims; i++){ - Animation *anim = this->anims[i]; + FORLIST(lnk, this->animations){ + Animation *anim = UVAnimDictEntry::fromDict(lnk)->anim; UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; if(strncmp(custom->name, name, 32) == 0) // strncmp correct? return anim; @@ -186,6 +243,7 @@ uvAnimStreamRead(Stream *stream, Animation *anim) stream->readI32(); stream->read(custom->name, 32); stream->read(custom->nodeToUVChannel, 8*4); + custom->refCount = 1; for(int32 i = 0; i < anim->numFrames; i++){ frames[i].time = stream->readF32(); @@ -262,8 +320,14 @@ destroyUVAnim(void *object, int32 offset, int32) { UVAnim *uvanim; uvanim = PLUGINOFFSET(UVAnim, object, offset); - // TODO: ref counts &c. - (void)uvanim; + for(int32 i = 0; i < 8; i++){ + AnimInterpolator *ip = uvanim->interp[i]; + if(ip){ + UVAnimCustomData *custom = (UVAnimCustomData*)ip->anim->customData; + custom->destroy(ip->anim); + delete ip; + } + } return object; } @@ -273,8 +337,16 @@ 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. + for(int32 i = 0; i < 8; i++){ + AnimInterpolator *srcip = srcuvanim->interp[i]; + AnimInterpolator *dstip; + if(srcip){ + UVAnimCustomData *custom = (UVAnimCustomData*)srcip->anim->customData; + dstip = new AnimInterpolator(srcip->anim); + custom->refCount++; + dstuvanim->interp[i] = dstip; + } + } return dst; } @@ -282,12 +354,13 @@ Animation* makeDummyAnimation(const char *name) { AnimInterpolatorInfo *interpInfo = findAnimInterpolatorInfo(0x1C0); - Animation *anim = new Animation(interpInfo, 2, 0, 1.0f); + Animation *anim = Animation::create(interpInfo, 2, 0, 1.0f); UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; -// UVAnimKeyFrame *frames = (UVAnimKeyFrame*)anim->keyframes; strncpy(custom->name, name, 32); memset(custom->nodeToUVChannel, 0, sizeof(custom->nodeToUVChannel)); + custom->refCount = 1; // TODO: init the frames +// UVAnimKeyFrame *frames = (UVAnimKeyFrame*)anim->keyframes; return anim; } @@ -305,9 +378,14 @@ readUVAnim(Stream *stream, int32, void *object, int32 offset, int32) Animation *anim = NULL; if(currentUVAnimDictionary) anim = currentUVAnimDictionary->find(name); - if(anim == NULL) + if(anim == NULL){ anim = makeDummyAnimation(name); + if(currentUVAnimDictionary) + currentUVAnimDictionary->add(anim); + } + UVAnimCustomData *custom = (UVAnimCustomData*)anim->customData; AnimInterpolator *interp = new AnimInterpolator(anim); + custom->refCount++; uvanim->interp[i] = interp; } bit <<= 1; diff --git a/src/clump.cpp b/src/clump.cpp index 5683b5e..75d450d 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -284,33 +284,6 @@ Clump::destroy(void) free(this); } -int32 -Clump::countAtomics(void) -{ - int32 n = 0; - FORLIST(l, this->atomics) - n++; - return n; -} - -int32 -Clump::countLights(void) -{ - int32 n = 0; - FORLIST(l, this->lights) - n++; - return n; -} - -int32 -Clump::countCameras(void) -{ - int32 n = 0; - FORLIST(l, this->cameras) - n++; - return n; -} - Clump* Clump::streamRead(Stream *stream) { @@ -748,9 +721,10 @@ Light::create(int32 type) assert(light != NULL); light->object.init(Light::ID, type); light->radius = 0.0f; - light->red = 1.0f; - light->green = 1.0f; - light->blue = 1.0f; + light->color.red = 1.0f; + light->color.green = 1.0f; + light->color.blue = 1.0f; + light->color.alpha = 1.0f; light->minusCosAngle = 1.0f; light->object.privateFlags = 1; light->object.flags = LIGHTATOMICS | LIGHTWORLD; @@ -781,9 +755,9 @@ Light::getAngle(void) void Light::setColor(float32 r, float32 g, float32 b) { - this->red = r; - this->green = g; - this->blue = b; + this->color.red = r; + this->color.green = g; + this->color.blue = b; this->object.privateFlags = r == g && r == b; } @@ -824,9 +798,9 @@ Light::streamWrite(Stream *stream) writeChunkHeader(stream, ID_LIGHT, this->streamGetSize()); writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData)); buf.radius = this->radius; - buf.red = this->red; - buf.green = this->green; - buf.blue = this->blue; + buf.red = this->color.red; + buf.green = this->color.green; + buf.blue = this->color.blue; if(version >= 0x30300) buf.minusCosAngle = this->minusCosAngle; else @@ -854,6 +828,12 @@ Camera::create(void) { Camera *cam = (Camera*)malloc(PluginBase::s_size); cam->object.init(Camera::ID, 0); + cam->viewWindow.set(1.0f, 1.0f); + cam->viewOffset.set(0.0f, 0.0f); + cam->nearPlane = 0.05f; + cam->farPlane = 10.0f; + cam->fogPlane = 5.0f; + cam->projection = 1; cam->constructPlugins(); return cam; } @@ -863,6 +843,13 @@ Camera::clone(void) { Camera *cam = Camera::create(); cam->object.copy(&this->object); + cam->setFrame(this->getFrame()); + cam->viewWindow = this->viewWindow; + cam->viewOffset = this->viewOffset; + cam->nearPlane = this->nearPlane; + cam->farPlane = this->farPlane; + cam->fogPlane = this->fogPlane; + cam->projection = this->projection; cam->copyPlugins(this); return cam; } @@ -878,7 +865,7 @@ struct CameraChunkData { V2d viewWindow; V2d viewOffset; - float32 nearClip, farClip; + float32 nearPlane, farPlane; float32 fogPlane; int32 projection; }; @@ -892,8 +879,8 @@ Camera::streamRead(Stream *stream) Camera *cam = Camera::create(); cam->viewWindow = buf.viewWindow; cam->viewOffset = buf.viewOffset; - cam->nearClip = buf.nearClip; - cam->farClip = buf.farClip; + cam->nearPlane = buf.nearPlane; + cam->farPlane = buf.farPlane; cam->fogPlane = buf.fogPlane; cam->projection = buf.projection; cam->streamReadPlugins(stream); @@ -909,8 +896,8 @@ Camera::streamWrite(Stream *stream) writeChunkHeader(stream, ID_STRUCT, sizeof(CameraChunkData)); buf.viewWindow = this->viewWindow; buf.viewOffset = this->viewOffset; - buf.nearClip = this->nearClip; - buf.farClip = this->farClip; + buf.nearPlane = this->nearPlane; + buf.farPlane = this->farPlane; buf.fogPlane = this->fogPlane; buf.projection = this->projection; stream->write(&buf, sizeof(CameraChunkData)); diff --git a/src/image.cpp b/src/image.cpp index 9cfeceb..a161a7f 100755 --- a/src/image.cpp +++ b/src/image.cpp @@ -49,15 +49,6 @@ TexDictionary::destroy(void) free(this); } -int32 -TexDictionary::count(void) -{ - int32 n = 0; - FORLIST(lnk, this->textures) - n++; - return n; -} - Texture* TexDictionary::find(const char *name) { @@ -151,8 +142,10 @@ Texture::read(const char *name, const char *mask) Raster *raster = NULL; Texture *tex; - if(currentTexDictionary && (tex = currentTexDictionary->find(name))) + if(currentTexDictionary && (tex = currentTexDictionary->find(name))){ + tex->refCount++; return tex; + } tex = Texture::create(NULL); strncpy(tex->name, name, 32); strncpy(tex->mask, mask, 32); diff --git a/src/rwobjects.h b/src/rwobjects.h index bad40ae..163b0eb 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -8,14 +8,26 @@ struct RGBA uint8 alpha; }; +struct RGBAf +{ + float32 red; + float32 green; + float32 blue; + float32 alpha; +}; + struct V2d { float32 x, y; + void set(float32 x, float32 y){ + this->x = x; this->y = y; } }; struct V3d { float32 x, y, z; + void set(float32 x, float32 y, float32 z){ + this->x = x; this->y = y; this->z = z; } }; struct LLLink @@ -35,6 +47,12 @@ struct LLLink #define LLLinkGetData(linkvar,type,entry) \ ((type*)(((uint8*)(linkvar))-offsetof(type,entry))) +// Have to be careful since the link might be deleted. +#define FORLIST(_link, _list) \ + for(LLLink *_next = NULL, *_link = (_list).link.next; \ + _next = (_link)->next, (_link) != (_list).end(); \ + (_link) = _next) + struct LinkList { LLLink link; @@ -60,14 +78,14 @@ struct LinkList LLLink *end(void){ return &this->link; } + int32 count(void){ + int32 n = 0; + FORLIST(lnk, (*this)) + n++; + return n; + } }; -// Have to be careful since the link might be deleted. -#define FORLIST(_link, _list) \ - for(LLLink *_next = NULL, *_link = (_list).link.next; \ - _next = (_link)->next, (_link) != (_list).end(); \ - (_link) = _next) - struct Object { uint8 type; @@ -544,7 +562,7 @@ struct Light : PluginBase enum { ID = 3 }; ObjectWithFrame object; float32 radius; - float32 red, green, blue; + RGBAf color; float32 minusCosAngle; // clump link handled by plugin in RW @@ -560,6 +578,7 @@ struct Light : PluginBase void setAngle(float32 angle); float32 getAngle(void); void setColor(float32 r, float32 g, float32 b); + int32 getType(void){ return this->object.subType; } static Light *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); @@ -583,7 +602,7 @@ struct Camera : PluginBase ObjectWithFrame object; V2d viewWindow; V2d viewOffset; - float32 nearClip, farClip; + float32 nearPlane, farPlane; float32 fogPlane; int32 projection; @@ -605,7 +624,7 @@ struct Camera : PluginBase struct Clump : PluginBase { enum { ID = 2 }; - ObjectWithFrame object; + Object object; LinkList atomics; LinkList lights; LinkList cameras; @@ -613,17 +632,17 @@ struct Clump : PluginBase static Clump *create(void); Clump *clone(void); void destroy(void); - int32 countAtomics(void); + int32 countAtomics(void) { return this->atomics.count(); } void addAtomic(Atomic *a){ a->clump = this; this->atomics.append(&a->inClump); } - int32 countLights(void); + int32 countLights(void) { return this->lights.count(); } void addLight(Light *l){ l->clump = this; this->lights.append(&l->inClump); } - int32 countCameras(void); + int32 countCameras(void) { return this->cameras.count(); } void addCamera(Camera *c){ c->clump = this; this->cameras.append(&c->inClump); @@ -648,7 +667,7 @@ struct TexDictionary : PluginBase static TexDictionary *create(void); void destroy(void); - int32 count(void); + int32 count(void) { return this->textures.count(); } void add(Texture *t){ t->dict = this; this->textures.append(&t->inDict); @@ -685,7 +704,8 @@ struct Animation void *keyframes; void *customData; - Animation(AnimInterpolatorInfo*, int32 numFrames, int32 flags, float duration); + static Animation *create(AnimInterpolatorInfo*, int32 numFrames, int32 flags, float duration); + void destroy(void); static Animation *streamRead(Stream *stream); static Animation *streamReadLegacy(Stream *stream); bool streamWrite(Stream *stream); @@ -708,23 +728,43 @@ struct UVAnimKeyFrame float uv[6]; }; +struct UVAnimDictionary; + +// RW does it differently...maybe we should implement RtDict +// and make it more general? + struct UVAnimCustomData { char name[32]; int32 nodeToUVChannel[8]; - // RW has a refcount + int32 refCount; + + void destroy(Animation *anim); }; +// This should be more general probably +struct UVAnimDictEntry +{ + Animation *anim; + LLLink inDict; + static UVAnimDictEntry *fromDict(LLLink *lnk){ + return LLLinkGetData(lnk, UVAnimDictEntry, inDict); } +}; + +// This too struct UVAnimDictionary { - // TODO: linked list probably - int32 numAnims; - Animation **anims; + LinkList animations; + + static UVAnimDictionary *create(void); + void destroy(void); + int32 count(void) { return this->animations.count(); } + void add(Animation *anim); + Animation *find(const char *name); static UVAnimDictionary *streamRead(Stream *stream); bool streamWrite(Stream *stream); uint32 streamGetSize(void); - Animation *find(const char *name); }; extern UVAnimDictionary *currentUVAnimDictionary; diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index 88071c4..93b99e8 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -97,6 +97,8 @@ main(int argc, char *argv[]) //in.open(data, len); StreamFile in; in.open(argv[0], "rb"); + currentUVAnimDictionary = NULL; + currentTexDictionary = TexDictionary::create(); ChunkHeaderInfo header; readChunkHeaderInfo(&in, &header); if(header.type == ID_UVANIMDICT){ @@ -124,6 +126,11 @@ main(int argc, char *argv[]) } } */ + //FORLIST(lnk, c->lights){ + // Light *l = Light::fromClump(lnk); + // printf("%p %p\n", l, lnk); + // printf("%d %f %f %f\n", l->getType(), l->color.red, l->color.green, l->color.blue); + //} int32 platform = findPlatform(c); if(platform){ @@ -185,6 +192,9 @@ main(int argc, char *argv[]) // out.close(); // delete[] data; + if(currentUVAnimDictionary) + currentUVAnimDictionary->destroy(); + //currentTexDictionary->destroy(); c->destroy(); return 0; diff --git a/tools/insttest/insttest.vcxproj b/tools/insttest/insttest.vcxproj index f3390b2..973bd0f 100644 --- a/tools/insttest/insttest.vcxproj +++ b/tools/insttest/insttest.vcxproj @@ -105,7 +105,7 @@ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir) - $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration) + $(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath) $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir) @@ -161,7 +161,7 @@ Disabled true _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebug + MultiThreadedDebugDLL true