Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
728 lines
20 KiB
C++
728 lines
20 KiB
C++
#include "ElementRendererHeaders.hpp"
|
|
|
|
//#define SCALE_BUG "your_loginname_here"
|
|
|
|
//############################################################################
|
|
//############################ ScalableShapeElement ################################
|
|
//############################################################################
|
|
|
|
HGOSHEAP
|
|
ElementRenderer::ScalableShapeElement::s_Heap = NULL;
|
|
|
|
ElementRenderer::ScalableShapeElement::ClassData*
|
|
ElementRenderer::ScalableShapeElement::DefaultData = NULL;
|
|
|
|
ElementRenderer::Element::SyncMethod
|
|
ElementRenderer::ScalableShapeElement::SyncMethods[SyncStateCount]=
|
|
{
|
|
//
|
|
// Root mode
|
|
//
|
|
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),
|
|
|
|
//
|
|
// Sphere Cull
|
|
//
|
|
SYNC_METHOD(ScalableShapeElement, CleanSphere),
|
|
SYNC_METHOD(ScalableShapeElement, DirtySphere),
|
|
SYNC_METHOD(ScalableShapeElement, CleanSphere),
|
|
SYNC_METHOD(ScalableShapeElement, DirtySphere),
|
|
SYNC_METHOD(Element, None),
|
|
SYNC_METHOD(Element, Defer),
|
|
SYNC_METHOD(Element, None),
|
|
SYNC_METHOD(Element, Defer),
|
|
|
|
//
|
|
// OBB Cull
|
|
//
|
|
SYNC_METHOD(ScalableShapeElement, CleanOBB),
|
|
SYNC_METHOD(ScalableShapeElement, DirtyOBB),
|
|
SYNC_METHOD(ScalableShapeElement, CleanOBB),
|
|
SYNC_METHOD(ScalableShapeElement, 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::DrawMethod
|
|
ElementRenderer::ScalableShapeElement::DrawMethods[DrawStateCount]=
|
|
{
|
|
//
|
|
// No billboarding
|
|
//
|
|
DRAW_METHOD(ScalableShapeElement, Inherit),
|
|
DRAW_METHOD(ScalableShapeElement, Override)
|
|
};
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::InitializeClass()
|
|
{
|
|
Verify(!s_Heap);
|
|
s_Heap = gos_CreateMemoryHeap("Scalable Shape", 0, g_LibraryHeap);
|
|
Check_Pointer(s_Heap);
|
|
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
ScalableShapeElementClassID,
|
|
"ElementRenderer::ScalableShapeElement",
|
|
BaseClass::DefaultData,
|
|
reinterpret_cast<Factory>(&Make)
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
|
|
Check_Pointer(s_Heap);
|
|
gos_DestroyMemoryHeap(s_Heap);
|
|
s_Heap = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::ScalableShapeElement::ScalableShapeElement(
|
|
Stuff::MemoryStream *stream,
|
|
int version,
|
|
ShapeHolder shapes,
|
|
bool read_scale_from_stream
|
|
):
|
|
ShapeElement(DefaultData, 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];
|
|
|
|
//
|
|
//------------------------
|
|
// Get the scale and color
|
|
//------------------------
|
|
//
|
|
if (read_scale_from_stream)
|
|
*stream >> m_scale >> m_color;
|
|
else
|
|
{
|
|
m_scale.x = 1.0f;
|
|
m_scale.y = 1.0f;
|
|
m_scale.z = 1.0f;
|
|
m_color.red = 1.0f;
|
|
m_color.green = 1.0f;
|
|
m_color.blue = 1.0f;
|
|
m_color.alpha = 1.0f;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::ScalableShapeElement::ScalableShapeElement():
|
|
ShapeElement(DefaultData)
|
|
{
|
|
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_scale.x = 1.0f;
|
|
m_scale.y = 1.0f;
|
|
m_scale.z = 1.0f;
|
|
m_color.red = 1.0f;
|
|
m_color.green = 1.0f;
|
|
m_color.blue = 1.0f;
|
|
m_color.alpha = 1.0f;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::ScalableShapeElement::ScalableShapeElement(ScalableShapeElement *shape):
|
|
ShapeElement(shape, DefaultData)
|
|
{
|
|
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_scale.x = 1.0f;
|
|
m_scale.y = 1.0f;
|
|
m_scale.z = 1.0f;
|
|
m_color.red = 1.0f;
|
|
m_color.green = 1.0f;
|
|
m_color.blue = 1.0f;
|
|
m_color.alpha = 1.0f;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::ScalableShapeElement*
|
|
ElementRenderer::ScalableShapeElement::Make(
|
|
Stuff::MemoryStream *stream,
|
|
int version,
|
|
ShapeHolder shapes
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
|
|
gos_PushCurrentHeap(s_Heap);
|
|
ScalableShapeElement *element =
|
|
new ScalableShapeElement(stream, version, shapes, true);
|
|
gos_PopCurrentHeap();
|
|
|
|
return element;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::ScalableShapeElement*
|
|
ElementRenderer::ScalableShapeElement::MakeFromShape(
|
|
Stuff::MemoryStream *stream,
|
|
int version,
|
|
ShapeHolder shapes
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
|
|
RegisteredClass::ClassID class_id;
|
|
*stream >> class_id;
|
|
Verify(class_id == ShapeElementClassID);
|
|
|
|
gos_PushCurrentHeap(s_Heap);
|
|
ScalableShapeElement *element =
|
|
new ScalableShapeElement(stream, version, shapes, false);
|
|
gos_PopCurrentHeap();
|
|
|
|
return element;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::Save(Stuff::MemoryStream *stream)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(stream);
|
|
BaseClass::Save(stream);
|
|
|
|
//
|
|
//-----------------------------
|
|
// Save the shape to the stream
|
|
//-----------------------------
|
|
//
|
|
*stream << m_scale << m_color;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::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::ScalableShapeElement::CleanSphereSyncMethod()
|
|
{
|
|
Check_Object(this);
|
|
Verify(m_localOBB.sphereRadius > 0.0f);
|
|
Verify(
|
|
!IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedBySphere()
|
|
);
|
|
SYNC_LOGIC("Sphere::Clean::ScalableShape");
|
|
|
|
//
|
|
//-------------------------------
|
|
// 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
|
|
//------------------------------
|
|
//
|
|
Stuff::Point3D local_origin(m_localOBB.localToParent);
|
|
local_origin *= m_scale;
|
|
m_worldOBB.localToParent(3,0) =
|
|
local_origin.x*m_localToWorld(0,0)
|
|
+ local_origin.y*m_localToWorld(1,0)
|
|
+ local_origin.z*m_localToWorld(2,0)
|
|
+ m_localToWorld(3,0);
|
|
m_worldOBB.localToParent(3,1) =
|
|
local_origin.x*m_localToWorld(0,1)
|
|
+ local_origin.y*m_localToWorld(1,1)
|
|
+ local_origin.z*m_localToWorld(2,1)
|
|
+ m_localToWorld(3,1);
|
|
m_worldOBB.localToParent(3,2) =
|
|
local_origin.x*m_localToWorld(0,2)
|
|
+ local_origin.y*m_localToWorld(1,2)
|
|
+ local_origin.z*m_localToWorld(2,2)
|
|
+ m_localToWorld(3,2);
|
|
m_worldOBB.sphereRadius = m_localOBB.sphereRadius * m_scale.GetLength();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::DirtySphereSyncMethod()
|
|
{
|
|
Check_Object(this);
|
|
Verify(m_localOBB.sphereRadius > 0.0f);
|
|
Verify(
|
|
IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedBySphere()
|
|
);
|
|
SYNC_LOGIC("Sphere::Dirty::ScalableShape");
|
|
|
|
//
|
|
//--------------------
|
|
// 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
|
|
//------------------------------
|
|
//
|
|
Stuff::Point3D local_origin(m_localOBB.localToParent);
|
|
local_origin *= m_scale;
|
|
m_worldOBB.localToParent(3,0) =
|
|
local_origin.x*m_localToWorld(0,0)
|
|
+ local_origin.y*m_localToWorld(1,0)
|
|
+ local_origin.z*m_localToWorld(2,0)
|
|
+ m_localToWorld(3,0);
|
|
m_worldOBB.localToParent(3,1) =
|
|
local_origin.x*m_localToWorld(0,1)
|
|
+ local_origin.y*m_localToWorld(1,1)
|
|
+ local_origin.z*m_localToWorld(2,1)
|
|
+ m_localToWorld(3,1);
|
|
m_worldOBB.localToParent(3,2) =
|
|
local_origin.x*m_localToWorld(0,2)
|
|
+ local_origin.y*m_localToWorld(1,2)
|
|
+ local_origin.z*m_localToWorld(2,2)
|
|
+ m_localToWorld(3,2);
|
|
m_worldOBB.sphereRadius = m_localOBB.sphereRadius * m_scale.GetLength();
|
|
MatrixIsClean();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::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));
|
|
Verify(
|
|
Stuff::Close_Enough(m_localOBB.localToParent(0,0), 1.0f) &&
|
|
Stuff::Close_Enough(m_localOBB.localToParent(1,1), 1.0f) &&
|
|
Stuff::Close_Enough(m_localOBB.localToParent(2,2), 1.0f)
|
|
);
|
|
SYNC_LOGIC("OBB::Clean::ScalableShape");
|
|
|
|
//
|
|
//-------------------------------
|
|
// 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
|
|
//------------------------------
|
|
//
|
|
Stuff::LinearMatrix4D scaled_transform = m_localOBB.localToParent;
|
|
scaled_transform(3,0) *= m_scale.x;
|
|
scaled_transform(3,1) *= m_scale.y;
|
|
scaled_transform(3,2) *= m_scale.z;
|
|
m_worldOBB.localToParent.Multiply(scaled_transform, m_localToWorld);
|
|
m_worldOBB.axisExtents.Multiply(m_localOBB.axisExtents, m_scale);
|
|
m_worldOBB.sphereRadius = m_worldOBB.axisExtents.GetLength();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::DirtyOBBSyncMethod()
|
|
{
|
|
Check_Object(this);
|
|
Verify(
|
|
IsMatrixDirty() && GetCullMode()==VolumeCullMode && IsBoundedByOBB()
|
|
);
|
|
Verify(Stuff::Close_Enough(m_localOBB.sphereRadius, m_localOBB.axisExtents.GetLength(), m_localOBB.sphereRadius*0.02f));
|
|
Verify(
|
|
Stuff::Close_Enough(m_localOBB.localToParent(0,0), 1.0f) &&
|
|
Stuff::Close_Enough(m_localOBB.localToParent(1,1), 1.0f) &&
|
|
Stuff::Close_Enough(m_localOBB.localToParent(2,2), 1.0f)
|
|
);
|
|
SYNC_LOGIC("OBB::Dirty::ScalableShape");
|
|
|
|
//
|
|
//--------------------
|
|
// 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
|
|
//------------------------------
|
|
//
|
|
Stuff::LinearMatrix4D scaled_transform = m_localOBB.localToParent;
|
|
scaled_transform(3,0) *= m_scale.x;
|
|
scaled_transform(3,1) *= m_scale.y;
|
|
scaled_transform(3,2) *= m_scale.z;
|
|
m_worldOBB.localToParent.Multiply(scaled_transform, m_localToWorld);
|
|
m_worldOBB.axisExtents.Multiply(m_localOBB.axisExtents, m_scale);
|
|
m_worldOBB.sphereRadius = m_worldOBB.axisExtents.GetLength();
|
|
#if defined(SCALE_BUG)
|
|
SPEW((SCALE_BUG, "m_worldOBB = "));
|
|
Spew(SCALE_BUG, m_worldOBB);
|
|
SPEW((SCALE_BUG, ""));
|
|
#endif
|
|
MatrixIsClean();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
ElementRenderer::ScalableShapeElement::CastCulledRay(CollisionQuery *query)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(query);
|
|
|
|
STOP(("ScalableShape is not collidable!"));
|
|
return false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::Element*
|
|
ElementRenderer::ScalableShapeElement::FindSmallestElementContainingCulled(SphereTest *test)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(test);
|
|
|
|
STOP(("ScalableShape is not collidable!"));
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::SetDrawState()
|
|
{
|
|
Check_Object(this);
|
|
unsigned index = (m_state>>DrawStateBit) & DrawStateMask;
|
|
Verify(index < DrawStateCount);
|
|
m_draw = DrawMethods[index];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::InheritDrawMethod(
|
|
CameraElement *camera,
|
|
const StateChange *inherited_state,
|
|
int culling_state
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(inherited_state);
|
|
Check_Object(camera);
|
|
Verify(culling_state != -1);
|
|
#if defined(_ARMOR)
|
|
if (!culling_state)
|
|
Verify(!Cull(camera));
|
|
#endif
|
|
|
|
//
|
|
//--------------------------------------
|
|
// 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);
|
|
}
|
|
else if (s_ShowClippedBounds && GetCullMode() == VolumeCullMode && culling_state)
|
|
{
|
|
Stuff::RGBAColor color(1.0f, 0.5f, 0.5f, 0.3f);
|
|
if (IsBoundedBySphere())
|
|
DrawSphere(m_worldOBB, color, camera, inherited_state, culling_state);
|
|
else
|
|
DrawOBB(m_worldOBB, color, camera, inherited_state, culling_state);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//----------------------------
|
|
// Set up the draw information
|
|
//----------------------------
|
|
//
|
|
MidLevelRenderer::DrawScalableShapeInformation info;
|
|
Check_Object(m_MLRShape);
|
|
info.shape = m_MLRShape;
|
|
info.clippingFlags.SetClippingState(culling_state);
|
|
Check_Object(&m_localToWorld);
|
|
info.shapeToWorld = &m_localToWorld;
|
|
info.worldToShape = NULL;
|
|
info.state = inherited_state->GetMLRState();
|
|
LightList culled_lights;
|
|
info.nrOfActiveLights = CullLights(culled_lights, inherited_state->m_lights);
|
|
info.activeLights = (info.nrOfActiveLights>0) ? &culled_lights[0] : NULL;
|
|
info.scaling = &m_scale;
|
|
info.paintMeColor = &m_color;
|
|
|
|
//
|
|
//---------------
|
|
// Draw the shape
|
|
//---------------
|
|
//
|
|
MidLevelRenderer::MLRClipper *clipper = camera->GetClipper();
|
|
Check_Object(clipper);
|
|
|
|
Stop_Timer(Graph_Traversal);
|
|
ELEMENT_RENDER("Culling::ScalableShape::Inherited");
|
|
Start_Timer(Draw_Scalable);
|
|
clipper->DrawScalableShape(&info);
|
|
Stop_Timer(Draw_Scalable);
|
|
Start_Timer(Graph_Traversal);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
ElementRenderer::ScalableShapeElement::OverrideDrawMethod(
|
|
CameraElement *camera,
|
|
const StateChange *inherited_state,
|
|
int culling_state
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(inherited_state);
|
|
Check_Object(camera);
|
|
Verify(culling_state != -1);
|
|
#if defined(_ARMOR)
|
|
if (!culling_state)
|
|
Verify(!Cull(camera));
|
|
#endif
|
|
|
|
//
|
|
//-------------------
|
|
// 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, &mixed, culling_state, this);
|
|
}
|
|
else if (s_ShowClippedBounds && GetCullMode() == VolumeCullMode && culling_state)
|
|
{
|
|
Stuff::RGBAColor color(1.0f, 0.5f, 0.5f, 0.3f);
|
|
if (IsBoundedBySphere())
|
|
DrawSphere(m_worldOBB, color, camera, &mixed, culling_state);
|
|
else
|
|
DrawOBB(m_worldOBB, color, camera, &mixed, culling_state);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//----------------------------
|
|
// Set up the draw information
|
|
//----------------------------
|
|
//
|
|
MidLevelRenderer::DrawScalableShapeInformation info;
|
|
Check_Object(m_MLRShape);
|
|
info.shape = m_MLRShape;
|
|
info.clippingFlags.SetClippingState(culling_state);
|
|
Check_Object(&m_localToWorld);
|
|
info.shapeToWorld = &m_localToWorld;
|
|
info.worldToShape = NULL;
|
|
info.state = mixed.GetMLRState();
|
|
LightList culled_lights;
|
|
info.nrOfActiveLights = CullLights(culled_lights, mixed.m_lights);
|
|
info.activeLights = (info.nrOfActiveLights>0) ? &culled_lights[0] : NULL;
|
|
info.scaling = &m_scale;
|
|
info.paintMeColor = &m_color;
|
|
|
|
//
|
|
//---------------
|
|
// Draw the shape
|
|
//---------------
|
|
//
|
|
MidLevelRenderer::MLRClipper *clipper = camera->GetClipper();
|
|
Check_Object(clipper);
|
|
|
|
Stop_Timer(Graph_Traversal);
|
|
ELEMENT_RENDER("Culling::ScalableShape::Overridden");
|
|
Start_Timer(Draw_Scalable);
|
|
clipper->DrawScalableShape(&info);
|
|
Stop_Timer(Draw_Scalable);
|
|
Start_Timer(Graph_Traversal);
|
|
}
|