// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #include #include #include static const persistentFlags = uniformDiffuse; World::World() : Node(), nrLights(0), lights(0), active(0), flags(lightColourChange|uniformDiffuse) { } World::~World() { } void World::renderHierarchy( Viewport &viewport ) { if (!active) { debug() << "No active camera" << endlog; return; } // Recalculate object-to-camera transformations where necessary. // Inefficient when camera is in motion. active->prepareToRender( viewport ); // A pretty ugly non-recursive traverse... Order isn't important // as we did all the hard stuff in prepareToRender. It is // possible to reunite the two traverses (they split when I added // lighting), maybe later though. Node *x = child; while (x) { while (x->child) { x = x->child; } x->render(viewport, lights, nrLights, flags); while (x) { if (x->next) { x = x->next; break; } x = x->parent; if (x) { x->render(viewport, lights, nrLights, flags); } } } flags &= persistentFlags; } void World::registerLight( Light &l ) { l.nextLight = lights; lights = &l; nrLights++; checkNewLight(l); } void World::unRegisterLight( Light &l ) { if (lights == &l) { lights = l.nextLight; nrLights--; checkRemovedLight(l); return; } Light *c = lights; while (c->nextLight) { if (c->nextLight == &l) { c->nextLight = c->nextLight->nextLight; nrLights--; checkRemovedLight(l); return; } } debug() << "Light not registered for this hierarchy" << endlog; } void World::checkNewLight( const Light& l ) { flags |= lightingChange; if (nrLights <= 1) { flags |= uniformDiffuse; flags |= lightColourChange; } else { if (l.nextLight->diffuse != l.diffuse) { flags &= ~uniformDiffuse; flags |= lightColourChange; } } if (l.ambient.v[R] != 0.0 || l.ambient.v[G] != 0.0 || l.ambient.v[B] != 0.0) { flags |= lightColourChange; } } void World::checkRemovedLight( const Light& ) { if (nrLights <= 1) { flags |= uniformDiffuse; return; } if (!(flags & uniformDiffuse)) { const Light *l = lights->nextLight; while(l) { if (lights->diffuse != l->diffuse) { return; } l = l->nextLight; } flags |= uniformDiffuse; } } void World::setActiveCamera( Camera &c ) { active = &c; }