improved uv animation code

This commit is contained in:
aap 2016-01-14 23:49:00 +01:00
parent da0417571d
commit 56e48f4d76
7 changed files with 211 additions and 102 deletions

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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<Light>
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<Light>
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<Camera>
ObjectWithFrame object;
V2d viewWindow;
V2d viewOffset;
float32 nearClip, farClip;
float32 nearPlane, farPlane;
float32 fogPlane;
int32 projection;
@ -605,7 +624,7 @@ struct Camera : PluginBase<Camera>
struct Clump : PluginBase<Clump>
{
enum { ID = 2 };
ObjectWithFrame object;
Object object;
LinkList atomics;
LinkList lights;
LinkList cameras;
@ -613,17 +632,17 @@ struct Clump : PluginBase<Clump>
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<TexDictionary>
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;

View File

@ -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;

View File

@ -105,7 +105,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - null|x64'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)</IncludePath>
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)</LibraryPath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)</IncludePath>
@ -161,7 +161,7 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>