diff --git a/src/camera.cpp b/src/camera.cpp index 6901dee..66e2fbe 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "rwbase.h" #include "rwerror.h" @@ -331,6 +332,9 @@ Camera::clone(void) cam->frameBuffer = this->frameBuffer; cam->zBuffer = this->zBuffer; + if(this->world) + this->world->addCamera(cam); + s_plglist.copy(cam, this); return cam; } @@ -339,8 +343,8 @@ void Camera::destroy(void) { s_plglist.destruct(this); - if(this->clump) - this->inClump.remove(); + assert(this->clump == nil); + assert(this->world == nil); rwFree(this); numAllocated--; } diff --git a/src/clump.cpp b/src/clump.cpp index e164875..974b4c0 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "rwbase.h" #include "rwerror.h" @@ -36,6 +37,11 @@ Clump::create(void) clump->atomics.init(); clump->lights.init(); clump->cameras.init(); + + // World extension + clump->world = nil; + clump->inWorld.init(); + s_plglist.construct(clump); return clump; } @@ -53,6 +59,11 @@ Clump::clone(void) clump->addAtomic(atomic); } root->purgeClone(); + + // World extension + if(this->world) + this->world->addClump(clump); + s_plglist.copy(clump, this); return clump; } @@ -62,18 +73,77 @@ Clump::destroy(void) { Frame *f; s_plglist.destruct(this); - FORLIST(lnk, this->atomics) - Atomic::fromClump(lnk)->destroy(); - FORLIST(lnk, this->lights) - Light::fromClump(lnk)->destroy(); - FORLIST(lnk, this->cameras) - Camera::fromClump(lnk)->destroy(); + FORLIST(lnk, this->atomics){ + Atomic *a = Atomic::fromClump(lnk); + this->removeAtomic(a); + a->destroy(); + } + FORLIST(lnk, this->lights){ + Light *l = Light::fromClump(lnk); + this->removeLight(l); + l->destroy(); + } + FORLIST(lnk, this->cameras){ + Camera *c = Camera::fromClump(lnk); + this->removeCamera(c); + c->destroy(); + } if(f = this->getFrame(), f) f->destroyHierarchy(); + assert(this->world == nil); rwFree(this); numAllocated--; } +void +Clump::addAtomic(Atomic *a) +{ + assert(a->clump == nil); + a->clump = this; + this->atomics.append(&a->inClump); +} + +void +Clump::removeAtomic(Atomic *a) +{ + assert(a->clump == this); + a->inClump.remove(); + a->clump = nil; +} + +void +Clump::addLight(Light *l) +{ + assert(l->clump == nil); + l->clump = this; + this->lights.append(&l->inClump); +} + +void +Clump::removeLight(Light *l) +{ + assert(l->clump == this); + l->inClump.remove(); + l->clump = nil; +} + +void +Clump::addCamera(Camera *c) +{ + assert(c->clump == nil); + c->clump = this; + this->cameras.append(&c->inClump); +} + +void +Clump::removeCamera(Camera *c) +{ + assert(c->clump == this); + c->inClump.remove(); + c->clump = nil; +} + + Clump* Clump::streamRead(Stream *stream) { @@ -357,6 +427,7 @@ Atomic::create(void) atomic->setFrame(nil); atomic->object.object.privateFlags |= WORLDBOUNDDIRTY; atomic->clump = nil; + atomic->inClump.init(); atomic->pipeline = nil; atomic->renderCB = Atomic::defaultRenderCB; atomic->object.object.flags = Atomic::COLLISIONTEST | Atomic::RENDER; @@ -383,6 +454,9 @@ Atomic::clone() atomic->setGeometry(this->geometry, 0); atomic->renderCB = this->renderCB; atomic->pipeline = this->pipeline; + + // World extension doesn't add to world + s_plglist.copy(atomic, this); return atomic; } @@ -393,22 +467,13 @@ Atomic::destroy(void) s_plglist.destruct(this); if(this->geometry) this->geometry->destroy(); - if(this->clump) - this->inClump.remove(); + assert(this->clump == nil); + assert(this->world == nil); this->setFrame(nil); rwFree(this); numAllocated--; } -void -Atomic::removeFromClump(void) -{ - if(this->clump){ - this->inClump.remove(); - this->clump = nil; - } -} - void Atomic::setGeometry(Geometry *geo, uint32 flags) { diff --git a/src/light.cpp b/src/light.cpp index 4283c81..b61362d 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "rwbase.h" #include "rwerror.h" @@ -66,9 +67,8 @@ void Light::destroy(void) { s_plglist.destruct(this); - if(this->clump) - this->inClump.remove(); - // we do not remove from world, be careful + assert(this->clump == nil); + assert(this->world == nil); rwFree(this); numAllocated--; } diff --git a/src/rwobjects.h b/src/rwobjects.h index e01fc2a..68eb4cc 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -537,7 +537,6 @@ struct Atomic Frame *getFrame(void) const { return (Frame*)this->object.object.parent; } static Atomic *fromClump(LLLink *lnk){ return LLLinkGetData(lnk, Atomic, inClump); } - void removeFromClump(void); void setGeometry(Geometry *geo, uint32 flags); Sphere *getWorldBoundingSphere(void); ObjPipeline *getPipeline(void); @@ -704,27 +703,24 @@ struct Clump LinkList cameras; World *world; + LLLink inWorld; static int32 numAllocated; static Clump *create(void); Clump *clone(void); void destroy(void); + static Clump *fromWorld(LLLink *lnk){ + return LLLinkGetData(lnk, Clump, inWorld); } int32 countAtomics(void) { return this->atomics.count(); } - void addAtomic(Atomic *a){ - a->clump = this; - this->atomics.append(&a->inClump); - } + void addAtomic(Atomic *a); + void removeAtomic(Atomic *a); int32 countLights(void) { return this->lights.count(); } - void addLight(Light *l){ - l->clump = this; - this->lights.append(&l->inClump); - } + void addLight(Light *l); + void removeLight(Light *l); int32 countCameras(void) { return this->cameras.count(); } - void addCamera(Camera *c){ - c->clump = this; - this->cameras.append(&c->inClump); - } + void addCamera(Camera *c); + void removeCamera(Camera *c); void setFrame(Frame *f){ this->object.parent = f; } Frame *getFrame(void) const { @@ -743,6 +739,7 @@ struct World Object object; LinkList lights; // these have positions (type >= 0x80) LinkList directionalLights; // these do not (type < 0x80) + LinkList clumps; static int32 numAllocated; @@ -752,6 +749,11 @@ struct World void removeLight(Light *light); void addCamera(Camera *cam); void removeCamera(Camera *cam); + void addAtomic(Atomic *atomic); + void removeAtomic(Atomic *atomic); + void addClump(Clump *clump); + void removeClump(Clump *clump); + void render(void); }; struct TexDictionary diff --git a/src/world.cpp b/src/world.cpp index 126714f..f724a5d 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "rwbase.h" #include "rwerror.h" @@ -29,6 +30,7 @@ World::create(void) world->object.init(World::ID, 0); world->lights.init(); world->directionalLights.init(); + world->clumps.init(); s_plglist.construct(world); return world; } @@ -64,6 +66,7 @@ World::removeLight(Light *light) void World::addCamera(Camera *cam) { + assert(cam->world == nil); cam->world = this; if(cam->getFrame()) cam->getFrame()->updateObjects(); @@ -76,4 +79,61 @@ World::removeCamera(Camera *cam) cam->world = nil; } +void +World::addAtomic(Atomic *atomic) +{ + assert(atomic->world == nil); + atomic->world = this; + if(atomic->getFrame()) + atomic->getFrame()->updateObjects(); +} + +void +World::removeAtomic(Atomic *atomic) +{ + assert(atomic->world == this); + atomic->world = nil; +} + +void +World::addClump(Clump *clump) +{ + assert(clump->world == nil); + clump->world = this; + this->clumps.add(&clump->inWorld); + FORLIST(lnk, clump->atomics) + this->addAtomic(Atomic::fromClump(lnk)); + FORLIST(lnk, clump->lights) + this->addLight(Light::fromClump(lnk)); + FORLIST(lnk, clump->cameras) + this->addCamera(Camera::fromClump(lnk)); + + if(clump->getFrame()){ + clump->getFrame()->matrix.optimize(); + clump->getFrame()->updateObjects(); + } +} + +void +World::removeClump(Clump *clump) +{ + assert(clump->world == this); + clump->inWorld.remove(); + FORLIST(lnk, clump->atomics) + this->removeAtomic(Atomic::fromClump(lnk)); + FORLIST(lnk, clump->lights) + this->removeLight(Light::fromClump(lnk)); + FORLIST(lnk, clump->cameras) + this->removeCamera(Camera::fromClump(lnk)); + clump->world = nil; +} + +void +World::render(void) +{ + // this is very wrong, we really want world sectors + FORLIST(lnk, this->clumps) + Clump::fromWorld(lnk)->render(); +} + }