#include "base.hh"
#include "base_random.hh"
#include "gfx.hh"
#include "eng.hh"
#include "eng_world.hh"
#include "eng_task.hh"
#include "eng_settings.hh"
Namespaces | |
| namespace | eng |
Defines | |
| #define | ENG_WORLD_CC 1 |
| #define | CODE_CORRECT_POSITION_WRAP(XYZ) |
| #define | GET_LOCUS_QUADRANT(QIDX) (gWorld.mQuadrants[QIDX].mQuadrant) |
| #define | MAKE_QUADRANT |
| #define | QUADRANT_AUTO_LOCK() |
Functions | |
| void | eng::ThreadQuadrantPopulate (long quadrant) |
Threading World: ---------------- World is designed to be threadable. Most World methods are reentrant since most data members don't ever change, except mQuadrants[], mObjectCnt. Associated classes such as Quadrants and Locus are critical sections.
Threading Quadrants: -------------------- A thread populates a Quadrant. Every Quadrant has its own lock. Populating a Quadrant may require executing graphics operations, but those can only be executed by the main thread. Therefore, a Quadrant thread will schedule a "task" which the main thread will execute during an idle event. A potential deadlock condition is when the main thread tries to execute a Quadrant method while a thread has it locked, yet the Quadrant thread will need the main thread to execute a task. Deadlock is solved by the main thread calling Thread::RunTasks() and then sleeping while the Quadrant is locked.
Locking: -------- World methods should be reentrant or have minimal locking, since World methods are used by many threads to populate Quadrants. By contrast, almost all Quadrant methods need locking to protect a Quadrant and its BSP while its thread is populating it.
Lazy-allocation of Quadrants: ----------------------------- To support a large mQuadrants[], Quadrants are lazy-allocated rather than pre-allocated. Locus will delete Quadrants that have no Objects.
Destroying zombie Quadrants: ---------------------------- As Locus moves away, a thread might still be populating a thread, or a Dyna was in a Quadrant which prevents deleting it. Such Quadrants become zombies (undeletable). Later, the conditions that prevented deleting them go away, so an idle function destroys them. But, deleting Quadrants (and in turn, BSP and Objects) is slow, so only some zombies are destroyed during one idle event. For fail-safe, if too many zombies accumulate past a threshold, an attempt is made to destroy all of them (impeding program).
Counting Objects in World: -------------------------- Object ctor/dtor count the amount of Objects in World. Counting by the World class proved convoluted.
Sorting and drawing Objects: ---------------------------- Drawing Objects begins by sorting the Quadrants in the Locus according to their distance from the viewpoint. Then, each BSP is drawn by recursing which (in another way) sorts Objects by distance.
| #define CODE_CORRECT_POSITION_WRAP | ( | XYZ | ) |
Value:
if ( pos.XYZ < mBoxVolume.mMin.XYZ ) \ { \ posCorrect.XYZ = mBoxVolume.mMax.XYZ - mMargin; \ } \ else if ( pos.XYZ > mBoxVolume.mMax.XYZ ) \ { \ posCorrect.XYZ = mBoxVolume.mMin.XYZ + mMargin; \ }
| #define ENG_WORLD_CC 1 |
| #define GET_LOCUS_QUADRANT | ( | QIDX | ) | (gWorld.mQuadrants[QIDX].mQuadrant) |
| #define MAKE_QUADRANT |
Value:
/* Skip if Quadrant is outside Locus. */ \ if ( t[XX] >= locusMin[XX] and t[XX] <= locusMax[XX] \ and t[YY] >= locusMin[YY] and t[YY] <= locusMax[YY] \ and t[ZZ] >= locusMin[ZZ] and t[ZZ] <= locusMax[ZZ] ) \ { \ /* Make Quadrant if necessary. */ \ populateQueueIdx = MakeQuadrant( t, populateQueues, populateQueueIdx ); \ \ }
| #define QUADRANT_AUTO_LOCK | ( | ) |
Value:
if ( gThread.IfMain() ) \ { \ /* Just test lock, ok if lock is taken inside clause. */ \ while ( mLock.IfLocked() ) \ { \ Task::GetInstance().RunTasks(); \ gThread.Yield(); \ } \ } \ THREAD_CODE( AutoLock<SlowLock> lock( &mLock ); ) \
Palomino 3D Engine documents generated by doxygen 1.5.3 on Fri Nov 23 11:26:14 2007