#include "ElementRendererHeaders.hpp" #include //############################################################################ //############################## Element ################################### //############################################################################ ElementRenderer::Element::ClassData* ElementRenderer::Element::DefaultData = NULL; ElementRenderer::Element::SyncMethod ElementRenderer::Element::SyncMethods[SyncStateCount]= { // // Root mode // SYNC_METHOD(Element, None), SYNC_METHOD(Element, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Stuff::Sphere Cull // SYNC_METHOD(Element, CleanSphere), SYNC_METHOD(Element, DirtySphere), SYNC_METHOD(Element, CleanSphere), SYNC_METHOD(Element, DirtySphere), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Stuff::OBB Cull // SYNC_METHOD(Element, CleanOBB), SYNC_METHOD(Element, DirtyOBB), SYNC_METHOD(Element, CleanOBB), SYNC_METHOD(Element, DirtyOBB), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Never Cull // SYNC_METHOD(Element, Clean), SYNC_METHOD(Element, Dirty), SYNC_METHOD(Element, Clean), SYNC_METHOD(Element, Dirty), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, Clean), SYNC_METHOD(Element, Dirty), SYNC_METHOD(Element, Clean), SYNC_METHOD(Element, Dirty), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Always Cull // SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None), SYNC_METHOD(Element, None) }; ElementRenderer::Element::CullMethod ElementRenderer::Element::CullMethods[CullStateCount]= { // // No billboarding // CULL_METHOD(Element, Never, Never), CULL_METHOD(Element, Never, Never), CULL_METHOD(Element, Sphere, Sphere), CULL_METHOD(Element, OBB, OBB), CULL_METHOD(Element, Never, Never), CULL_METHOD(Element, Never, Never), CULL_METHOD(Element, Always, Always), CULL_METHOD(Element, Always, Always), // // Billboarding around X // CULL_METHOD(Element, DeferredXNever, Never), CULL_METHOD(Element, DeferredXNever, Never), CULL_METHOD(Element, DeferredXSphere, Sphere), CULL_METHOD(Element, DeferredXOBB, OBB), CULL_METHOD(Element, DeferredXNever, Never), CULL_METHOD(Element, DeferredXNever, Never), CULL_METHOD(Element, DeferredXAlways, Always), CULL_METHOD(Element, DeferredXAlways, Always), // // Billboarding around Y // CULL_METHOD(Element, DeferredYNever, Never), CULL_METHOD(Element, DeferredYNever, Never), CULL_METHOD(Element, DeferredYSphere, Sphere), CULL_METHOD(Element, DeferredYOBB, OBB), CULL_METHOD(Element, DeferredYNever, Never), CULL_METHOD(Element, DeferredYNever, Never), CULL_METHOD(Element, DeferredYAlways, Always), CULL_METHOD(Element, DeferredYAlways, Always), // // Billboarding around X and Y // CULL_METHOD(Element, DeferredXYNever, Never), CULL_METHOD(Element, DeferredXYNever, Never), CULL_METHOD(Element, DeferredXYSphere, Sphere), CULL_METHOD(Element, DeferredXYOBB, OBB), CULL_METHOD(Element, DeferredXYNever, Never), CULL_METHOD(Element, DeferredXYNever, Never), CULL_METHOD(Element, DeferredXYAlways, Always), CULL_METHOD(Element, DeferredXYAlways, Always) }; Stuff::RGBAColor ElementRenderer::Element::FadeColor; ElementRenderer::Element::Callback* ElementRenderer::Element::CallbackSet = NULL; ElementRenderer::Element::Callback ElementRenderer::Element::Callbacks[1<Add(cube); cube->DetachReference(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::TerminateClass() { Box_Object->DetachReference(); Box_Object = NULL; Sphere_Object->DetachReference(); Sphere_Object = NULL; Check_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element::Element(ClassData *class_data): Plug(class_data) { Check_Pointer(this); Check_Object(class_data); // //-------------------------------- // Initialize the member variables //-------------------------------- // m_data = NULL; m_parent = NULL; m_worldOBB.localToParent = m_localOBB.localToParent = Stuff::LinearMatrix4D::Identity; m_localOBB.axisExtents = Stuff::Vector3D::Identity; m_localOBB.sphereRadius = 0.0f; m_worldOBB.axisExtents = Stuff::Vector3D::Identity; m_worldOBB.sphereRadius = -1.0f; m_newLocalToParent = Stuff::LinearMatrix4D::Identity; m_localToParent = Stuff::LinearMatrix4D::Identity; m_localToWorld = Stuff::LinearMatrix4D::Identity; m_stateChange = NULL; // //---------------------------- // Now set the method handlers //---------------------------- // m_state = RootMode | MatrixDirtyFlag | LocalToParentIsIdentityFlag; unsigned sync_state = (m_state>>SyncStateBit)&SyncStateMask; Verify(sync_state < SyncStateCount); m_sync = SyncMethods[sync_state]; unsigned cull_state = (m_state>>CullStateBit)&CullStateMask; Verify(cull_state < CullStateCount); m_cameraCull = CullMethods[cull_state].m_cameraCull; m_rayCull = CullMethods[cull_state].m_rayCull; m_sphereTest = CullMethods[cull_state].m_sphereTest; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element::Element( ClassData *class_data, Element *element ): Plug(class_data) { Check_Pointer(this); Check_Object(class_data); // //-------------------------------- // Initialize the member variables //-------------------------------- // m_data = NULL; m_parent = NULL; m_localOBB = element->m_localOBB; m_worldOBB.localToParent = Stuff::LinearMatrix4D::Identity; m_worldOBB.axisExtents = Stuff::Vector3D::Identity; m_worldOBB.sphereRadius = -1.0f; m_newLocalToParent = element->m_newLocalToParent; m_localToParent = element->m_localToParent; m_localToWorld = element->m_localToWorld; if (element->m_stateChange) { m_stateChange = new StateChange(*element->m_stateChange); Check_Object(m_stateChange); } else m_stateChange = NULL; // //---------------------------- // Now set the method handlers //---------------------------- // m_state = element->m_state; m_state &= ~CullMask; m_state |= RootMode | MatrixDirtyFlag; unsigned sync_state = (m_state>>SyncStateBit)&SyncStateMask; Verify(sync_state < SyncStateCount); m_sync = SyncMethods[sync_state]; unsigned cull_state = (m_state>>CullStateBit)&CullStateMask; Verify(cull_state < CullStateCount); m_cameraCull = CullMethods[cull_state].m_cameraCull; m_rayCull = CullMethods[cull_state].m_rayCull; m_sphereTest = CullMethods[cull_state].m_sphereTest; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element::Element( ClassData *class_data, Stuff::MemoryStream *stream, int version ): Plug(class_data) { Check_Pointer(this); Check_Object(class_data); Check_Object(stream); // //-------------------------------- // Initialize the member variables //-------------------------------- // m_data = NULL; m_parent = NULL; m_localToParent = Stuff::LinearMatrix4D::Identity; m_localToWorld = Stuff::LinearMatrix4D::Identity; m_stateChange = NULL; m_worldOBB.localToParent = Stuff::LinearMatrix4D::Identity; m_worldOBB.axisExtents = Stuff::Vector3D::Identity; m_worldOBB.sphereRadius = -1.0f; // //---------------------------------------------------------------------- // Read mask and element state. If we are reading something from before // version 6, make room for the new locked flag //---------------------------------------------------------------------- // if (version < 7) { int collision_mask; *stream >> collision_mask; } *stream >> m_state; if (version < 6) m_state = (m_state&1) | ((m_state << 1)&0xFFFFFFFC); // //------------------------------ // Read the StateChange and name //------------------------------ // if (m_state & PropertyChangeFlag) { m_stateChange = new StateChange(stream, version); Check_Object(m_stateChange); } if (version < 12) { Stuff::MString name; *stream >> name; } if (!IsLocalToParentIdentity()) *stream >> m_newLocalToParent; else m_newLocalToParent = Stuff::LinearMatrix4D::Identity; // //------------------------- // Read the bounding volume //------------------------- // if (IsBoundedByOBB()) { *stream >> m_localOBB.localToParent >> m_localOBB.axisExtents >> m_localOBB.sphereRadius; } else { Stuff::Point3D center; *stream >> center; m_localOBB.localToParent = Stuff::LinearMatrix4D::Identity; m_localOBB.localToParent.BuildTranslation(center); m_localOBB.axisExtents = Stuff::Vector3D::Identity; *stream >> m_localOBB.sphereRadius; } // //---------------------------- // Now set the method handlers //---------------------------- // m_state |= MatrixDirtyFlag; unsigned sync_state = (m_state>>SyncStateBit)&SyncStateMask; Verify(sync_state < SyncStateCount); m_sync = SyncMethods[sync_state]; unsigned cull_state = (m_state>>CullStateBit)&CullStateMask; Verify(cull_state < CullStateCount); m_cameraCull = CullMethods[cull_state].m_cameraCull; m_rayCull = CullMethods[cull_state].m_rayCull; m_sphereTest = CullMethods[cull_state].m_sphereTest; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element::~Element() { Check_Object(this); // //------------------- // Unhook from parent //------------------- // if (m_parent) { Check_Object(m_parent); m_parent->DetachChild(this); } // //-------------------------- // Unhook the properties set //-------------------------- // if (m_stateChange) { Check_Object(m_stateChange); delete m_stateChange; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element* ElementRenderer::Element::Create( Stuff::MemoryStream *stream, int version, ShapeHolder shapes ) { RegisteredClass::ClassID class_id; *stream >> class_id; ClassData* class_data = Cast_Pointer(ClassData*, FindClassData(class_id)); Check_Object(class_data); Element *child = (*class_data->m_elementFactory)(stream, version, shapes); Check_Object(child); return child; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::Save(Stuff::MemoryStream *stream) { Check_Pointer(this); Check_Object(stream); // //-------------------------- // Write stuff to the stream //-------------------------- // *stream << static_cast(GetClassID()) << m_state; if (m_stateChange) { Check_Object(m_stateChange); Verify(m_state & PropertyChangeFlag); m_stateChange->Save(stream); } if (!IsLocalToParentIdentity()) *stream << m_localToParent; // //-------------------------- // Write the bounding volume //-------------------------- // if (IsBoundedByOBB()) { *stream << m_localOBB.localToParent << m_localOBB.axisExtents << m_localOBB.sphereRadius; } else { Stuff::Point3D center(m_localOBB.localToParent); *stream << center; *stream << m_localOBB.sphereRadius; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::TestInstance() { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::ReadStateFromPage( Stuff::Page *page, const Stuff::MString &prefix, unsigned *state, unsigned *delta, Stuff::OBB *bounds ) { Check_Object(&prefix); Check_Object(page); Check_Pointer(state); Check_Pointer(bounds); // //------------------------ // Is it an identity state //------------------------ // *delta = 0; bool identity; if (page->GetEntry(prefix+"LocalToParentIsIdentity", &identity)) { if (identity) *state |= LocalToParentIsIdentityFlag; else *state &= ~LocalToParentIsIdentityFlag; } // //--------------------------- // Is there a bounding sphere //--------------------------- // const char* sphere = NULL; if (page->GetEntry(prefix+"BoundingSphere", &sphere)) { *state &= ~OBBFlag; *delta |= OBBFlag; bounds->localToParent = Stuff::LinearMatrix4D::Identity; Check_Pointer(sphere); #if defined(_ARMOR) int count= #endif sscanf( sphere, "%f %f %f %f", &bounds->localToParent(3,0), &bounds->localToParent(3,1), &bounds->localToParent(3,2), &bounds->sphereRadius ); Verify(count == 4); bounds->axisExtents = Stuff::Vector3D::Identity; *state |= BoundsLockedFlag; *delta |= BoundsLockedFlag; } // //------------------------ // Is there a bounding Stuff::OBB //------------------------ // else { const char* obb = NULL; if (page->GetEntry(prefix+"Stuff::OBB", &obb)) { *state |= OBBFlag; *delta |= OBBFlag; Stuff::YawPitchRoll rotation; Check_Pointer(obb); sscanf( obb, "%f %f %f %f %f %f %f %f %f", &bounds->localToParent(3,0), &bounds->localToParent(3,1), &bounds->localToParent(3,2), &rotation.yaw.angle, &rotation.pitch.angle, &rotation.roll.angle, &bounds->axisExtents.x, &bounds->axisExtents.y, &bounds->axisExtents.z ); rotation.yaw *= Stuff::Radians_Per_Degree; rotation.pitch *= Stuff::Radians_Per_Degree; rotation.roll *= Stuff::Radians_Per_Degree; bounds->localToParent.BuildRotation(rotation); bounds->sphereRadius = bounds->axisExtents.GetLength(); *state |= BoundsLockedFlag; *delta |= BoundsLockedFlag; } // //---------------------------------------------------------------- // Otherwise, there is no Stuff::OBB, so clear out everything and set the // radius to -1 //---------------------------------------------------------------- // else { bounds->localToParent = Stuff::LinearMatrix4D::Identity; bounds->axisExtents = Stuff::Vector3D::Identity; bounds->sphereRadius = -1.0f; } } // //------------------ // Get the cull mode //------------------ // const char* cull_mode = NULL; if (page->GetEntry(prefix+"Cull", &cull_mode)) { *state &= ~CullMask; *delta |= CullMask; Check_Pointer(cull_mode); if (!_stricmp(cull_mode, "VolumeCull")) *state |= VolumeCullMode; else if (!_stricmp(cull_mode, "AlwaysCull")) { *state |= AlwaysCullMode|BoundsLockedFlag; *delta |= BoundsLockedFlag; } else if (!_stricmp(cull_mode, "NeverCull")) { *state |= NeverCullMode|BoundsLockedFlag; *delta |= BoundsLockedFlag; } else Verify(!_stricmp(cull_mode, "RootCull")); } // //------------------------ // Look for the align bits //------------------------ // bool align_x; if (page->GetEntry(prefix+"AlignZUsingX", &align_x)) { if (align_x) { *state |= AlignXFlag|SyncOnCullFlag; *delta |= AlignXFlag|SyncOnCullFlag; } } bool align_y; if (page->GetEntry(prefix+"AlignZUsingY", &align_y)) { if (align_y) { *state |= AlignYFlag|SyncOnCullFlag; *delta |= AlignYFlag|SyncOnCullFlag; } } bool shadow; if (page->GetEntry(prefix+"DisableShadow", &shadow)) { if (shadow) { *state |= NoShadowFlag; *delta |= NoShadowFlag; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::SetSyncState() { Check_Object(this); Verify( GetCullMode() != VolumeCullMode || AreBoundsWrong() || IsSyncDeferred() || ( m_localOBB.sphereRadius>0.0f && (IsMatrixDirty() || m_worldOBB.sphereRadius>0.0f ) ) ); Verify( GetCullMode() == RootMode || m_parent != NULL || AreBoundsWrong() ); unsigned sync_state = (m_state>>SyncStateBit)&SyncStateMask; Verify(sync_state < SyncStateCount); m_sync = SyncMethods[sync_state]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::NoneSyncMethod() { Check_Object(this); SYNC_LOGIC("None::Element"); MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DirtyRootSyncMethod() { Check_Object(this); Verify(IsMatrixDirty() && GetCullMode() == RootMode); SYNC_LOGIC("Root::Dirty::Element"); // //------------------------------------- // Copy the matrix and reset the method //------------------------------------- // m_localToWorld = m_localToParent = m_newLocalToParent; MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DeferSyncMethod() { Check_Object(this); Verify(IsMatrixDirty()); SYNC_LOGIC("Defer::Element"); // //------------------------------------- // Copy the matrix and reset the method //------------------------------------- // m_localToParent = m_newLocalToParent; MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::CleanSyncMethod() { Check_Object(this); Verify(!IsMatrixDirty() && GetCullMode()==NeverCullMode); SYNC_LOGIC("Clean::Element"); // //------------------------------------------------------------------ // Concatenated our m_localToWorld from m_localToParent and our parent's // m_localToWorld //------------------------------------------------------------------ // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DirtySyncMethod() { Check_Object(this); Verify(IsMatrixDirty() && GetCullMode()==NeverCullMode); SYNC_LOGIC("Dirty::Element"); // //------------------------------------- // Copy the matrix and reset the method //------------------------------------- // m_localToParent = m_newLocalToParent; Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::CleanSphereSyncMethod() { Check_Object(this); Verify(m_localOBB.sphereRadius > 0.0f); Verify( !IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); SYNC_LOGIC("Sphere::Clean::Element"); // //------------------------------------------------------------------ // Concatenated our m_localToWorld from m_localToParent and our parent's // m_localToWorld //------------------------------------------------------------------ // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //------------------------------ // Transform the bounding sphere //------------------------------ // m_worldOBB.MultiplySphereOnly(m_localOBB, m_localToWorld); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DirtySphereSyncMethod() { Check_Object(this); Verify(m_localOBB.sphereRadius > 0.0f); Verify( IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); SYNC_LOGIC("Sphere::Dirty::Element"); // //------------------------------------- // Copy the matrix and reset the method //------------------------------------- // m_localToParent = m_newLocalToParent; // //------------------------------------------------------------------ // Concatenated our m_localToWorld from m_localToParent and our parent's // m_localToWorld //------------------------------------------------------------------ // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //------------------------------ // Transform the bounding sphere //------------------------------ // m_worldOBB.MultiplySphereOnly(m_localOBB, m_localToWorld); MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::CleanOBBSyncMethod() { Check_Object(this); Verify( !IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); SYNC_LOGIC("OBB::Clean::Element"); // //------------------------------------------------------------------ // Concatenated our m_localToWorld from m_localToParent and our parent's // m_localToWorld //------------------------------------------------------------------ // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //------------------------------ // Transform the bounding sphere //------------------------------ // m_worldOBB.Multiply(m_localOBB, m_localToWorld); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DirtyOBBSyncMethod() { Check_Object(this); Verify( IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); SYNC_LOGIC("OBB::Dirty::Element"); // //------------------------------------- // Copy the matrix and reset the method //------------------------------------- // m_localToParent = m_newLocalToParent; // //------------------------------------------------------------------ // Concatenated our m_localToWorld from m_localToParent and our parent's // m_localToWorld //------------------------------------------------------------------ // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //------------------------------ // Transform the bounding sphere //------------------------------ // m_worldOBB.Multiply(m_localOBB, m_localToWorld); MatrixIsClean(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::SetCullState() { Check_Object(this); unsigned cull_state = (m_state>>CullStateBit)&CullStateMask; Verify(cull_state < CullStateCount); m_cameraCull = CullMethods[cull_state].m_cameraCull; m_rayCull = CullMethods[cull_state].m_rayCull; m_sphereTest = CullMethods[cull_state].m_sphereTest; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::NeverCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); return 0x2f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::AlwaysCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty() && GetCullMode()==AlwaysCullMode); return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::SphereCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(m_worldOBB.sphereRadius > 0.0f); Verify( !IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); // //------------------------------- // We only use the sphere portion //------------------------------- // int cull_state = 0; Stuff::Point3D center(m_worldOBB.localToParent); // //----------------------------------------------------------------------- // Run each of the camera bounding planes against the sphere. First find // the distance from the sphere center point to the bounding plane //----------------------------------------------------------------------- // const Stuff::Plane* plane = &camera->GetWorldCullingPlane(0); for (int i=0; iGetDistanceTo(center); // //------------------------------------------------------------------- // Now, if this distance is greater than the sphere radius, we have a // trivial reject //------------------------------------------------------------------- // if (distance >= m_worldOBB.sphereRadius) return -1; // //---------------------------------------------------------------------- // Make room in the clip state for this plane result, then if the center // is not more than the radius away from the plane, it will need // culling by this plane //---------------------------------------------------------------------- // cull_state <<= 1; if (distance > -m_worldOBB.sphereRadius) cull_state |= 1; } if (!cull_state) camera->m_acceptingElement = this; return cull_state; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::OBBCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); // //------------------------------------------------------------------------ // We will be testing the planes inside the matrix, so compute the inverse //------------------------------------------------------------------------ // Stuff::LinearMatrix4D parent_to_local; parent_to_local.Invert(m_worldOBB.localToParent); // //----------------------------------------------------------------------- // Run each of the camera bounding planes against the sphere. First find // the distance from the sphere center point to the bounding plane //----------------------------------------------------------------------- // Stuff::Point3D inside_extents, outside_extents; int cull_state = 0; const Stuff::Plane* plane = &camera->GetWorldCullingPlane(0); for (int i=0; i 0.0f) { inside_extents.x = -m_worldOBB.axisExtents.x; outside_extents.x = m_worldOBB.axisExtents.x; } else { inside_extents.x = m_worldOBB.axisExtents.x; outside_extents.x = -m_worldOBB.axisExtents.x; } if (local_plane.normal.y > 0.0f) { inside_extents.y = -m_worldOBB.axisExtents.y; outside_extents.y = m_worldOBB.axisExtents.y; } else { inside_extents.y = m_worldOBB.axisExtents.y; outside_extents.y = -m_worldOBB.axisExtents.y; } if (local_plane.normal.z > 0.0f) { inside_extents.z = -m_worldOBB.axisExtents.z; outside_extents.z = m_worldOBB.axisExtents.z; } else { inside_extents.z = m_worldOBB.axisExtents.z; outside_extents.z = -m_worldOBB.axisExtents.z; } // //------------------------------------------------------------------- // Now, if this distance is greater than the sphere radius, we have a // trivial reject //------------------------------------------------------------------- // Stuff::Scalar distance = local_plane.GetDistanceTo(inside_extents); if (distance > 0.0f) return -1; // //---------------------------------------------------------------------- // Make room in the clip state for this plane result, then if the center // is not more than the radius away from the plane, it will need // culling by this plane //---------------------------------------------------------------------- // distance = local_plane.GetDistanceTo(outside_extents); cull_state <<= 1; if (distance > 0.0f) cull_state |= 1; } if (!cull_state) camera->m_acceptingElement = this; return cull_state; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::AlignX(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); // //---------------------------------------------------------------------- // We have to move the camera into the same parent space as the local // matrix will be in, then figure out the relative direction the element // should face //---------------------------------------------------------------------- // Check_Object(m_parent); Stuff::Point3D world_camera(camera->GetLocalToWorld()); Stuff::Point3D parent_camera; parent_camera.MultiplyByInverse( world_camera, m_parent->GetLocalToWorld() ); Stuff::Vector3D camera_direction; Stuff::Point3D local_origin(m_newLocalToParent); camera_direction.Subtract(parent_camera, local_origin); // //------------------------------------------------------------------------ // Now align the matrix in the direction we wish it to point, then set the // matrix inside the element and sync //------------------------------------------------------------------------ // m_newLocalToParent.AlignLocalAxisToWorldVector(camera_direction, Stuff::Z_Axis, Stuff::X_Axis, -1); // //------------------------------------------------------------------------ // In order for the sync to work properly, we have to disable the deferred // bit for the actual sync, then re-enable it afterwords. After the sync, // do the standard sphere cull //------------------------------------------------------------------------ // m_state &= ~(SyncOnCullFlag|LocalToParentIsIdentityFlag); m_state |= MatrixDirtyFlag; SetSyncState(); Sync(); m_state |= SyncOnCullFlag; SetSyncState(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXNeverCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); AlignX(camera); return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXAlwaysCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty() && GetCullMode()==AlwaysCullMode); AlignX(camera); return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXSphereCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); AlignX(camera); return SphereCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXOBBCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); AlignX(camera); return OBBCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::AlignY(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); // //---------------------------------------------------------------------- // We have to move the camera into the same parent space as the local // matrix will be in, then figure out the relative direction the element // should face //---------------------------------------------------------------------- // Check_Object(m_parent); Stuff::Point3D world_camera(camera->GetLocalToWorld()); Stuff::Point3D parent_camera; parent_camera.MultiplyByInverse( world_camera, m_parent->GetLocalToWorld() ); Stuff::Vector3D camera_direction; Stuff::Point3D local_origin(m_newLocalToParent); camera_direction.Subtract(parent_camera, local_origin); // //------------------------------------------------------------------------ // Now align the matrix in the direction we wish it to point, then set the // matrix inside the element and sync //------------------------------------------------------------------------ // m_newLocalToParent.AlignLocalAxisToWorldVector(camera_direction, Stuff::Z_Axis, Stuff::Y_Axis, -1); // //------------------------------------------------------------------------ // In order for the sync to work properly, we have to disable the deferred // bit for the actual sync, then re-enable it afterwords. After the sync, // do the standard sphere cull //------------------------------------------------------------------------ // m_state &= ~(SyncOnCullFlag|LocalToParentIsIdentityFlag); m_state |= MatrixDirtyFlag; SetSyncState(); Sync(); m_state |= SyncOnCullFlag; SetSyncState(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredYNeverCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); AlignY(camera); return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredYAlwaysCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty() && GetCullMode()==AlwaysCullMode); AlignY(camera); return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredYSphereCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); AlignY(camera); return SphereCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredYOBBCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); AlignY(camera); return OBBCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::AlignXY(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); // //---------------------------------------------------------------------- // We have to move the camera into the same parent space as the local // matrix will be in, then figure out the relative direction the element // should face //---------------------------------------------------------------------- // Check_Object(m_parent); Stuff::Point3D world_camera(camera->GetLocalToWorld()); Stuff::Point3D parent_camera; parent_camera.MultiplyByInverse( world_camera, m_parent->GetLocalToWorld() ); Stuff::Vector3D camera_direction; Stuff::Point3D local_origin(m_newLocalToParent); camera_direction.Subtract(parent_camera, local_origin); // //------------------------------------------------------------------------ // Now align the matrix in the direction we wish it to point, then set the // matrix inside the element and sync //------------------------------------------------------------------------ // Stuff::LinearMatrix4D old_pos = m_newLocalToParent; m_newLocalToParent.AlignLocalAxisToWorldVector(camera_direction, Stuff::Z_Axis, Stuff::Y_Axis, Stuff::X_Axis); // //------------------------------------------------------------------------ // In order for the sync to work properly, we have to disable the deferred // bit for the actual sync, then re-enable it afterwords. After the sync, // do the standard sphere cull //------------------------------------------------------------------------ // m_state &= ~(SyncOnCullFlag|LocalToParentIsIdentityFlag); m_state |= MatrixDirtyFlag; SetSyncState(); Sync(); m_state |= SyncOnCullFlag; SetSyncState(); m_newLocalToParent = old_pos; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXYNeverCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty()); AlignXY(camera); return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXYAlwaysCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify(!IsMatrixDirty() && GetCullMode()==AlwaysCullMode); AlignXY(camera); return -1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXYSphereCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedBySphere() && GetCullMode()==VolumeCullMode ); AlignXY(camera); return SphereCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::DeferredXYOBBCullMethod(CameraElement *camera) { Check_Object(this); Check_Object(camera); Verify( !IsMatrixDirty() && IsBoundedByOBB() && GetCullMode()==VolumeCullMode ); AlignXY(camera); return OBBCullMethod(camera); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ElementRenderer::Element::NeverRayCullMethod(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode() == NeverCullMode || GetCullMode() == RootMode); Verify(!query->m_data); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ElementRenderer::Element::AlwaysRayCullMethod(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode() == AlwaysCullMode); Verify(!query->m_data); return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ElementRenderer::Element::SphereRayCullMethod(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(m_worldOBB.sphereRadius > 0.0f); Verify(GetCullMode()==VolumeCullMode && IsBoundedBySphere()); Verify(!query->m_data); // //------------------------------- // We only use the sphere portion //------------------------------- // Stuff::Sphere sphere(m_worldOBB); Stuff::Scalar penetration; Check_Object(query->m_line); return query->m_line->GetDistanceTo(sphere, &penetration) >= 0.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ElementRenderer::Element::OBBRayCullMethod(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode()==VolumeCullMode && IsBoundedByOBB()); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); Verify(!query->m_data); // //------------------------------- // We only use the sphere portion //------------------------------- // Check_Object(query->m_line); return query->m_line->GetDistanceTo(m_worldOBB) >= 0.0f; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::NeverSphereTestMethod(SphereTest *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode() == NeverCullMode || GetCullMode() == RootMode); return query->m_type; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::AlwaysSphereTestMethod(SphereTest *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode() == AlwaysCullMode); return SphereTest::Disjoint; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::SphereSphereTestMethod(SphereTest *query) { Check_Object(this); Check_Object(query); Verify(m_worldOBB.sphereRadius > 0.0f); Verify(GetCullMode()==VolumeCullMode && IsBoundedBySphere()); // //------------------------------- // We only use the sphere portion //------------------------------- // Stuff::Sphere sphere(m_worldOBB); Stuff::Vector3D diff; diff.Subtract(sphere.center, query->m_sphere.center); int result = SphereTest::Disjoint; Stuff::Scalar range = diff.GetLengthSquared(); Stuff::Scalar slop; switch (query->m_type) { case SphereTest::Contains: slop = sphere.radius - query->m_sphere.radius; if (slop >= 0.0f) { if (range <= slop*slop) result = SphereTest::Contains; } break; case SphereTest::Intersects: slop = sphere.radius + query->m_sphere.radius; if (range <= slop*slop) result = SphereTest::Intersects; break; case SphereTest::Contained: slop = sphere.radius - query->m_sphere.radius; if (slop <= 0.0f) { if (range <= slop*slop) result = SphereTest::Contained; } break; default: slop = sphere.radius + query->m_sphere.radius; if (range <= slop*slop) { result |= SphereTest::Intersects; slop = sphere.radius - query->m_sphere.radius; if (slop >= 0.0f) { if (range <= slop*slop) result |= SphereTest::Contains; } if (slop <= 0.0f) { if (range <= slop*slop) result |= SphereTest::Contained; } } break; } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::OBBSphereTestMethod(SphereTest *query) { Check_Object(this); Check_Object(query); Verify(GetCullMode()==VolumeCullMode && IsBoundedByOBB()); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); STOP(("Not implemented")); return SphereTest::Disjoint; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int ElementRenderer::Element::MixLights( LightList new_lights, const LightList parent_lights, const LightList child_lights ) { unsigned i; for (i=0; iGetMLRState(); info.state.SetTextureHandle(0); info.state.SetAlphaMode(MidLevelRenderer::MLRState::AlphaInvAlphaMode); info.state.SetZBufferWriteOff(); info.state.SetPriority(1); info.state.SetFogMode(0); Check_Object(Box_Object); info.shape = Box_Object; info.scaling = &obb.axisExtents; // //--------------- // Draw the shape //--------------- // MidLevelRenderer::MLRClipper *clipper = camera->GetClipper(); Check_Object(clipper); clipper->DrawScalableShape(&info); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawSphere( const Stuff::OBB& obb, const Stuff::RGBAColor &color, CameraElement *camera, const StateChange *state, int culling_state ) { Check_Object(&obb); Check_Object(&color); Check_Object(camera); Check_Object(state); // //------------------ // Set up the fields //------------------ // MidLevelRenderer::DrawScalableShapeInformation info; info.clippingFlags.SetClippingState(culling_state); info.shapeToWorld = &obb.localToParent; info.worldToShape = NULL; info.paintMeColor = &color; info.state = state->GetMLRState(); info.state.SetTextureHandle(0); info.state.SetAlphaMode(MidLevelRenderer::MLRState::AlphaInvAlphaMode); info.state.SetZBufferWriteOff(); info.state.SetPriority(1); info.state.SetFogMode(0); Verify(Stuff::Small_Enough(obb.axisExtents.GetLengthSquared())); Stuff::Vector3D scale; Check_Object(Sphere_Object); info.shape = Sphere_Object; info.scaling = &scale; scale.x = scale.y = scale.z = obb.sphereRadius; // //--------------- // Draw the shape //--------------- // MidLevelRenderer::MLRClipper *clipper = camera->GetClipper(); Check_Object(clipper); clipper->DrawScalableShape(&info); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawGreenBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //------------------ // Draw green bounds //------------------ // Stuff::RGBAColor color(0.5f, 1.0f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawYellowBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //------------------- // Draw yellow bounds //------------------- // Stuff::RGBAColor color(1.0f, 1.0f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawRedBoundsCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //---------------- // Draw red bounds //---------------- // Stuff::RGBAColor color(1.0f, 0.5f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawGreenBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //------------------ // Draw green bounds //------------------ // Stuff::RGBAColor color(0.5f, 1.0f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); element->SetCallbackIndex(0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawYellowBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //------------------- // Draw yellow bounds //------------------- // Stuff::RGBAColor color(1.0f, 1.0f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); element->SetCallbackIndex(0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DrawRedBoundsOnceCallback( CameraElement *camera, const StateChange *state, int culling_state, Element *element ) { Check_Object(camera); Check_Object(state); Check_Object(element); // //---------------------------------- // Only volume cull bounds are shown //---------------------------------- // if (element->GetCullMode() != VolumeCullMode) return; // //---------------- // Draw red bounds //---------------- // Stuff::RGBAColor color(1.0f, 0.5f, 0.5f, 0.3f); if (element->IsBoundedBySphere()) DrawSphere(element->m_worldOBB, color, camera, state, culling_state); else DrawOBB(element->m_worldOBB, color, camera, state, culling_state); element->SetCallbackIndex(0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::AdoptStateChange(StateChange *set) { Check_Object(this); Check_Object(set); // //-------------------------------------------- // Detach the old property set if it was there //-------------------------------------------- // if (m_stateChange) { Check_Object(m_stateChange); delete m_stateChange; } // //---------------------------- // Attach the new property set //---------------------------- // m_stateChange = set; m_state |= PropertyChangeFlag; SetDrawState(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::Element::DestroyStateChange() { Check_Object(this); // //-------------------------------------------- // Detach the old property set if it was there //-------------------------------------------- // if (m_stateChange) { Check_Object(m_stateChange); delete m_stateChange; m_stateChange = NULL; m_state &= ~PropertyChangeFlag; SetDrawState(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Returns array of vertex coordinates and number of vertices void ElementRenderer::Element::GetCoordData( Stuff::DynamicArrayOf *array) { Check_Object(this); array->SetLength(0); } //############################################################################# //########################## Element__ClassData ######################### //############################################################################# void ElementRenderer::Element__ClassData::TestInstance() { Verify(IsDerivedFrom(ElementRenderer::Element::DefaultData)); }