------------------------ Component Architecture ------------------------ The basic idea behind this architecture is implement a configurable system (scenery things, objects, light sources,...) and implement a flexible message system for a script language. Objects are the basic element, they are created to populate the scenery. In true, they alone, are just general storage things and the engine can do nothing (no visualization, no motion, no light emiting,...) with it. The only thing objects can do is store components and activate them. A component implement some specific object feature: has a poly mesh as body, light source parameters,... Activate the component mean use this feature. Sure, acording each component the result of activation is one. Objects store components in slots. Each slot can be filled only by one component at a time. Each object has how many slots it need, and they are identified by a unique ID, between all slots in his object. When a slot is activated it's component is, too. Any component can be used in any slot. This is the major advantage of this architecture. Like a operacional system has device drivers; objects have components. Is recommended, but not necessary, for who implement this architecture: assign semantic to each slot. For example: the first slot is convensioneted to be used for object move, the second for light emission parameters, the third for visualization data (poly mesh, voxel structure). See examples: Object structure: Object----------------------------------------------+ | | | slot 1 | | slot 2 | | slot 3 | | ... | | slot n | | | +---------------------------------------------------+ Slots are identified by IDs (#define MACRO XX), for example MOTION (has object reference system parameters change), BODY (is the slot where the visible object body is), LIGHT_SOURCE (light the scenery around the object). Object-----------------------------------------------+ | | | slot MOTION | | slot LIGHT_SOURCE | | slot BODY | | ... | | slot n | | | +----------------------------------------------------+ Each slot can be filled by any component. Sure some combinations has bad results. One self move voxel object: Object------------------------------------------------+ | | | slot MOTION -> component script interpreter| | slot LIGHT_SOURCE -> empty | | slot BODY -> component voxel data | | ... | | slot n | | | +-----------------------------------------------------+ When somebody activate slot MOTION, the component in this slot is activated and execute the motion. If the slot LIGHT_SOURCE is activated nothing happens. If the slot BODY is activated it returns a pointer to its data. One camera object, with motion controlled by user: Object-----------------------------------------------+ | | | slot MOTION -> component keyboard read-move | slot LIGHT_SOURCE -> component planar light source | slot BODY -> component mesh (if has a body!) | ... | | slot n | | | +----------------------------------------------------+ Now when slot MOTION is activated the keyboard is read and special actions are performed acording the key press. One scenery static object, with planar light source: Object------------------------------------------+ | | | slot MOTION -> empty | | slot LIGHT_SOURCE -> planar light source | | slot BODY -> component mesh | | ... | | slot n | | | +-----------------------------------------------+ Thinking in a message system, a message is equivalent to activate one slot. --------------------------------------- Component Architecture Implementation --------------------------------------- (General idea about how to implement using C++) The objects are implemented by CObject class. This class has one structure (array or list) of indexed slots. The indexes are used as slots ID. Objects has, too, an activation function (explanation comes latter). Components are just other C++ classes. Each component type has one ID unique between all components. In the examples (above) the MOTION slot are be filled by instances of class CComponentKeyboardRead and CComponentScriptInterpreter. Each slot is a struct with a pointer to void (point the component instance) and the component type ID. The object activation function: CObject::mActivateComponent ( DWORD dwSlotID ) call a specific component function acording the slot to be activated. Seeing more close: mActivateComponent get from the array (or list) of slots, the slot identified by dwSlotID. Then it make a "switch-case" acording the component ID: if the ID is for the CComponentKeyboardRead the slot pointer (to void) is CAST to (CComponentKeyboardRead*) and the component is activated (is called the specific component funtion). The CObject header: class CObject { // one slot struct tagSlot { DWORD dwComponentID; void* poComponentPtr; }; // the object slots tagSlot m_astSlots [ MAXSLOTS ]; // the activation function DWORD mActivateComponent ( DWORD dwSlotID ); }; The real implementation is a bit more complex, but the general idea is that.