diff --git a/src/clump.cpp b/src/clump.cpp
index c8c55f3..925ebc1 100644
--- a/src/clump.cpp
+++ b/src/clump.cpp
@@ -18,6 +18,8 @@ using namespace std;
namespace rw {
+LinkList Frame::dirtyList;
+
Frame*
Frame::create(void)
{
@@ -27,15 +29,13 @@ Frame::create(void)
f->objectList.init();
f->child = NULL;
f->next = NULL;
- f->root = NULL;
+ f->root = f;
for(int i = 0; i < 16; i++)
f->matrix[i] = 0.0f;
f->matrix[0] = 1.0f;
f->matrix[5] = 1.0f;
f->matrix[10] = 1.0f;
f->matrix[15] = 1.0f;
- f->matflag = 0;
- f->dirty = true;
f->constructPlugins();
return f;
}
@@ -88,13 +88,15 @@ Frame::destroyHierarchy(void)
Frame*
Frame::addChild(Frame *child, bool32 append)
{
+ Frame *c;
+ if(child->getParent())
+ child->removeChild();
if(append){
if(this->child == NULL)
this->child = child;
else{
- Frame *f;
- for(f = this->child; f->next; f = f->next);
- f->next = child;
+ for(c = this->child; c->next; c = c->next);
+ c->next = child;
}
child->next = NULL;
}else{
@@ -103,6 +105,13 @@ Frame::addChild(Frame *child, bool32 append)
}
child->object.parent = this;
child->root = this->root;
+ for(c = child->child; c; c = c->next)
+ c->setHierarchyRoot(this);
+ if(child->object.privateFlags & Frame::HIERARCHYSYNC){
+ child->inDirtyList.remove();
+ child->object.privateFlags &= ~Frame::HIERARCHYSYNC;
+ }
+ this->updateObjects();
return this;
}
@@ -110,19 +119,19 @@ Frame*
Frame::removeChild(void)
{
Frame *parent = this->getParent();
- if(parent->child == this)
+ Frame *child = parent->child;
+ if(child == this)
parent->child = this->next;
else{
- Frame *f;
- for(f = parent->child; f; f = f->next)
- if(f->next == this)
- goto found;
- // not found
-found:
- f->next = f->next->next;
+ while(child->next != this)
+ child = child->next;
+ child->next = this->next;
}
- this->object.parent = NULL;
- this->next = this->root = NULL;
+ this->object.parent = this->next = NULL;
+ this->root = this;
+ for(child = this->child; child; child = child->next)
+ child->setHierarchyRoot(this);
+ this->updateObjects();
return this;
}
@@ -150,35 +159,53 @@ Frame::count(void)
return count;
}
-void
-Frame::updateLTM(void)
+static void
+syncRecurse(Frame *frame, uint8 flags)
{
- if(!this->dirty)
- return;
- Frame *parent = this->getParent();
- if(parent){
- parent->updateLTM();
- matrixMult(this->ltm, parent->ltm, this->matrix);
- this->dirty = false;
- }else{
- memcpy(this->ltm, this->matrix, 16*4);
- this->dirty = false;
+ uint8 flg;
+ for(; frame; frame = frame->next){
+ flg = flags | frame->object.privateFlags;
+ if(flg & Frame::SUBTREESYNCLTM){
+ matrixMult(frame->ltm, frame->getParent()->ltm, frame->matrix);
+ frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
+ }
+ syncRecurse(frame->child, flg);
}
}
-static Frame*
-dirtyCB(Frame *f, void *)
+void
+Frame::syncHierarchyLTM(void)
{
- f->dirty = true;
- f->forAllChildren(dirtyCB, NULL);
- return f;
+ Frame *child;
+ uint8 flg;
+ if(this->object.privateFlags & Frame::SUBTREESYNCLTM)
+ memcpy(this->ltm, this->matrix, 64);
+ for(child = this->child; child; child = child->next){
+ flg = this->object.privateFlags | child->object.privateFlags;
+ if(flg & Frame::SUBTREESYNCLTM){
+ matrixMult(child->ltm, this->ltm, child->matrix);
+ child->object.privateFlags &= ~Frame::SUBTREESYNCLTM;
+ }
+ syncRecurse(child, flg);
+ }
+ this->object.privateFlags &= ~Frame::SYNCLTM;
+}
+
+float*
+Frame::getLTM(void)
+{
+ if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM)
+ this->root->syncHierarchyLTM();
+ return this->ltm;
}
void
-Frame::setDirty(void)
+Frame::updateObjects(void)
{
- this->dirty = true;
- this->forAllChildren(dirtyCB, NULL);
+ if((this->root->object.privateFlags & HIERARCHYSYNC) == 0)
+ Frame::dirtyList.add(&this->inDirtyList);
+ this->root->object.privateFlags |= HIERARCHYSYNC;
+ this->object.privateFlags |= SUBTREESYNC;
}
void
@@ -493,7 +520,7 @@ Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf)
f->matrix[13] = buf.pos[1];
f->matrix[14] = buf.pos[2];
f->matrix[15] = 1.0f;
- f->matflag = buf.matflag;
+ //f->matflag = buf.matflag;
if(buf.parent >= 0)
frameList[buf.parent]->addChild(f);
}
@@ -533,7 +560,7 @@ Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames)
buf.pos[2] = f->matrix[14];
buf.parent = findPointer(f->getParent(), (void**)frameList,
numFrames);
- buf.matflag = f->matflag;
+ buf.matflag = 0; //f->matflag;
stream->write(&buf, sizeof(buf));
}
for(int32 i = 0; i < numFrames; i++)
@@ -552,6 +579,7 @@ Atomic::create(void)
atomic->object.init(Atomic::ID, 0);
atomic->geometry = NULL;
atomic->pipeline = NULL;
+ atomic->renderCB = Atomic::defaultRenderCB;
atomic->constructPlugins();
// flags:
@@ -670,21 +698,9 @@ Atomic::getPipeline(void)
}
void
-Atomic::init(void)
+Atomic::defaultRenderCB(Atomic *atomic)
{
- ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL);
- for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++)
- defaultPipelines[i] = defpipe;
- defaultPipelines[PLATFORM_PS2] =
- ps2::makeDefaultPipeline();
- defaultPipelines[PLATFORM_OGL] =
- gl::makeDefaultPipeline();
- defaultPipelines[PLATFORM_XBOX] =
- xbox::makeDefaultPipeline();
- defaultPipelines[PLATFORM_D3D8] =
- d3d8::makeDefaultPipeline();
- defaultPipelines[PLATFORM_D3D9] =
- d3d9::makeDefaultPipeline();
+ atomic->getPipeline()->render(atomic);
}
// Atomic Rights plugin
diff --git a/src/image.cpp b/src/image.cpp
index 752c261..788edb7 100755
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -149,7 +149,8 @@ Texture::read(const char *name, const char *mask)
}
tex = Texture::create(NULL);
strncpy(tex->name, name, 32);
- strncpy(tex->mask, mask, 32);
+ if(mask)
+ strncpy(tex->mask, mask, 32);
Image *img = NULL;
if(loadTextures){
char *n = (char*)malloc(strlen(name) + 5);
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index e2f6867..9e27505 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -16,6 +16,8 @@ using namespace std;
namespace rw {
+void (*defaultRenderCBs[rw::NUM_PLATFORMS])(Atomic*);
+
Pipeline::Pipeline(uint32 platform)
{
this->pluginID = 0;
@@ -50,9 +52,10 @@ ObjPipeline::uninstance(Atomic*)
}
void
-ObjPipeline::render(Atomic*)
+ObjPipeline::render(Atomic *atomic)
{
- fprintf(stderr, "This pipeline can't render\n");
+ if(defaultRenderCBs[rw::platform])
+ defaultRenderCBs[rw::platform](atomic);
}
// helper functions
diff --git a/src/ps2raster.cpp b/src/ps2raster.cpp
index f414bb1..7f06f9c 100644
--- a/src/ps2raster.cpp
+++ b/src/ps2raster.cpp
@@ -237,9 +237,8 @@ Ps2Raster::create(Raster *raster)
if(pageWidth*nPagW > raster->width ||
pageHeight*nPagH > raster->height)
ras->tex1[0] = (ras->gsSize >> 6) - 4;
- else{
+ else
ras->tex1[0] = ras->gsSize >> 6;
- }
nPagW = (paletteWidth + palettePagewidth-1)/palettePagewidth;
nPagH = (paletteHeight + palettePageheight-1)/palettePageheight;
ras->gsSize += (nPagW*nPagH*0x800)&~0x7FF;
diff --git a/src/rwbase.cpp b/src/rwbase.cpp
index b20ac3d..9314606 100644
--- a/src/rwbase.cpp
+++ b/src/rwbase.cpp
@@ -5,6 +5,13 @@
#include "rwbase.h"
#include "rwplugin.h"
+#include "rwpipeline.h"
+#include "rwobjects.h"
+#include "rwps2.h"
+#include "rwogl.h"
+#include "rwxbox.h"
+#include "rwd3d8.h"
+#include "rwd3d9.h"
using namespace std;
@@ -23,6 +30,27 @@ int32 build = 0xFFFF;
#endif
char *debugFile = NULL;
+void
+initialize(void)
+{
+ // Atomic pipelines
+ ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL);
+ for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++)
+ defaultPipelines[i] = defpipe;
+ defaultPipelines[PLATFORM_PS2] =
+ ps2::makeDefaultPipeline();
+ defaultPipelines[PLATFORM_OGL] =
+ gl::makeDefaultPipeline();
+ defaultPipelines[PLATFORM_XBOX] =
+ xbox::makeDefaultPipeline();
+ defaultPipelines[PLATFORM_D3D8] =
+ d3d8::makeDefaultPipeline();
+ defaultPipelines[PLATFORM_D3D9] =
+ d3d9::makeDefaultPipeline();
+
+ Frame::dirtyList.init();
+}
+
void
matrixIdentity(float32 *mat)
{
diff --git a/src/rwbase.h b/src/rwbase.h
index fb33218..44977a3 100644
--- a/src/rwbase.h
+++ b/src/rwbase.h
@@ -153,6 +153,8 @@ extern int build;
extern int platform;
extern char *debugFile;
+void initialize(void);
+
void matrixIdentity(float32 *mat);
int matrixEqual(float32 *m1, float32 *m2);
int matrixIsIdentity(float32 *mat);
diff --git a/src/rwobjects.h b/src/rwobjects.h
index 6ad176e..f9c942f 100644
--- a/src/rwobjects.h
+++ b/src/rwobjects.h
@@ -115,9 +115,20 @@ struct Object
struct Frame : PluginBase
{
typedef Frame *(*Callback)(Frame *f, void *data);
-
enum { ID = 0 };
+ enum { // private flags
+ HIERARCHYSYNCLTM = 0x01,
+ HIERARCHYSYNCOBJ = 0x02,
+ HIERARCHYSYNC = HIERARCHYSYNCLTM | HIERARCHYSYNCOBJ,
+ SUBTREESYNCLTM = 0x04,
+ SUBTREESYNCOBJ = 0x08,
+ SUBTREESYNC = SUBTREESYNCLTM | SUBTREESYNCOBJ,
+ SYNCLTM = HIERARCHYSYNCLTM | SUBTREESYNCLTM,
+ SYNCOBJ = HIERARCHYSYNCOBJ | SUBTREESYNCOBJ,
+ };
+
Object object;
+ LLLink inDirtyList;
LinkList objectList;
float32 matrix[16];
float32 ltm[16];
@@ -126,9 +137,7 @@ struct Frame : PluginBase
Frame *next;
Frame *root;
- // temporary
- int32 matflag;
- bool dirty;
+ static LinkList dirtyList;
static Frame *create(void);
Frame *cloneHierarchy(void);
@@ -140,9 +149,10 @@ struct Frame : PluginBase
Frame *getParent(void){
return (Frame*)this->object.parent; }
int32 count(void);
- void updateLTM(void);
- void setDirty(void);
+ float *getLTM(void);
+ void updateObjects(void);
+ void syncHierarchyLTM(void);
void setHierarchyRoot(Frame *root);
Frame *cloneAndLink(Frame *clonedroot);
void purgeClone(void);
@@ -578,12 +588,15 @@ struct Clump;
struct Atomic : PluginBase
{
+ typedef void (*RenderCB)(Atomic *atomic);
enum { ID = 1 };
+
ObjectWithFrame object;
Geometry *geometry;
Clump *clump;
LLLink inClump;
ObjPipeline *pipeline;
+ RenderCB renderCB;
static Atomic *create(void);
Atomic *clone(void);
@@ -598,8 +611,9 @@ struct Atomic : PluginBase
Frame **frameList, int32 numframes);
uint32 streamGetSize(void);
ObjPipeline *getPipeline(void);
+ void render(void) { this->renderCB(this); }
- static void init(void);
+ static void defaultRenderCB(Atomic *atomic);
};
extern ObjPipeline *defaultPipelines[NUM_PLATFORMS];
diff --git a/src/rwpipeline.h b/src/rwpipeline.h
index 6785f9b..e7c8ec7 100644
--- a/src/rwpipeline.h
+++ b/src/rwpipeline.h
@@ -25,11 +25,13 @@ class ObjPipeline : public Pipeline
{
public:
ObjPipeline(uint32 platform) : Pipeline(platform) {}
- virtual void instance(Atomic *atomic);
- virtual void uninstance(Atomic *atomic);
- virtual void render(Atomic *atomic);
+ virtual void instance(Atomic *atomic); // TODO?: make these callbacks instead of virtual
+ virtual void uninstance(Atomic *atomic); // TODO?: make these callbacks instead of virtual
+ virtual void render(Atomic *atomic); // TODO?: make these callbacks instead of virtual
};
+extern void (*defaultRenderCBs[rw::NUM_PLATFORMS])(Atomic*);
+
void findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, int32 *numVertices);
// everything xbox, d3d8 and d3d9 may want to use