Files
firestorm/Gameleap/code/mw4/Code/MW4GameEd2/CameraController.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

693 lines
14 KiB
C++

#include "stdafx.h"
#include "cameracontroller.h"
#include "ObjectManager.h"
#include "GameInterface.h"
#include "DrawInfo.h"
#include "Refresher.h"
#include <MW4\MW4.hpp>
#include <MW4\MW4Headers.hpp>
#include <MW4\VehicleInterface.hpp>
const float rotate_size = -Stuff::Pi * 0.2f;
const float pitch_size = 0.4f;
const float zoom_size = 44.0f;
const float speed_size = 40.0f;
const float height_size = 20.0f;
const float default_speed = 80.0f;
const float default_height = 5;
CameraController* CameraController::m_Instance = 0;
#define REALSMALLRANGE 0.0000001f
CameraController::CameraController(ObjectManager& object_manager)
: m_ObjectManager(object_manager)
, m_LastCameraAnimateTime(0)
{
m_Speed=default_speed;
Verify(m_Instance == 0);
m_Instance = this;
LastTime=0.0f;
LookAtMode=false;
m_YawPitchRange.range=REALSMALLRANGE;
OldDistance=100.0f;
RBMode=false;
RevMouse=false;
TerrainFollow=true;
Reset();
}
CameraController::~CameraController()
{
Verify(m_Instance == this);
m_Instance = 0;
}
CameraController* CameraController::GetInstance()
{
return (m_Instance);
}
inline bool PointIsInsideBounds(const Stuff::Point3D& point, const Stuff::Point3D& map_size)
{
if((point.x >= map_size.x * 0.5f) ||
(point.z >= map_size.z * 0.5f) ||
(point.x < -map_size.x * 0.5f) ||
(point.z < -map_size.z * 0.5f))
{
return (false);
}
return (true);
}
bool CameraController::StaysInsideBounds(const Stuff::Point3D& new_point, const Stuff::YawPitchRange& new_ypr) const
{
if (PointIsInsideBounds(new_point,m_ObjectManager.GetMapSize()) == false)
{
return (false);
}
Stuff::LinearMatrix4D matrix(new_point);
matrix.BuildLookAt(new_ypr);
return (PointIsInsideBounds((Stuff::Point3D)matrix,m_ObjectManager.GetMapSize()));
}
void CameraController::PutPointInsideBounds(Stuff::Point3D& point)
{
Stuff::Point3D map_size(m_ObjectManager.GetMapSize());
Clamp(point.x,-map_size.x * 0.5f,map_size.x * 0.5f);
Clamp(point.z,-map_size.z * 0.5f,map_size.z * 0.5f);
}
void CameraController::PutYPRInsideBounds(Stuff::YawPitchRange& ypr)
{
if (StaysInsideBounds(m_LookAtPoint,ypr) == true)
{
return;
}
Stuff::YawPitchRange ypr2(ypr);
{for (Stuff::Scalar yaw_add = 0.1f;
yaw_add < (GetMaxYaw() * 0.5f) + 0.1f;
yaw_add += 0.1f)
{
{
ypr2.yaw = ypr.yaw + yaw_add;
if (StaysInsideBounds(m_LookAtPoint,ypr2) == true)
{
ypr = ypr2;
return;
}
}
{
ypr2.yaw = ypr.yaw - yaw_add;
if (StaysInsideBounds(m_LookAtPoint,ypr2) == true)
{
ypr = ypr2;
return;
}
}
}}
}
void CameraController::Update()
{
if (!GameInitilized)
return;
if ((Adept::Player::GetInstance() == 0) ||
(Adept::Player::GetInstance()->playerInterface == 0))
{
return;
}
PutPointInsideBounds(m_LookAtPoint);
PutYPRInsideBounds(m_YawPitchRange);
if (StaysInsideBounds(m_LookAtPoint,m_YawPitchRange) == false)
{
return;
}
Stuff::LinearMatrix4D matrix(m_LookAtPoint);
matrix.BuildLookAt(m_YawPitchRange);
Stuff::Point3D camera_pos(matrix);
if(TerrainFollow)
{
Stuff::Scalar terrain_height(ComputeTerrainElevation(camera_pos.x,camera_pos.z,0));
if (camera_pos.y < terrain_height + GetMinHeight())
{
camera_pos.y = terrain_height + GetMinHeight();
matrix.BuildTranslation(camera_pos);
}
}
Adept::Player::GetInstance()->SetNewLocalToParent(matrix);
Adept::Player::GetInstance()->SyncMatrices(true);
}
Stuff::YawPitchRange CameraController::GetYawPitchRange() const
{
return (m_YawPitchRange);
}
void CameraController::SetYawPitchRange(Stuff::YawPitchRange ypr)
{
Clamp(ypr.pitch,GetMinPitch(),GetMaxPitch());
m_YawPitchRange = ypr;
}
void CameraController::Reset()
{
m_YawPitchRange = Stuff::YawPitchRange(GetDefaultYaw(),GetDefaultPitch(),REALSMALLRANGE);
LookAtMode=false;
OldDistance=100.0f;
m_LookAtPoint = Stuff::Point3D(0,0,0);
m_Speed = default_speed;
m_Height = default_height;
// put camera in "editor view" mode
if (GameInitilized && (Adept::Player::GetInstance() != 0))
{
Adept::Interface* iface = Adept::Player::GetInstance()->playerInterface;
if ((iface != 0) &&
(iface->IsDerivedFrom(MechWarrior4::VehicleInterface::DefaultData) == true))
{
MechWarrior4::VehicleInterface* vehicle_interface = Cast_Object(VehicleInterface*,iface);
vehicle_interface->SetCameraMode(MechWarrior4::VehicleInterface::EditorCameraView);
}
}
m_LookAtPoint.y = ComputeTerrainElevation(m_LookAtPoint.x,m_LookAtPoint.z,0) + m_Height;
Update();
}
void CameraController::SetHeight(Stuff::Scalar height)
{
m_Height = height;
if(TerrainFollow)
m_LookAtPoint.y = ComputeTerrainElevation(m_LookAtPoint.x,m_LookAtPoint.z,0) + m_Height;
Update();
}
void CameraController::SetSpeed(Stuff::Scalar speed)
{
m_Speed = speed;
}
Stuff::Scalar CameraController::GetHeight() const
{
return (m_Height);
}
Stuff::Scalar CameraController::GetSpeed() const
{
return (m_Speed);
}
void CameraController::SetLookAt(const Stuff::Point3D& look_at, bool adjust_to_terrain)
{
m_LookAtPoint = look_at;
const Stuff::Scalar terrain_elevation(ComputeTerrainElevation(m_LookAtPoint.x,m_LookAtPoint.z,0));
if (adjust_to_terrain )
{
m_LookAtPoint.y = terrain_elevation + m_Height;
}
else
{
m_Height = m_LookAtPoint.y-terrain_elevation;
}
}
Stuff::Point3D CameraController::GetLookAt() const
{
return (m_LookAtPoint);
}
void CameraController::Draw(DrawInfo& dinf)
{
dinf.SetPen(DrawInfo::HelperPen);
CPoint start(dinf.vinf.DataToScreen(m_LookAtPoint));
Stuff::LinearMatrix4D matrix(m_LookAtPoint);
matrix.BuildLookAt(Stuff::YawPitchRange(m_YawPitchRange.yaw,m_YawPitchRange.pitch,GetLookAtMode()?m_YawPitchRange.range:-100.0f));
CPoint end(dinf.vinf.DataToScreen((Stuff::Point3D)matrix));
/*
RECT r;
dinf.GetDC()->GetClipBox(&r);
if ((start.x > r.right)||
(end.x > r.right) ||
(start.y > r.bottom) ||
(end.y > r.bottom))
{
return;
}
*/
/*
if(!GetLookAtMode())
{
int ydist,xdist;
ydist=end.y-start.y;
xdist=end.x-start.x;
end.y=(ydist*10)/xdist;
end.x=(xdist*10)/ydist;
}
*/
dinf.GetDC()->MoveTo(start);
dinf.GetDC()->LineTo(end);
{
const int circle_size(4);
CRect rect(start.x - circle_size,
start.y - circle_size,
start.x + circle_size,
start.y + circle_size);
dinf.GetDC()->Ellipse(&rect);
}
if(GetLookAtMode())
{
const int circle_size(6);
CRect rect(end.x - circle_size,
end.y - circle_size,
end.x + circle_size,
end.y + circle_size);
dinf.GetDC()->Ellipse(&rect);
}
}
float GetCurTime()
{
return GetTickCount()/1000.0f;
}
bool CameraController::ProcessIO()
{
Scalar new_time= GetCurTime();
Scalar frame_time=new_time-LastTime;
LastTime=new_time;
if(frame_time<(1/1000.0f)) frame_time=(1/1000.0f);
YawPitchRange ypr_offset(0,0,0);
Point3D offset(0,0,0);
bool yaw_changed = false;
bool poschanged=false;
if(GetLookAtMode())
{
if(GetAsyncKeyState('C') || GetAsyncKeyState('A'))
{
ypr_offset.yaw = rotate_size*frame_time;
poschanged=true;
}
if(GetAsyncKeyState('Z') || GetAsyncKeyState('D'))
{
ypr_offset.yaw = -rotate_size*frame_time;
poschanged=true;
}
if(GetAsyncKeyState(VK_SHIFT))
{
if(GetAsyncKeyState('S'))
{
ypr_offset.pitch = rotate_size*frame_time * pitch_size;
poschanged=true;
}
if(GetAsyncKeyState('W'))
{
ypr_offset.pitch = -rotate_size*frame_time * pitch_size;
poschanged=true;
}
}
else
{
if(GetAsyncKeyState('W'))
{
ypr_offset.range = -m_Speed * frame_time;
poschanged=true;
}
if(GetAsyncKeyState('S'))
{
ypr_offset.range = m_Speed * frame_time;
poschanged=true;
}
}
}
else
{
if(RBMode)
{
if(GetAsyncKeyState('W'))
{
TranslateForward(m_Speed*frame_time);
}
if(GetAsyncKeyState('S'))
{
TranslateForward(-m_Speed*frame_time);
}
}
else
{
if(GetAsyncKeyState(VK_SHIFT))
{
if(GetAsyncKeyState('W'))
{
m_Height += m_Speed * frame_time;
poschanged=true;
}
if(GetAsyncKeyState('S'))
{
m_Height -= m_Speed * frame_time;
poschanged=true;
}
}
else
{
if(GetAsyncKeyState('W'))
{
offset.z = m_Speed*frame_time;
poschanged=true;
}
if(GetAsyncKeyState('S'))
{
offset.z = -m_Speed*frame_time;
poschanged=true;
}
}
}
if(GetAsyncKeyState('A'))
{
offset.x = m_Speed*frame_time;
poschanged=true;
}
if(GetAsyncKeyState('D'))
{
offset.x = -m_Speed*frame_time;
poschanged=true;
}
}
if(GetAsyncKeyState('X'))
{
m_Height = default_height;
poschanged=true;
}
if(GetAsyncKeyState('E'))
{
ypr_offset.yaw = rotate_size*frame_time;
poschanged=true;
if(GetLookAtMode())
{
SetLookAtMode(false);
}
m_YawPitchRange.range=REALSMALLRANGE;
}
if(GetAsyncKeyState('Q'))
{
ypr_offset.yaw = -rotate_size*frame_time;
poschanged=true;
if(GetLookAtMode())
{
SetLookAtMode(false);
}
m_YawPitchRange.range=REALSMALLRANGE;
}
if(GetAsyncKeyState('R'))
{
ypr_offset.pitch = rotate_size*frame_time * pitch_size;
poschanged=true;
}
if(GetAsyncKeyState('F'))
{
ypr_offset.pitch = -rotate_size*frame_time * pitch_size;
poschanged=true;
}
Point3D new_point(m_LookAtPoint);
YawPitchRange new_ypr(m_YawPitchRange);
new_ypr.yaw+=ypr_offset.yaw;
new_ypr.pitch+=ypr_offset.pitch;
new_ypr.range+=ypr_offset.range;
while (new_ypr.yaw < 0)
{
new_ypr.yaw += Stuff::Two_Pi;
poschanged=true;
}
while (new_ypr.yaw > Stuff::Two_Pi)
{
new_ypr.yaw -= Stuff::Two_Pi;
poschanged=true;
}
if(poschanged)
{
Clamp(new_ypr.pitch,GetMinPitch(),GetMaxPitch());
Clamp(new_ypr.range,GetMinDistance(),GetMaxDistance());
Clamp(m_Height,GetMinHeight(),GetMaxHeight());
m_YawPitchRange = new_ypr;
LinearMatrix4D rotation(YawPitchRoll(m_YawPitchRange.yaw,0,0));
offset *= rotation;
new_point += offset;
if(!GetLookAtMode())
{
if(TerrainFollow && !RBMode)
new_point.y = ComputeTerrainElevation(new_point.x,new_point.z,0) + m_Height;
else
new_point.y = m_Height;
}
m_LookAtPoint=new_point;
}
Update();
return true;
}
void CameraController::SetLookAtMode(bool lmode)
{
if(LookAtMode && !lmode)
{
OldDistance=m_YawPitchRange.range;
m_YawPitchRange.range=REALSMALLRANGE;
TranslateForward(-OldDistance);
// LinearMatrix4D pos(),rot,trans;
LookAtMode=false;
}
else if(!LookAtMode && lmode)
{
LookAtMode=true;
m_YawPitchRange.range=OldDistance;
Point3D top_left,bottom_right;
if (m_ObjectManager.GetSelectionExtents(&top_left,&bottom_right))
{
Point3D center(top_left);
SetLookAt(center,false);
center += bottom_right;
center *= 0.5f;
}
}
}
Stuff::Scalar CameraController::GetCameraYaw() const
{
Stuff::Scalar rv(m_YawPitchRange.yaw + Stuff::Pi);
while (rv > Stuff::Two_Pi)
{
rv -= Stuff::Two_Pi;
}
return (rv);
}
void CameraController::SetCameraYaw(Stuff::Scalar yaw)
{
Stuff::LinearMatrix4D old_matrix(m_LookAtPoint);
old_matrix.BuildLookAt(m_YawPitchRange);
m_YawPitchRange.yaw = yaw - Stuff::Pi;
while (m_YawPitchRange.yaw < 0)
{
m_YawPitchRange.yaw += Stuff::Two_Pi;
}
Stuff::LinearMatrix4D new_matrix(m_LookAtPoint);
new_matrix.BuildLookAt(m_YawPitchRange);
Stuff::Point3D old_pos(old_matrix);
Stuff::Point3D new_pos(new_matrix);
Stuff::Point3D delta;
delta.Subtract(old_pos,new_pos);
Stuff::Point3D pos(m_LookAtPoint);
pos += delta;
SetLookAt(pos,TerrainFollow);
}
void CameraController::TranslateForward(float dist)
{
Stuff::LinearMatrix4D mat(m_LookAtPoint),tmat(Point3D(0,0,dist));
mat.BuildLookAt(m_YawPitchRange);
tmat*=mat;
Stuff::Point3D new_pos(tmat);
SetLookAt(new_pos,false);
// if(!TerrainFollow)
{
m_Height=new_pos.y;
}
}
void CameraController::UpdateCamera()
{
Point3D top_left,bottom_right;
if(GetLookAtMode())
{
if (m_ObjectManager.GetSelectionExtents(&top_left,&bottom_right))
{
Point3D center(top_left);
center += bottom_right;
center *= 0.5f;
SetLookAt(center,false);
}
else
{
SetLookAtMode(false);
}
}
}
void CameraController::SaveToReg()
{
CString wintitle="Camera";
gos_SaveDataToRegistry((char *)(LPCSTR)(wintitle+"TerrainFollow"),&TerrainFollow,sizeof(TerrainFollow));
gos_SaveDataToRegistry((char *)(LPCSTR)(wintitle+"RevMouse"),&RevMouse,sizeof(RevMouse));
gos_SaveDataToRegistry((char *)(LPCSTR)(wintitle+"Speed"),&m_Speed,sizeof(m_Speed));
}
void CameraController::LoadFromReg()
{
CString wintitle="Camera";
unsigned long size;
CRect rct;
size=sizeof(TerrainFollow);
gos_LoadDataFromRegistry((char *)(LPCSTR)(wintitle+"TerrainFollow"),&TerrainFollow,&size);
size=sizeof(RevMouse);
gos_LoadDataFromRegistry((char *)(LPCSTR)(wintitle+"RevMouse"),&RevMouse,&size);
size=sizeof(m_Speed);
gos_LoadDataFromRegistry((char *)(LPCSTR)(wintitle+"Speed"),&m_Speed,&size);
}
/*
LinearMatrix4D &CameraController::GetCameraMat()
{
Stuff::LinearMatrix4D matrix(m_LookAtPoint);
matrix.BuildLookAt(m_YawPitchRange);
return matrix;
}
void CameraController::SetCameraMat(LinearMatrix4D &mat)
{
m_LookAtPoint=mat;
m_Height=m_LookAtPoint.y-ComputeTerrainElevation(m_LookAtPoint.x,m_LookAtPoint.z,0);
if(GetLookAtMode())
{
}
}
*/