Files
firestorm/Gameleap/code/mw4/Libraries/elementrenderer/CameraElement.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

937 lines
26 KiB
C++

#include "ElementRendererHeaders.hpp"
#include <MLR\MLRFootstep.hpp>
#include <MLR\MLRSortByOrder.hpp>
#include <MLR\MLRTexturePool.hpp>
//############################################################################
//############################ CameraElement ###############################
//############################################################################
#if 0
MidLevelRenderer::MLRTexture *g_BergerName;
bool s_AbzugFlag = false;
bool g_AbzugFlag = false;
#endif
ElementRenderer::CameraElement::ClassData*
ElementRenderer::CameraElement::DefaultData = NULL;
ElementRenderer::Element::SyncMethod
ElementRenderer::CameraElement::SyncMethods[2]=
{
SYNC_METHOD(CameraElement, CleanCamera),
SYNC_METHOD(CameraElement, DirtyCamera)
};
ElementRenderer::Element::CullMethod
ElementRenderer::CameraElement::CullMethodObject=CULL_METHOD(CameraElement, CameraOnly, Always);
bool ElementRenderer::CameraElement::s_HideSky=false;
static bool __stdcall CheckHideSky() {return ElementRenderer::CameraElement::s_HideSky;}
static void __stdcall EnableHideSky() {ElementRenderer::CameraElement::s_HideSky = !ElementRenderer::CameraElement::s_HideSky;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::InitializeClass(Stuff::NotationFile *startup_ini)
{
Verify(!DefaultData);
DefaultData =
new ClassData(
CameraElementClassID,
"ElementRenderer::CameraElement",
BaseClass::DefaultData,
reinterpret_cast<Factory>(&Make)
);
Check_Object(DefaultData);
AddDebuggerMenuItem("Libraries\\Graphics Options\\Hide Sky", CheckHideSky, EnableHideSky, 0 );
if (startup_ini)
{
Check_Object(startup_ini);
Stuff::Page *page = startup_ini->FindPage("Graphics Options");
if (page)
{
Check_Object(page);
page->GetEntry("HideSky", &s_HideSky);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::TerminateClass(Stuff::NotationFile *startup_ini)
{
if (startup_ini)
{
Check_Object(startup_ini);
Stuff::Page *page = startup_ini->SetPage("Graphics Options");
Check_Object(page);
page->SetEntry("HideSky", s_HideSky);
}
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::CameraElement::CameraElement(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes
):
GroupElement(DefaultData, stream, version, shapes),
m_scene(NULL)
{
Check_Pointer(this);
//
//----------------------------
// Initialize member variables
//----------------------------
//
m_state = NeverCullMode | MatrixDirtyFlag;
CameraElement::SetSyncState();
CameraElement::SetCullState();
CameraElement::SetDrawState();
//
//-----------------------------
// Create the attachment to MLR
//-----------------------------
//
gos_PushCurrentHeap(MidLevelRenderer::SorterHeap);
m_sorter = new MidLevelRenderer::MLRSortByOrder(MidLevelRenderer::MLRTexturePool::Instance);
Check_Object(m_sorter);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ClipperHeap);
m_clipper = new MidLevelRenderer::MLRClipper(0, m_sorter);
Check_Object(m_clipper);
gos_PopCurrentHeap();
//
//-----------------------------------------
// Get the scene properties from the stream
//-----------------------------------------
//
m_viewingStateChange = new StateChange(stream, version);
Check_Object(m_viewingStateChange);
//
//----------------------------------
// Get the clip data from the stream
//----------------------------------
//
*stream >> m_nearLeft >> m_nearRight >> m_nearTop >> m_nearBottom;
*stream >> m_nearClip >> m_farClip;
SetPerspective(
m_nearClip,
m_farClip,
m_nearLeft,
m_nearRight,
m_nearTop,
m_nearBottom
);
//
//-----------------------------------
// Get the buffer flags and fog color
//-----------------------------------
//
*stream >> m_clearZBufferOnDraw >> m_clearBackBufferOnDraw;
if (version < 5)
{
Stuff::RGBAColor color;
*stream >> color;
}
m_viewPortLeft = 0.0f;
m_viewPortTop = 0.0f;
m_viewPortRight = 1.0f;
m_viewPortBottom = 1.0f;
m_acceptingElement = NULL;
m_drawSky = true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::CameraElement::CameraElement(StateChange *properties):
GroupElement(DefaultData),
m_scene(NULL)
{
Check_Pointer(this);
Check_Object(properties);
//
//----------------------------
// Initialize member variables
//----------------------------
//
m_state = NeverCullMode | MatrixDirtyFlag;
CameraElement::SetSyncState();
CameraElement::SetCullState();
CameraElement::SetDrawState();
m_viewingStateChange = properties;
m_clearZBufferOnDraw = true;
m_clearBackBufferOnDraw = true;
m_drawSky = true;
m_fovAngle = Stuff::Pi_Over_3;
//m_scene = NULL;
m_useTintColor = false;
//
//--------------
// Build the sky
//--------------
//
//
//-----------------------------
// Create the attachment to MLR
//-----------------------------
//
gos_PushCurrentHeap(MidLevelRenderer::SorterHeap);
m_sorter = new MidLevelRenderer::MLRSortByOrder(MidLevelRenderer::MLRTexturePool::Instance);
Check_Object(m_sorter);
gos_PopCurrentHeap();
gos_PushCurrentHeap(MidLevelRenderer::ClipperHeap);
m_clipper = new MidLevelRenderer::MLRClipper(0, m_sorter);
Check_Object(m_clipper);
gos_PopCurrentHeap();
m_viewPortLeft = 0.0f;
m_viewPortTop = 0.0f;
m_viewPortRight = 1.0f;
m_viewPortBottom = 1.0f;
m_acceptingElement = NULL;
//상훈 앞
m_hsh_special_flag=false;
//상훈 뒤
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ElementRenderer::CameraElement::DeleteSky()
{
Element *sky = m_sky.GetCurrent();
if (sky)
{
Check_Object(sky);
delete sky;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::CameraElement::~CameraElement()
{
Check_Object(m_clipper);
delete m_clipper;
Check_Object(m_viewingStateChange);
delete m_viewingStateChange;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::CameraElement*
ElementRenderer::CameraElement::Make(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes
)
{
Check_Object(stream);
gos_PushCurrentHeap(g_Heap);
CameraElement *element = new CameraElement(stream, version, shapes);
gos_PopCurrentHeap();
return element;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::Save(Stuff::MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
BaseClass::Save(stream);
//
//--------------------------
// Save the scene properties
//--------------------------
//
Check_Object(m_viewingStateChange);
m_viewingStateChange->Save(stream);
//
//-------------------
// Save the clip data
//-------------------
//
*stream << m_nearLeft << m_nearRight << m_nearTop << m_nearBottom;
*stream << m_nearClip << m_farClip;
//
//--------------------------------
// Save buffer flags and fog color
//--------------------------------
//
*stream << m_clearZBufferOnDraw << m_clearBackBufferOnDraw;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::SetSyncState()
{
Check_Object(this);
Verify(GetCullMode() == NeverCullMode);
m_sync = SyncMethods[IsMatrixDirty()?1:0];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::CleanCameraSyncMethod()
{
Check_Object(this);
SYNC_LOGIC("Clean::Camera");
//
//------------------------------------------------------------------
// Concatenated our m_localToWorld from m_localToParent and our parent's
// m_localToWorld
//------------------------------------------------------------------
//
Check_Object(m_parent);
m_localToWorld.Multiply(m_localToParent, m_parent->GetLocalToWorld());
//
//--------------------------------------------
// Transform the local planes into world space
//--------------------------------------------
//
for (int i=0; i<CullingPlaneCount; ++i)
m_worldCullingPlanes[i].Multiply(
m_localCullingPlanes[i],
m_localToWorld
);
//
//--------------------------------------------
// Prepare 2D culling
//--------------------------------------------
//
m_cullFrustrumXZ[0] = m_localToWorld;
Stuff::UnitVector3D ur, uu, uf;
Stuff::Vector3D
right = Stuff::Vector3D::Identity,
forward = Stuff::Vector3D::Identity,
up = Stuff::Vector3D::Identity;
m_localToWorld.GetLocalRightInWorld(&ur);
m_localToWorld.GetLocalUpInWorld(&uu);
m_localToWorld.GetLocalForwardInWorld(&uf);
right.AddScaled(right, ur, Stuff::Fabs(m_nearRight*m_farClip/m_nearClip));
up.AddScaled(up, uu, Stuff::Fabs(m_nearTop*m_farClip/m_nearClip));
forward.AddScaled(forward, uf, Stuff::Fabs(m_farClip));
m_cullFrustrumXZ[1].Add(forward, up);
m_cullFrustrumXZ[2].Add(forward, up);
up.Negate(up);
m_cullFrustrumXZ[3].Add(forward, up);
m_cullFrustrumXZ[4].Add(forward, up);
m_cullFrustrumXZ[2].Add(m_cullFrustrumXZ[2], right);
m_cullFrustrumXZ[3].Add(m_cullFrustrumXZ[3], right);
right.Negate(right);
m_cullFrustrumXZ[1].Add(m_cullFrustrumXZ[1], right);
m_cullFrustrumXZ[4].Add(m_cullFrustrumXZ[4], right);
for(i=1;i<5;i++)
{
m_cullFrustrumXZ[i].Add(m_cullFrustrumXZ[i], m_cullFrustrumXZ[0]);
m_cullFrustrumXZ[i].y = 0.0f;
}
m_cullFrustrumXZ[0].y = 0.0f;
#if 0
SPEW(("micgaert", "%f %f %f", m_cullFrustrumXZ[0].x, m_cullFrustrumXZ[0].y, m_cullFrustrumXZ[0].z));
SPEW(("micgaert", "%f %f %f", m_cullFrustrumXZ[1].x, m_cullFrustrumXZ[1].y, m_cullFrustrumXZ[1].z));
SPEW(("micgaert", "%f %f %f", m_cullFrustrumXZ[2].x, m_cullFrustrumXZ[2].y, m_cullFrustrumXZ[2].z));
SPEW(("micgaert", "%f %f %f", m_cullFrustrumXZ[3].x, m_cullFrustrumXZ[3].y, m_cullFrustrumXZ[3].z));
SPEW(("micgaert", "%f %f %f", m_cullFrustrumXZ[4].x, m_cullFrustrumXZ[4].y, m_cullFrustrumXZ[4].z));
SPEW(("micgaert", "\n"));
#endif
//
//--------------------
// Update our children
//--------------------
//
Stuff::ChainIteratorOf<Element*> children(&m_group);
Element *child;
while ((child = children.ReadAndNext()) != NULL)
{
Check_Object(child);
child->Sync();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::DirtyCameraSyncMethod()
{
Check_Object(this);
SYNC_LOGIC("Dirty::Camera");
//
//------------------------------------------------------
// If the local-to-parent matrix is dirty, make it clean
//------------------------------------------------------
//
m_localToParent = m_newLocalToParent;
MatrixIsClean();
CleanCameraSyncMethod();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::SetCullState()
{
Check_Object(this);
m_cameraCull = CullMethodObject.m_cameraCull;
m_rayCull = CullMethodObject.m_rayCull;
m_sphereTest = CullMethodObject.m_sphereTest;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
ElementRenderer::CameraElement::CameraOnlyCullMethod(CameraElement *camera)
{
Check_Object(this);
Check_Object(camera);
return (camera != this) ? -1 : 0;
}
//상훈 앞
void __cdecl ClearTargetCameraBackBuffer();
//상훈 뒤
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::DrawScene(bool gosClearedScreen)
{
Check_Object(this);
//
//-----------------------------
// Tell MLR where the camera is
//-----------------------------
//
ELEMENT_RENDER("DrawScene");
Start_Timer(Total_Video);
#if 0
if (g_AbzugFlag)
{
m_viewingStateChange->DisableChildTextureHandleControl();
m_viewingStateChange->DisableChildAlphaControl ();
m_viewingStateChange->SetAlphaMode (MidLevelRenderer::MLRState::AlphaMode::OneZeroMode);
m_viewingStateChange->SetTextureHandle (g_BergerName->GetTextureHandle ());
}
#endif
bool secondary = false;
{
ELEMENT_RENDER("Setup & Sky");
Start_Timer(Setup_Sky);
Check_Object(m_clipper);
Check_Object(m_viewingStateChange);
if(m_useTintColor)
{
FadeColor = m_tintColor;
}
else
{
FadeColor = Stuff::RGBAColor::White;
}
m_acceptingElement = NULL;
if (m_clearZBufferOnDraw)
{
Stuff::Scalar z=1.0f;
if (m_clearBackBufferOnDraw)
{
m_clipper->StartDraw(
m_localToWorld,
m_cameraToClip,
Stuff::RGBAColor::Unassigned,
&StateChange::GetFogColor(),
m_viewingStateChange->GetMLRState(),
&z
);
}
else
{
m_clipper->StartDraw(
m_localToWorld,
m_cameraToClip,
Stuff::RGBAColor::Unassigned,
NULL,
m_viewingStateChange->GetMLRState(),
&z
);
}
}
else
{
if (m_clearBackBufferOnDraw)
{
m_clipper->StartDraw(
m_localToWorld,
m_cameraToClip,
Stuff::RGBAColor::Unassigned,
&StateChange::GetFogColor(),
m_viewingStateChange->GetMLRState(),
NULL
);
}
else
{
//
//-----------------------------------------
//This means that we are a secondary camera
//-----------------------------------------
//
//상훈 앞
if(m_hsh_special_flag){
ClearTargetCameraBackBuffer();
}
//상훈 뒤
m_clipper->StartDraw(
m_localToWorld,
m_cameraToClip,
Stuff::RGBAColor::Unassigned,
NULL,
m_viewingStateChange->GetMLRState(),
NULL
);
secondary = true;
}
}
//
//---------------------------------
//Setup the Viewport for the camera
//---------------------------------
//
MidLevelRenderer::SetViewportScalars(
m_viewPortTop,
m_viewPortLeft,
m_viewPortBottom,
m_viewPortRight
);
if(secondary)
{
if(gosClearedScreen==false)
{
MidLevelRenderer::ClearZBuffer();
}
GetClipper()->SetCurrentState();
}
//
//------------------------------------------------------------------------
// If the sky is active, draw it first after moving it to where the camera
// is
//------------------------------------------------------------------------
//
else // Don't update LastCameraPosition for any camera but the main one.
{
gosFX::Effect::LastCameraPosition = GetLocalToWorld();
}
if (m_sky.GetCurrent() && !s_HideSky && m_drawSky && m_scene.GetCurrent())
{
Element *sky = m_sky.GetCurrent();
Check_Object(sky);
Stuff::LinearMatrix4D sky_to_parent = sky->GetLocalToParent();
sky_to_parent.BuildTranslation(gosFX::Effect::LastCameraPosition);
sky->SetLocalToParent(sky_to_parent);
sky->Sync();
DrawElement(sky, m_viewingStateChange);
}
Stop_Timer(Setup_Sky);
}
//
//---------------------------------------------
// Traverse the scene, and tell MLR we are done
//---------------------------------------------
//
if(m_scene.GetCurrent())
{
ELEMENT_RENDER("Culling");
Check_Object(m_scene.GetCurrent());
Start_Timer(Graph_Traversal);
DrawElement(m_scene.GetCurrent(), m_viewingStateChange);
Stop_Timer(Graph_Traversal);
}
if(!secondary && (MidLevelRenderer::MLRFootStep::Instance!=NULL) )
{
MidLevelRenderer::MLRFootStep::Instance->Draw(m_clipper, GetLocalToWorld());
}
{
ELEMENT_RENDER("Rasterizing");
Start_Timer(Render);
//상훈
extern bool sh_isdeathmode;
if(!sh_isdeathmode)
m_clipper->RenderNow();
Stop_Timer(Render);
}
FadeColor = Stuff::RGBAColor::White;
Stop_Timer(Total_Video);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::CastShadow(
const Stuff::LinearMatrix4D &shadow_to_world,
const Stuff::UnitVector3D &sun_in_world,
Stuff::Scalar radius
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::MakeFootStep(
MidLevelRenderer::MLRShape *shape,
const Stuff::LinearMatrix4D &foot,
Stuff::Scalar radius,
MidLevelRenderer::MLRTexture *tex
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::SetScene(Element *scene)
{
Check_Object(this);
m_scene.Remove();
if (scene != NULL)
{
m_scene.Add(scene);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::AdoptSkyElement(Element *sky)
{
Check_Object(this);
Check_Object(sky);
//
//----------------------------------------------------------------------
// Make sure that the sky element only writes to the z-buffer and is not
// fogged
//----------------------------------------------------------------------
//
m_sky.Remove();
m_sky.Add(sky);
StateChange *state = sky->GetStateChange();
if (!state)
{
state = new StateChange;
Check_Object(state);
sky->AdoptStateChange(state);
}
state->DisableBackfaceCulling();
state->DisableChildBackfaceControl();
state->SetFogMode(StateChange::DisableFogMode);
state->DisableChildFogControl();
state->DisableZBufferWrite();
state->DisableChildZBufferWriteControl();
state->DisableZBufferCompare();
state->DisableChildZBufferCompareControl();
state->DisableTextureWrap();
state->DisableChildTextureWrapControl();
state->SetFilterMode(MidLevelRenderer::MLRState::BiLinearFilterMode);
state->DisableChildFilterControl();
state->EnableDrawNow();
state->DisableChildDrawNowControl();
sky->SetRootMode();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::SetPerspective(
Stuff::Scalar near_clip,
Stuff::Scalar far_clip,
Stuff::Scalar left_clip,
Stuff::Scalar right_clip,
Stuff::Scalar top_clip,
Stuff::Scalar bottom_clip
)
{
Check_Object(this);
Verify(far_clip - near_clip > Stuff::SMALL);
Verify(left_clip - right_clip > Stuff::SMALL);
Verify(top_clip - bottom_clip > Stuff::SMALL);
m_nearClip = near_clip;
m_farClip = far_clip;
m_nearLeft = left_clip;
m_nearRight = right_clip;
m_nearTop = top_clip;
m_nearBottom = bottom_clip;
//
//-------------------------------------------------------
// Calculate the horizontal, vertical, and forward ranges
//-------------------------------------------------------
//
Stuff::Scalar horizontal_range = APPLY_LEFT_SIGN(1.0f) / (left_clip - right_clip);
Stuff::Scalar vertical_range = APPLY_UP_SIGN(1.0f) / (top_clip - bottom_clip);
Stuff::Scalar depth_range = APPLY_FORWARD_SIGN(1.0f) / (far_clip - near_clip);
//
//------------------------------------------------------------------------
// Set up the camera to clip matrix. This matrix takes camera space
// coordinates and maps them into a homogeneous culling space where valid
// X, Y, and Z axis values (when divided by W) will all be between 0 and 1
//------------------------------------------------------------------------
//
m_cameraToClip(LEFT_AXIS, LEFT_AXIS) = near_clip * horizontal_range;
m_cameraToClip(LEFT_AXIS, UP_AXIS) = 0.0f;
m_cameraToClip(LEFT_AXIS, FORWARD_AXIS) = 0.0f;
m_cameraToClip(LEFT_AXIS, 3) = 0.0f;
m_cameraToClip(UP_AXIS, LEFT_AXIS) = 0.0f;
m_cameraToClip(UP_AXIS, UP_AXIS) = near_clip * vertical_range;
m_cameraToClip(UP_AXIS, FORWARD_AXIS) = 0.0f;
m_cameraToClip(UP_AXIS, 3) = 0.0f;
m_cameraToClip(FORWARD_AXIS, LEFT_AXIS) = -right_clip * horizontal_range;
m_cameraToClip(FORWARD_AXIS, UP_AXIS) = -bottom_clip * vertical_range;
m_cameraToClip(FORWARD_AXIS, FORWARD_AXIS) = far_clip * depth_range;
m_cameraToClip(FORWARD_AXIS, 3) = 1.0f;
m_cameraToClip(3, LEFT_AXIS) = 0.0f;
m_cameraToClip(3, UP_AXIS) = 0.0f;
m_cameraToClip(3, FORWARD_AXIS) = -far_clip * near_clip * depth_range;
m_cameraToClip(3, 3) = 0.0f;
//
//-----------------------------------------------------------------------
// Now, set up the far and near clip planes. They are always parallel to
// the X-Y plane
//-----------------------------------------------------------------------
//
int index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::NearClipBit - 1;
m_localCullingPlanes[index].offset = -near_clip;
m_localCullingPlanes[index].normal = Stuff::UnitVector3D::Backward;
index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::FarClipBit - 1;
m_localCullingPlanes[index].offset = far_clip;
m_localCullingPlanes[index].normal = Stuff::UnitVector3D::Forward;
//
//------------------------------------------------------------------------
// Set up the left culling plane. Given right-handed points, create three
// vertices from the clip data
//------------------------------------------------------------------------
//
Stuff::Scalar growth = far_clip / near_clip;
Stuff::Scalar far_left = left_clip * growth;
Stuff::Scalar far_right = right_clip * growth;
Stuff::Scalar far_top = top_clip * growth;
Stuff::Scalar far_bottom = bottom_clip * growth;
Stuff::Point3D
point1,
point2,
point3;
point1[LEFT_AXIS] = APPLY_LEFT_SIGN(left_clip);
point1[UP_AXIS] = APPLY_UP_SIGN(bottom_clip);
point1[FORWARD_AXIS] = APPLY_FORWARD_SIGN(near_clip);
point2[LEFT_AXIS] = APPLY_LEFT_SIGN(left_clip);
point2[UP_AXIS] = APPLY_UP_SIGN(top_clip);
point2[FORWARD_AXIS] = APPLY_FORWARD_SIGN(near_clip);
point3[LEFT_AXIS] = APPLY_LEFT_SIGN(far_left);
point3[UP_AXIS] = APPLY_UP_SIGN(top_clip);
point3[FORWARD_AXIS] = APPLY_FORWARD_SIGN(far_clip);
index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::LeftClipBit - 1;
m_localCullingPlanes[index].BuildPlane(point1, point2, point3);
//
//-------------------------------
// Set up the right culling plane
//-------------------------------
//
point1[LEFT_AXIS] = APPLY_LEFT_SIGN(right_clip);
point1[UP_AXIS] = APPLY_UP_SIGN(top_clip);
point2[LEFT_AXIS] = APPLY_LEFT_SIGN(right_clip);
point2[UP_AXIS] = APPLY_UP_SIGN(bottom_clip);
point3[LEFT_AXIS] = APPLY_LEFT_SIGN(far_right);
point3[UP_AXIS] = APPLY_UP_SIGN(far_bottom);
index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::RightClipBit - 1;
m_localCullingPlanes[index].BuildPlane(point1, point2, point3);
//
//-----------------------------
// Set up the top culling plane
//-----------------------------
//
point1[LEFT_AXIS] = APPLY_LEFT_SIGN(left_clip);
point2[UP_AXIS] = APPLY_UP_SIGN(top_clip);
point3[UP_AXIS] = APPLY_UP_SIGN(far_top);
index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::TopClipBit - 1;
m_localCullingPlanes[index].BuildPlane(point1, point2, point3);
//
//--------------------------------
// Set up the bottom culling plane
//--------------------------------
//
point1[LEFT_AXIS] = APPLY_LEFT_SIGN(right_clip);
point1[UP_AXIS] = APPLY_UP_SIGN(bottom_clip);
point2[LEFT_AXIS] = APPLY_LEFT_SIGN(left_clip);
point2[UP_AXIS] = APPLY_UP_SIGN(bottom_clip);
point3[LEFT_AXIS] = APPLY_LEFT_SIGN(far_left);
point3[UP_AXIS] = APPLY_UP_SIGN(far_bottom);
index = MidLevelRenderer::MLRClippingState::NextBit - MidLevelRenderer::MLRClippingState::BottomClipBit - 1;
m_localCullingPlanes[index].BuildPlane(point1, point2, point3);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::SetPerspective(
Stuff::Scalar near_clip,
Stuff::Scalar far_clip,
const Stuff::Radian &horizontal_fov,
Stuff::Scalar height_to_width
)
{
Check_Object(this);
Verify(far_clip - near_clip > Stuff::SMALL);
Verify(horizontal_fov > Stuff::SMALL);
Verify(height_to_width > Stuff::SMALL);
//
//-------------------------------------------------------------
// Calculate the near plane offsets to the side culling planes
//-------------------------------------------------------------
//
Stuff::Scalar width = near_clip * Stuff::Tan(horizontal_fov*0.5f);
Stuff::Scalar height = width * height_to_width;
m_fovAngle = horizontal_fov;
SetPerspective(near_clip, far_clip, width, -width, height, -height);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::CameraElement::GetPerspective(
Stuff::Scalar &near_clip,
Stuff::Scalar &far_clip,
Stuff::Scalar &horizontal_fov,
Stuff::Scalar &height_to_width
)
{
near_clip = m_nearClip;
far_clip = m_farClip;
horizontal_fov = Stuff::Arctan(m_nearLeft, m_nearClip)*2.0f;
height_to_width = m_nearTop / m_nearLeft;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
ElementRenderer::CameraElement::CastCulledRay(CollisionQuery *query)
{
Check_Object(this);
Check_Object(query);
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::Element*
ElementRenderer::CameraElement::FindSmallestElementContainingCulled(SphereTest *test)
{
Check_Object(this);
Check_Object(test);
return NULL;
}