#include "ElementRendererHeaders.hpp" //############################################################################ //############################ SwitchElement ################################ //############################################################################ HGOSHEAP ElementRenderer::SwitchElement::s_Heap = NULL; ElementRenderer::SwitchElement::ClassData* ElementRenderer::SwitchElement::DefaultData = NULL; ElementRenderer::Element::SyncMethod ElementRenderer::SwitchElement::SyncMethods[SyncStateCount]= { // // Root mode // SYNC_METHOD(SwitchElement, CleanRoot), SYNC_METHOD(SwitchElement, DirtyRoot), SYNC_METHOD(SwitchElement, CleanRoot), SYNC_METHOD(SwitchElement, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(SwitchElement, CleanRoot), SYNC_METHOD(SwitchElement, DirtyRoot), SYNC_METHOD(SwitchElement, CleanRoot), SYNC_METHOD(SwitchElement, DirtyRoot), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Sphere Cull // SYNC_METHOD(SwitchElement, CleanSphere), SYNC_METHOD(SwitchElement, MatrixDirtySphere), SYNC_METHOD(SwitchElement, BoundsWrongSphere), SYNC_METHOD(SwitchElement, FullSphere), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // OBB Cull // SYNC_METHOD(SwitchElement, CleanOBB), SYNC_METHOD(SwitchElement, MatrixDirtyOBB), SYNC_METHOD(SwitchElement, BoundsWrongOBB), SYNC_METHOD(SwitchElement, FullOBB), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), // // Never Cull // SYNC_METHOD(SwitchElement, Clean), SYNC_METHOD(SwitchElement, Dirty), SYNC_METHOD(SwitchElement, Clean), SYNC_METHOD(SwitchElement, Dirty), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(Element, None), SYNC_METHOD(Element, Defer), SYNC_METHOD(SwitchElement, Clean), SYNC_METHOD(SwitchElement, Dirty), SYNC_METHOD(SwitchElement, Clean), SYNC_METHOD(SwitchElement, 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::DrawMethod ElementRenderer::SwitchElement::DrawMethods[DrawStateCount]= { DRAW_METHOD(SwitchElement, Inherit), DRAW_METHOD(SwitchElement, Override), }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::InitializeClass() { Verify(!s_Heap); s_Heap = gos_CreateMemoryHeap("Switch", 0, g_LibraryHeap); Check_Pointer(s_Heap); Verify(!DefaultData); DefaultData = new ClassData( SwitchElementClassID, "ElementRenderer::SwitchElement", BaseClass::DefaultData, reinterpret_cast(&Make) ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; Check_Pointer(s_Heap); gos_DestroyMemoryHeap(s_Heap); s_Heap = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::SwitchElement::SwitchElement( ClassData *class_data, Stuff::MemoryStream *stream, int version, ShapeHolder shapes ): ListElement(class_data, stream, version, shapes) { Check_Pointer(this); Check_Object(stream); unsigned index = (m_state>>SyncStateBit) & SyncStateMask; Verify(index < SyncStateCount); m_sync = SyncMethods[index]; index = (m_state>>CullStateBit) & CullStateMask; Verify(index < CullStateCount); m_cameraCull = CullMethods[index].m_cameraCull; m_rayCull = CullMethods[index].m_rayCull; m_sphereTest = CullMethods[index].m_sphereTest; index = (m_state>>DrawStateBit) & DrawStateMask; Verify(index < DrawStateCount); m_draw = DrawMethods[index]; // //--------------------------------- // Create the shape from the stream //--------------------------------- // Verify(m_list.GetLength() < 65536); *stream >> m_switch; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::SwitchElement::SwitchElement(ClassData *class_data): ListElement(class_data) { Check_Pointer(this); unsigned index = (m_state>>SyncStateBit) & SyncStateMask; Verify(index < SyncStateCount); m_sync = SyncMethods[index]; index = (m_state>>CullStateBit) & CullStateMask; Verify(index < CullStateCount); m_cameraCull = CullMethods[index].m_cameraCull; m_rayCull = CullMethods[index].m_rayCull; m_sphereTest = CullMethods[index].m_sphereTest; index = (m_state>>DrawStateBit) & DrawStateMask; Verify(index < DrawStateCount); m_draw = DrawMethods[index]; m_switch = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::SwitchElement::~SwitchElement() { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::SwitchElement* ElementRenderer::SwitchElement::Make( Stuff::MemoryStream *stream, int version, ShapeHolder shapes ) { Check_Object(stream); gos_PushCurrentHeap(s_Heap); SwitchElement *element = new SwitchElement(DefaultData, stream, version, shapes); gos_PopCurrentHeap(); return element; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::Save(Stuff::MemoryStream *stream) { Check_Object(this); Check_Object(stream); BaseClass::Save(stream); // //-------------------- // Save each Switch entry //-------------------- // *stream << m_switch; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::TestInstance() { Verify(!AreBoundsLocked()); Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::SetSize(WORD max_size) { Check_Object(this); BaseClass::SetSize(max_size); m_switch = max_size; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::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 index = (m_state>>SyncStateBit) & SyncStateMask; Verify(index < SyncStateCount); m_sync = SyncMethods[index]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::SetDrawState() { Check_Object(this); unsigned index = (m_state>>DrawStateBit) & DrawStateMask; Verify(index < DrawStateCount); m_draw = DrawMethods[index]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CleanRootSyncMethod() { Check_Object(this); Verify(!IsMatrixDirty() && GetCullMode()==RootMode); SYNC_LOGIC("Root::Clean::Switch"); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::DirtyRootSyncMethod() { Check_Object(this); Verify(IsMatrixDirty() && GetCullMode()==RootMode); SYNC_LOGIC("Root::Dirty::Switch"); // //------------------------------------------------------ // If the local-to-parent matrix is dirty, make it clean //------------------------------------------------------ // m_localToWorld = m_localToParent = m_newLocalToParent; MatrixIsClean(); CleanRootSyncMethod(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CleanSyncMethod() { Check_Object(this); Verify(!IsMatrixDirty() && GetCullMode()==NeverCullMode); SYNC_LOGIC("Clean::Switch"); // //------------------------------- // Update our m_localToWorld matrix //------------------------------- // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::DirtySyncMethod() { Check_Object(this); Verify(IsMatrixDirty() && GetCullMode()==NeverCullMode); SYNC_LOGIC("Dirty::Switch"); // //-------------------- // Update our matrices //-------------------- // 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(); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CleanSphereSyncMethod() { Check_Object(this); Verify(m_localOBB.sphereRadius > 0.0f); Verify( !IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedBySphere() ); SYNC_LOGIC("Sphere::Clean::Switch"); // //------------------------------- // Update our m_localToWorld matrix //------------------------------- // 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); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::MatrixDirtySphereSyncMethod() { Check_Object(this); Verify(m_localOBB.sphereRadius > 0.0f); Verify( IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedBySphere() ); SYNC_LOGIC("Sphere::Dirty::Switch"); // //-------------------- // Update our matrices //-------------------- // m_localToParent = m_newLocalToParent; 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(); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::BoundsWrongSphereSyncMethod() { Check_Object(this); Verify( !IsMatrixDirty() && AreBoundsWrong() && GetCullMode()==VolumeCullMode && IsBoundedBySphere() ); SYNC_LOGIC("Sphere::Recalc::Switch"); // //------------------------------- // Update our m_localToWorld matrix //------------------------------- // Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //-------------------- // Update our children //-------------------- // WORD i; Verify(m_list.GetLength() < 65536); WORD switch_count = static_cast(m_list.GetLength()); Stuff::Point3D centroid = Stuff::Point3D::Identity; WORD bounded_children = 0; for (i=0; iSync(); if (element->GetCullMode() == VolumeCullMode) { ++bounded_children; Stuff::LinearMatrix4D child_to_parent = element->GetLocalToParent(); Stuff::Point3D child_center(element->m_localOBB.localToParent); Stuff::Point3D child_center_in_parent; child_center_in_parent.Multiply(child_center, child_to_parent); centroid += child_center_in_parent; } } } // //--------------------------------------------------- // If we have no bounded children, we will never cull //--------------------------------------------------- // if (!bounded_children) { m_localOBB.sphereRadius = 0.0f; SetNeverCullMode(); } // //----------------------------------------------------------------- // Otherwise, find the tightest bounds from our calculated centroid //----------------------------------------------------------------- // else { centroid /= static_cast(bounded_children); m_localOBB.localToParent.BuildTranslation(centroid); m_localOBB.sphereRadius = -1.0f; for (i=0; iGetCullMode() == VolumeCullMode) { Stuff::LinearMatrix4D child_to_parent = element->GetLocalToParent(); Stuff::Point3D child_center(element->m_localOBB.localToParent); Stuff::Point3D child_center_in_parent; child_center_in_parent.Multiply(child_center, child_to_parent); child_center_in_parent -= centroid; Stuff::Scalar range = child_center_in_parent.GetLength() + element->m_localOBB.sphereRadius; if (range > m_localOBB.sphereRadius) m_localOBB.sphereRadius = range; } } } Verify(m_localOBB.sphereRadius > 0.0f); m_worldOBB.MultiplySphereOnly(m_localOBB, m_localToWorld); } BoundsAreRight(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::FullSphereSyncMethod() { Check_Object(this); Verify( IsMatrixDirty() && AreBoundsWrong() && GetCullMode()==VolumeCullMode && IsBoundedBySphere() ); SYNC_LOGIC("Sphere::Full::Switch"); // //-------------------- // Update our matrices //-------------------- // m_localToParent = m_newLocalToParent; Check_Object(m_parent); if (!IsLocalToParentIdentity()) m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld()); else m_localToWorld = m_parent->GetLocalToWorld(); // //-------------------- // Update our children //-------------------- // WORD i; Verify(m_list.GetLength() < 65536); WORD switch_count = static_cast(m_list.GetLength()); Stuff::Point3D centroid = Stuff::Point3D::Identity; WORD bounded_children = 0; for (i=0; iSync(); if (element->GetCullMode() == VolumeCullMode) { ++bounded_children; Stuff::LinearMatrix4D child_to_parent = element->GetLocalToParent(); Stuff::Point3D child_center(element->m_localOBB.localToParent); Stuff::Point3D child_center_in_parent; child_center_in_parent.Multiply(child_center, child_to_parent); centroid += child_center_in_parent; } } } // //--------------------------------------------------- // If we have no bounded children, we will never cull //--------------------------------------------------- // if (!bounded_children) { m_localOBB.sphereRadius = 0.0f; SetNeverCullMode(); } // //----------------------------------------------------------------- // Otherwise, find the tightest bounds from our calculated centroid //----------------------------------------------------------------- // else { centroid /= static_cast(bounded_children); m_localOBB.localToParent.BuildTranslation(centroid); m_localOBB.sphereRadius = -1.0f; for (i=0; iGetCullMode() == VolumeCullMode) { Stuff::LinearMatrix4D child_to_parent = element->GetLocalToParent(); Stuff::Point3D child_center(element->m_localOBB.localToParent); Stuff::Point3D child_center_in_parent; child_center_in_parent.Multiply(child_center, child_to_parent); child_center_in_parent -= centroid; Stuff::Scalar range = child_center_in_parent.GetLength() + element->m_localOBB.sphereRadius; if (range > m_localOBB.sphereRadius) m_localOBB.sphereRadius = range; } } } Verify(m_localOBB.sphereRadius > 0.0f); m_worldOBB.MultiplySphereOnly(m_localOBB, m_localToWorld); } m_state &= ~(MatrixDirtyFlag|BoundsWrongFlag); SetSyncState(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CleanOBBSyncMethod() { Check_Object(this); Verify( !IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedByOBB() ); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); SYNC_LOGIC("OBB::Clean::Switch"); // //------------------------------- // Update our m_localToWorld matrix //------------------------------- // 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); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::MatrixDirtyOBBSyncMethod() { Check_Object(this); Verify( IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedByOBB() ); Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f)); SYNC_LOGIC("OBB::Dirty::Switch"); // //-------------------- // Update our matrices //-------------------- // m_localToParent = m_newLocalToParent; 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(); // //-------------------- // Update our children //-------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); element->Sync(); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); element->Sync(); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); element->Sync(); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::BoundsWrongOBBSyncMethod() { Check_Object(this); STOP(("OBB's cannot recalculate bounds!")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::FullOBBSyncMethod() { Check_Object(this); STOP(("OBB's cannot recalculate bounds!")); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // bool ElementRenderer::SwitchElement::CastCulledRay(CollisionQuery *query) { Check_Object(this); Check_Object(query); Verify(!query->m_data); // //----------------------------- // Test it against the MLRShape //----------------------------- // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); if (element->CastRay(query)) { if (!query->m_data) query->m_data = m_data; return true; } } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); if (element->CastRay(query)) { if (!query->m_data) query->m_data = m_data; return true; } } element = GetSecondSwitchElement(); if (element) { Check_Object(element); if (element->CastRay(query)) { if (!query->m_data) query->m_data = m_data; return true; } } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ElementRenderer::Element* ElementRenderer::SwitchElement::FindSmallestElementContainingCulled(SphereTest *test) { Check_Object(this); Check_Object(test); // //------------------ // Draw our children //------------------ // Element *result = this; if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); Element *temp = element->FindSmallestElementContaining(test); if (temp) result = temp; } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); Element *temp = element->FindSmallestElementContaining(test); if (temp) result = temp; } element = GetSecondSwitchElement(); if (element) { Check_Object(element); Element *temp = element->FindSmallestElementContaining(test); if (temp) result = temp; } } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::InheritDrawMethod( CameraElement *camera, const StateChange *inherited_state, int culling_state ) { Check_Object(this); Check_Object(inherited_state); Check_Object(camera); Verify(culling_state != -1); // //-------------------------------------- // Draw our bounds if we are supposed to //-------------------------------------- // #if defined(LAB_ONLY) Callback *callback = GetCallbackSet(); unsigned index = GetCallbackIndex(); if (callback && callback[index]) { Check_Pointer(callback[index]); (*callback[index])(camera, inherited_state, culling_state, this); } #endif // //------------------------------ // Only draw the switch selected //------------------------------ // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); camera->DrawElement(element, inherited_state); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); camera->DrawElement(element, inherited_state); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); camera->DrawElement(element, inherited_state); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::OverrideDrawMethod( CameraElement *camera, const StateChange *inherited_state, int culling_state ) { Check_Object(this); Check_Object(inherited_state); Check_Object(camera); Verify(culling_state != -1); // //------------------- // Mix the properties //------------------- // Check_Object(m_stateChange); StateChange mixed; mixed.Mix(*inherited_state, *m_stateChange); MixLights( mixed.m_lights, inherited_state->m_lights, m_stateChange->m_lights ); // //-------------------------------------- // Draw our bounds if we are supposed to //-------------------------------------- // #if defined(LAB_ONLY) Callback *callback = GetCallbackSet(); unsigned index = GetCallbackIndex(); if (callback && callback[index]) { Check_Pointer(callback[index]); (*callback[index])(camera, inherited_state, culling_state, this); } #endif // //------------------------------ // Only draw the switch selected //------------------------------ // if (m_switch < m_list.GetLength()) { Element *element = m_list[m_switch]; if (element) { Check_Object(element); camera->DrawElement(element, &mixed); } } else if (m_switch & 0xf0) // special case { Element *element = GetFirstSwitchElement(); if (element) { Check_Object(element); camera->DrawElement(element, &mixed); } element = GetSecondSwitchElement(); if (element) { Check_Object(element); camera->DrawElement(element, &mixed); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CleanDamage() { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::ApplyDamage( const Stuff::LinearMatrix4D &damage_spot, Stuff::Scalar radius ) { Check_Object(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::ApplyDamageDecal( const Stuff::LinearMatrix4D &damage_spot, Stuff::Scalar radius, MidLevelRenderer::MLRTexture *texture ) { Check_Object(this); Check_Object(texture); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::CastShadow( const Stuff::LinearMatrix4D &shadow_to_world, const Stuff::UnitVector3D &sun_in_world, Stuff::Scalar radius ) { Check_Object(this); if (!IsShadowed()) return; WORD current = GetSwitch(); if (current < GetActiveCount()) { Element *element = GetIndexedElement(current); if (element) { Check_Object(element); element->CastShadow(shadow_to_world, sun_in_world, radius); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void ElementRenderer::SwitchElement::MakeFootStep( MidLevelRenderer::MLRShape *shape, const Stuff::LinearMatrix4D &foot, Stuff::Scalar radius, MidLevelRenderer::MLRTexture *tex ) { Check_Object(this); WORD current = GetSwitch(); if (current < GetActiveCount()) { Element *element = GetIndexedElement(current); if (element) { Check_Object(element); element->MakeFootStep(shape, foot, radius, tex); } } }