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.
372 lines
9.2 KiB
C++
372 lines
9.2 KiB
C++
#include "AdeptHeaders.hpp"
|
|
|
|
#include "VideoHeaders.hpp"
|
|
#include "Interface.hpp"
|
|
#include "Mission.hpp"
|
|
#include <ElementRenderer\CameraElement.hpp>
|
|
#include <ElementRenderer\StateChange.hpp>
|
|
#include <ElementRenderer\LightElement.hpp>
|
|
|
|
//
|
|
// Shared Data Support
|
|
//
|
|
Component::ClassData*
|
|
CameraComponent::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// InitializeClass
|
|
//
|
|
void
|
|
CameraComponent::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
CameraComponentClassID,
|
|
"Adept::CameraComponent",
|
|
BaseClass::DefaultData,
|
|
0,
|
|
NULL
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraComponent::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//#############################################################################
|
|
// Constructors and destructors
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ElementRenderer::CameraElement*
|
|
CameraComponent::AllocateCamera()
|
|
{
|
|
gos_PushCurrentHeap(ElementRenderer::g_Heap);
|
|
ElementRenderer::StateChange *states = new ElementRenderer::StateChange;
|
|
Register_Object(states);
|
|
ElementRenderer::CameraElement *camera = new ElementRenderer::CameraElement(states);
|
|
Register_Object(camera);
|
|
gos_PopCurrentHeap();
|
|
return camera;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CameraComponent
|
|
//
|
|
CameraComponent::CameraComponent(
|
|
ClassData *class_data,
|
|
MemoryStream *stream,
|
|
VideoComponentWeb *owning_web,
|
|
Interface * intface
|
|
):
|
|
GroupComponent(
|
|
class_data,
|
|
stream,
|
|
owning_web,
|
|
AllocateCamera()
|
|
)
|
|
{
|
|
ElementRenderer::CameraElement *camera = GetElement();
|
|
Check_Object(camera);
|
|
|
|
//
|
|
//-----------------------
|
|
// Read the viewing state
|
|
//-----------------------
|
|
//
|
|
ElementRenderer::StateChange *view_states = camera->GetViewingStateChange();
|
|
Check_Object(view_states);
|
|
view_states->Load(stream, ElementRenderer::ReadERFVersion(stream));
|
|
|
|
//
|
|
//------------------------
|
|
// Set the clipping planes
|
|
//------------------------
|
|
//
|
|
Scalar angle;
|
|
*stream >> angle;
|
|
Check_Object(Mission::GetInstance());
|
|
const Mission::GameModel *model = Mission::GetInstance()->GetGameModel();
|
|
Check_Object(model);
|
|
|
|
//
|
|
//------------------
|
|
// Set the view port
|
|
//------------------
|
|
//
|
|
Scalar x_position;
|
|
Scalar y_position;
|
|
Scalar width;
|
|
Scalar height;
|
|
*stream >> x_position;
|
|
*stream >> y_position;
|
|
*stream >> width;
|
|
*stream >> height;
|
|
SetViewPort(x_position, y_position, width, height);
|
|
SetPerspective(model->m_nearClip, model->m_farClip, angle, (height/width)*0.75f);
|
|
|
|
//
|
|
//-------------------
|
|
// Load up the lights
|
|
//-------------------
|
|
//
|
|
ChainIteratorOf<gosFX::Light*> lights(&Mission::GetInstance()->m_staticLights);
|
|
gosFX::Light *light;
|
|
int i=0;
|
|
while ((light = lights.ReadAndNext()) != NULL)
|
|
{
|
|
Verify(i < ELEMENTS(view_states->m_lights));
|
|
view_states->m_lights[i++] = light->m_light;
|
|
}
|
|
view_states->m_lights[i] = NULL;
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Set up the sky element if there is one
|
|
//---------------------------------------
|
|
//
|
|
#if 0
|
|
const Mission::GameModel *mission_model = Mission::GetInstance()->GetGameModel();
|
|
Check_Object(mission_model);
|
|
#endif
|
|
|
|
*stream >> m_isMainSceneCamera;
|
|
*stream >> m_drawSky;
|
|
*stream >> m_LODOffset;
|
|
|
|
if(m_drawSky)
|
|
{
|
|
camera->DrawSky(true);
|
|
if(Mission::GetInstance()->m_isNightMission)
|
|
{
|
|
if(Mission::GetInstance()->m_nightSky.GetCurrent())
|
|
camera->AdoptSkyElement(Mission::GetInstance()->m_nightSky.GetCurrent());
|
|
}
|
|
else
|
|
{
|
|
if(Mission::GetInstance()->m_sky.GetCurrent())
|
|
camera->AdoptSkyElement(Mission::GetInstance()->m_sky.GetCurrent());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
camera->DrawSky(false);
|
|
}
|
|
|
|
|
|
//
|
|
//------------------------------------------
|
|
// Attach the camera to the renderer's scene
|
|
//------------------------------------------
|
|
//
|
|
|
|
VideoRenderer *renderer =
|
|
Cast_Object(VideoRenderer*, owning_web->GetRenderer());
|
|
if(m_isMainSceneCamera)
|
|
{
|
|
Element *root = renderer->GetSceneRoot();
|
|
Check_Object(root);
|
|
camera->SetScene(root);
|
|
renderer->SetCamera(const_cast<CameraComponent*>(this));
|
|
}
|
|
else
|
|
{
|
|
renderer->AddSecondaryCamera(const_cast<CameraComponent*>(this));
|
|
camera->SetSecondaryCamera();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraComponent*
|
|
CameraComponent::Make(
|
|
MemoryStream *stream,
|
|
VideoComponentWeb *owning_web,
|
|
Replicator *replicator
|
|
)
|
|
{
|
|
CameraComponent *camera =
|
|
new
|
|
CameraComponent(
|
|
DefaultData,
|
|
stream,
|
|
owning_web,
|
|
Cast_Object(Interface*, replicator)
|
|
);
|
|
return camera;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraComponent::~CameraComponent()
|
|
{
|
|
if (m_isMainSceneCamera && m_drawSky)
|
|
{
|
|
ElementRenderer::CameraElement *camera = GetElement();
|
|
Check_Object(camera);
|
|
camera->DeleteSky();
|
|
}
|
|
|
|
Check_Object(VideoRenderer::Instance);
|
|
if (VideoRenderer::Instance->GetSceneCamera() == this)
|
|
VideoRenderer::Instance->SetCamera(NULL);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraComponent::Execute()
|
|
{
|
|
//
|
|
//-------------------------------------------------------
|
|
// Get the camera and display, then clear the back buffer
|
|
//-------------------------------------------------------
|
|
//
|
|
ElementRenderer::LODElement::s_Offset -= m_LODOffset;
|
|
|
|
Check_Object(this);
|
|
ElementRenderer::CameraElement *camera = GetElement();
|
|
Check_Object(camera);
|
|
camera->DrawScene();
|
|
|
|
ElementRenderer::LODElement::s_Offset += m_LODOffset;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraComponent::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraComponent::ComputeEyeLine(
|
|
Line3D *eye_line,
|
|
const Vector2DOf<Scalar> &cursor
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(eye_line);
|
|
Check_Object(&cursor);
|
|
Verify(
|
|
cursor.x >= 0.0f && cursor.x <= 1.0f
|
|
&& cursor.y >= 0.0f && cursor.y <= 1.0f
|
|
);
|
|
|
|
//
|
|
//----------------------------------
|
|
// Figure out the near plane borders
|
|
//----------------------------------
|
|
//
|
|
ElementRenderer::CameraElement *camera = GetElement();
|
|
Check_Object(camera);
|
|
Scalar
|
|
left,
|
|
right,
|
|
up,
|
|
down,
|
|
n,
|
|
f;
|
|
camera->GetNearPlaneBorders(&left, &right, &up, &down, &n, &f);
|
|
Verify(n > SMALL);
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Figure out the point the near plane where the eye hits, the normalize
|
|
// the direction
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Vector3D eye_to_plane;
|
|
eye_to_plane.x = Lerp(left, right, cursor.x);
|
|
eye_to_plane.y = Lerp(up, down, cursor.y);
|
|
eye_to_plane.z = n;
|
|
UnitVector3D local_d(eye_to_plane);
|
|
|
|
//
|
|
//------------------------------------
|
|
// Transform this into the world space
|
|
//------------------------------------
|
|
//
|
|
const LinearMatrix4D &eye_to_world = camera->GetLocalToWorld();
|
|
eye_line->m_origin = eye_to_world;
|
|
eye_line->m_direction.Multiply(local_d, eye_to_world);
|
|
eye_line->m_length = f / local_d.z;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
CameraComponent::ComputeCursor(
|
|
Vector2DOf<Scalar> *cursor,
|
|
const Point3D &location
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(cursor);
|
|
Check_Object(&location);
|
|
|
|
//
|
|
//----------------------------------
|
|
// Figure out the near plane borders
|
|
//----------------------------------
|
|
//
|
|
ElementRenderer::CameraElement *camera = GetElement();
|
|
Check_Object(camera);
|
|
Scalar
|
|
left,
|
|
right,
|
|
up,
|
|
down,
|
|
n,
|
|
f;
|
|
camera->GetNearPlaneBorders(&left, &right, &up, &down, &n, &f);
|
|
Verify(n > SMALL);
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Transform the world point into camera space and project it unto the near
|
|
// viewing plane. If there is nothing to project, just take the points as
|
|
// they are
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
LinearMatrix4D world_to_eye;
|
|
world_to_eye.Invert(camera->GetLocalToWorld());
|
|
Point3D local_point;
|
|
local_point.Multiply(location, world_to_eye);
|
|
if (!Small_Enough(local_point.z))
|
|
{
|
|
Scalar scale = n / local_point.z;
|
|
local_point.x *= scale;
|
|
local_point.y *= scale;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Now figure out how far they are between the edges of the scene
|
|
//---------------------------------------------------------------
|
|
//
|
|
cursor->x = (local_point.x - left) / (right - left);
|
|
cursor->y = (local_point.y - up) / (down - up);
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Return true if the cursor is on screen
|
|
//---------------------------------------
|
|
//
|
|
return
|
|
cursor->x >= 0.0f && cursor->x <= 1.0f
|
|
&& cursor->y >= 0.0f && cursor->y <= 1.0f;
|
|
}
|