#pragma once #include "ElementRenderer.hpp" #include #include namespace MidLevelRenderer { class MLRLight; class MLRTexture; class MLRShape; } namespace ElementRenderer { class CameraElement; class StateChange; class Element__ClassData; typedef MidLevelRenderer::MLRLight* LightList[MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive]; class CollisionQuery #if defined(_ARMOR) : public Stuff::Signature #endif { public: CollisionQuery(Stuff::Line3D *l, Stuff::Normal3D *n): m_line(l), m_normal(n), m_data(NULL) {Check_Pointer(this);} Stuff::Line3D *m_line; Stuff::Normal3D *m_normal; void *m_data; BYTE m_material; void TestInstance() const {} }; class SphereTest #if defined(_ARMOR) : public Stuff::Signature #endif { public: enum TestCase { Disjoint=0, Intersects=1, Contains=2, Contained=4 }; Stuff::Sphere m_sphere; int m_type; void TestInstance() const {} }; //######################################################################### //########################### Element ################################### //######################################################################### class _declspec(novtable) Element: public Stuff::Plug { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Initialization // public: static void InitializeClass(); static void TerminateClass(); typedef Element__ClassData ClassData; static ClassData *DefaultData; typedef Stuff::Plug BaseClass; static Stuff::RGBAColor FadeColor; typedef MidLevelRenderer::MLRShape* (*ShapeHolder)( Stuff::MemoryStream *stream, int version, int length ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructors/Destructors // protected: Element(ClassData *class_data); explicit Element( ClassData *class_data, Element *element ); Element( ClassData *class_data, Stuff::MemoryStream *stream, int version ); public: ~Element(); typedef Element* (*Factory)( Stuff::MemoryStream *stream, int version, ShapeHolder shapes ); virtual void Save(Stuff::MemoryStream *stream); static Element* Create( Stuff::MemoryStream *stream, int version, ShapeHolder shapes=NULL ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Testing // public: void TestInstance(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Hierarchy // public: Element* GetParentElement() {Check_Object(this); return m_parent;} void DetachFromParent() { Check_Object(this); Check_Object(m_parent); m_parent->DetachChild(this); Verify(!m_parent); } void AttachToParent(Element *parent) { Check_Object(this); Check_Object(parent); Verify(!m_parent); parent->AttachChild(this); Check_Object(m_parent); } virtual void AttachChild(Element *child)=0; virtual void DetachChild(Element *child)=0; void SetClientData(void *data) {Check_Object(this); m_data = data;} void* GetClientData() {Check_Object(this); return m_data;} protected: static void SetParentElement( Element *child, Element *parent ) {Check_Object(child); child->m_parent = parent;} Element *m_parent; void *m_data; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // States // public: enum { LocalToParentIsIdentityBit = 0, BoundsLockedBit, SyncStateBit, MatrixDirtyBit = SyncStateBit, BoundsWrongBit, SyncOnCullBit, CullStateBit, OBBBit = CullStateBit, CullBit, CullBits = 2, AlignXBit = CullBit+CullBits, SyncStateBits = AlignXBit - SyncStateBit, AlignYBit = AlignXBit+1, DrawStateBit, CullStateBits = DrawStateBit - CullStateBit, PropertyChangeBit = DrawStateBit, DrawStateBits = 1, CallbackBit = DrawStateBit+1, CallbackBits = 3, NoShadowBit = CallbackBit+CallbackBits }; enum { LocalToParentIsIdentityFlag = 1<> (Stuff::INT_BITS - SyncStateBits), SyncStateCount = 1<> (Stuff::INT_BITS - CullBits)) << CullBit, RootMode = 0, VolumeCullMode = 1<> (Stuff::INT_BITS - CullStateBits), CullStateCount = 1<> (Stuff::INT_BITS - DrawStateBits), DrawStateCount = 1<> (Stuff::INT_BITS - CallbackBits)) << CallbackBit, NoShadowFlag = 1<*m_sync)(); } protected: virtual void SetSyncState(); SyncMethod m_sync; static SyncMethod SyncMethods[SyncStateCount]; Stuff::LinearMatrix4D m_newLocalToParent, m_localToParent, m_localToWorld; void NoneSyncMethod(); void DirtyRootSyncMethod(); void DeferSyncMethod(); void CleanSyncMethod(); void DirtySyncMethod(); void CleanSphereSyncMethod(); void DirtySphereSyncMethod(); void CleanOBBSyncMethod(); void DirtyOBBSyncMethod(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Culling // public: typedef int (Element::*CameraCullMethod)(CameraElement *camera); typedef bool (Element::*RayCullMethod)(CollisionQuery *query); typedef int (Element::*SphereTestMethod)(SphereTest *test); struct CullMethod { CameraCullMethod m_cameraCull; RayCullMethod m_rayCull; SphereTestMethod m_sphereTest; }; int Cull(CameraElement *camera) { Check_Object(this); Check_Pointer(camera); Verify(m_cameraCull != NULL); return (this->*m_cameraCull)(camera); } const Stuff::OBB& GetWorldOBB() {Check_Object(this); return m_worldOBB;} Stuff::OBB m_localOBB; protected: Stuff::OBB m_worldOBB; virtual void SetCullState(); CameraCullMethod m_cameraCull; RayCullMethod m_rayCull; SphereTestMethod m_sphereTest; static CullMethod CullMethods[CullStateCount]; int NeverCullMethod(CameraElement *camera); int AlwaysCullMethod(CameraElement *camera); int SphereCullMethod(CameraElement *camera); int OBBCullMethod(CameraElement *camera); void AlignX(CameraElement *camera); int DeferredXNeverCullMethod(CameraElement *camera); int DeferredXAlwaysCullMethod(CameraElement *camera); int DeferredXSphereCullMethod(CameraElement *camera); int DeferredXOBBCullMethod(CameraElement *camera); void AlignY(CameraElement *camera); int DeferredYNeverCullMethod(CameraElement *camera); int DeferredYAlwaysCullMethod(CameraElement *camera); int DeferredYSphereCullMethod(CameraElement *camera); int DeferredYOBBCullMethod(CameraElement *camera); void AlignXY(CameraElement *camera); int DeferredXYNeverCullMethod(CameraElement *camera); int DeferredXYAlwaysCullMethod(CameraElement *camera); int DeferredXYSphereCullMethod(CameraElement *camera); int DeferredXYOBBCullMethod(CameraElement *camera); bool NeverRayCullMethod(CollisionQuery *query); bool AlwaysRayCullMethod(CollisionQuery *query); bool SphereRayCullMethod(CollisionQuery *query); bool OBBRayCullMethod(CollisionQuery *query); int NeverSphereTestMethod(SphereTest *test); int AlwaysSphereTestMethod(SphereTest *test); int SphereSphereTestMethod(SphereTest *test); int OBBSphereTestMethod(SphereTest *test); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Collision // public: bool CastRay(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(m_rayCull != NULL); if ((this->*m_rayCull)(query)) return CastCulledRay(query); return false; } Element* FindSmallestElementContaining(SphereTest *test) { Check_Object(this); Check_Object(test); Verify(m_sphereTest != NULL); Verify(test->m_type == SphereTest::Contains); if (((this->*m_sphereTest)(test)&SphereTest::Contains) != 0) return FindSmallestElementContainingCulled(test); return NULL; } protected: virtual bool CastCulledRay(CollisionQuery *query)=0; virtual Element* FindSmallestElementContainingCulled(SphereTest *test)=0; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Drawing // public: typedef void (Element::*DrawMethod)( CameraElement *camera, const StateChange *inherited_state, int culling_state ); void DrawTo( CameraElement *camera, const StateChange *inherited_state, int culling_state ) { Check_Object(this); Check_Pointer(camera); Verify(m_draw != NULL); (this->*m_draw)( camera, inherited_state, culling_state ); } virtual int CountTriangles()=0; static int MixLights( LightList new_lights, const LightList parent_lights, const LightList child_lights ); virtual void CleanDamage(); virtual void ApplyDamage( const Stuff::LinearMatrix4D &damage_spot, Stuff::Scalar radius ); virtual void ApplyDamageDecal( const Stuff::LinearMatrix4D &damage_spot, Stuff::Scalar radius, MidLevelRenderer::MLRTexture *texture ); virtual void CastShadow( const Stuff::LinearMatrix4D &shadow_to_world, const Stuff::UnitVector3D &sun_in_world, Stuff::Scalar radius ); virtual void MakeFootStep( MidLevelRenderer::MLRShape *shape, const Stuff::LinearMatrix4D &foot, Stuff::Scalar radius, MidLevelRenderer::MLRTexture *tex ); virtual MidLevelRenderer::MLRShape* GetMLRShape(CameraElement *camera=NULL) {Check_Object(this); return NULL;} virtual void GetCoordData(Stuff::DynamicArrayOf *array); protected: virtual void SetDrawState()=0; DrawMethod m_draw; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Debugging aids // public: typedef void (*Callback)( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); enum { DrawGreenBounds=1, DrawYellowBounds, DrawRedBounds, DrawGreenBoundsOnce, DrawYellowBoundsOnce, DrawRedBoundsOnce }; void SetCallbackIndex(unsigned function) { Check_Object(this); Verify(function < 1<>CallbackBit;} static Callback* GetCallbackSet() {return CallbackSet;} static void UseCallbackSet(Callback *callback) {CallbackSet = callback;} static void DrawOBB( const Stuff::OBB& obb, const Stuff::RGBAColor& color, CameraElement *camera, const StateChange *state, int culling_state ); static void DrawSphere( const Stuff::OBB& obb, const Stuff::RGBAColor& color, CameraElement *camera, const StateChange *state, int culling_state ); static void DrawGreenBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static void DrawYellowBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static void DrawRedBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static void DrawGreenBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static void DrawYellowBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static void DrawRedBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ); static Callback Callbacks[1<(&t::s##SyncMethod) #define CULL_METHOD(t, c, r)\ {\ static_cast(&t::c##CullMethod),\ static_cast(&t::r##RayCullMethod),\ static_cast(&t::r##SphereTestMethod)\ } #define DRAW_METHOD(t, d) static_cast(&t::d##DrawMethod) //########################################################################## //####################### Element__ClassData ######################### //########################################################################## class Element__ClassData: public Stuff::Plug__ClassData { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // public: Element__ClassData( Stuff::RegisteredClass::ClassID class_id, const char* class_name, Stuff::Plug__ClassData *parent_class, Element::Factory element_factory ): RegisteredClass__ClassData(class_id, class_name, parent_class), m_elementFactory(element_factory) {} Element::Factory m_elementFactory; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // public: void TestInstance(); }; }