Files
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

733 lines
18 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "camship.h"
#include "player.h"
#include "mission.h"
#include "cammppr.h"
#include "app.h"
#include "hostmgr.h"
//##########################################################################
//############################# CameraShip ################################
//##########################################################################
//#############################################################################
// Shared Data Support
//
Derivation* CameraShip::GetClassDerivations()
{ static Derivation classDerivations(Mover::GetClassDerivations(), "CameraShip");
return &classDerivations;
}
CameraShip::SharedData
CameraShip::DefaultData(
CameraShip::GetClassDerivations(),
CameraShip::MessageHandlers,
CameraShip::GetAttributeIndex(),
CameraShip::StateCount,
(Entity::MakeHandler)CameraShip::Make
);
//#############################################################################
// Attribute Support
//
const CameraShip::IndexEntry
CameraShip::AttributePointers[]=
{
ATTRIBUTE_ENTRY(CameraShip, MapRange, mapRange),
ATTRIBUTE_ENTRY(CameraShip, MapLinearPosition, mapLinearPosition),
ATTRIBUTE_ENTRY(CameraShip, MapAngularPosition, mapAngularPosition)
};
CameraShip::AttributeIndexSet& CameraShip::GetAttributeIndex()
{
static CameraShip::AttributeIndexSet attributeIndex(ELEMENTS(CameraShip::AttributePointers),
CameraShip::AttributePointers,
Mover::GetAttributeIndex()
);
return attributeIndex;
}
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
CameraShip::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(CameraShip, Direction)
};
CameraShip::MessageHandlerSet
CameraShip::MessageHandlers(
ELEMENTS(CameraShip::MessageHandlerEntries),
CameraShip::MessageHandlerEntries,
Entity::GetMessageHandlers()
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DirectionMessageHandler(DirectionMessage *message)
{
Check(this);
Check(message);
Check(application);
HostManager *host = application->GetHostManager();
Check(host);
SetGoalEntity(host->GetEntityPointer(message->goalEntity));
Check(goalEntity);
mapLinearPosition = &goalEntity->localOrigin.linearPosition;
focusOffset = message->focusOffset;
SetSimulationState(DefaultState);
timeOnCamera = message->timeOnCamera;
lastSwitch = Now();
lastSwitch -= timeOnCamera;
Check_Fpu();
}
//#############################################################################
// ControlsMapper Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::SetMappingSubsystem(CameraControlsMapper *mapper)
{
Check(this);
Check(mapper);
if(subsystemArray[ControlsMapperSubsystem])
{
Unregister_Object(subsystemArray[ControlsMapperSubsystem]);
delete subsystemArray[ControlsMapperSubsystem];
}
subsystemArray[ControlsMapperSubsystem] = mapper;
Check_Fpu();
}
//#############################################################################
// Simulation Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DriveCamera(Scalar time_slice)
{
Check(this);
CameraControlsMapper* controls =
Cast_Object(
CameraControlsMapper*,
GetSubsystem(CameraShip::ControlsMapperSubsystem)
);
Check(controls);
//
//-----------------------------------------------
// If we are in positioning mode, move the camera
//-----------------------------------------------
//
if (controls->driveCamera > 0)
{
ApplyControlledPanAndTilt(controls, time_slice);
ApplyControlledCameraMotion(controls, time_slice);
ApplyControlledCameraHeight(controls);
currentCamera->SetLocalOrigin(localOrigin);
}
//
//------------------------------------------------------------------------
// Operate in camera mode, obeying the limits of the camera as established
// by the clamps
//------------------------------------------------------------------------
//
else
{
//
//-------------------------
// Stop any existing motion
//-------------------------
//
worldLinearVelocity = Vector3D::Identity;
//
//-----------------------------------------------------------------------
// Read the controls for panning the camera, and if the clamp override is
// on, tell the camera to allow this orientation
//-----------------------------------------------------------------------
//
ApplyControlledPanAndTilt(controls, time_slice);
localToWorld = localOrigin;
//
//---------------------------------------------------------------------
// Establish an aim point along negative Z and figure out where that is
// in world space, then point the camera there. The camera clamps will
// automatically do their thing
//---------------------------------------------------------------------
//
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
if (controls->slideOrClamp > 0)
{
currentCamera->AllowLookingAt(world_aim);
}
AimCameraAtPoint(world_aim);
}
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledPanAndTilt(
CameraControlsMapper *controls,
Scalar time_slice
)
{
Check(this);
Check(controls);
//
//-----------------------------------------
// Point the Camera in the direction of the
// Joystick Position Calc Pitch and Yaw only
//-----------------------------------------
//
Scalar rotation_amount;
if(controls->stickPosition.x < -0.02f)
{
rotation_amount = controls->stickPosition.x + 0.02f;
rotation_amount *= rotation_amount;
rotation_amount *= -1.0f;
}
else if (controls->stickPosition.x > 0.02f)
{
rotation_amount = controls->stickPosition.x - 0.02f;
rotation_amount *= rotation_amount;
}
else
{
rotation_amount = 0.0f;
}
YawPitchRoll ypr;
ypr = localOrigin.angularPosition;
ypr.yaw += rotation_amount * PI * time_slice;
ypr.pitch += controls->stickPosition.y * PI * 0.2f * time_slice;
localOrigin.angularPosition = ypr;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledCameraHeight(CameraControlsMapper *controls)
{
Check(this);
Check(controls);
//
//----------------------------------------------------
// Raise and lower the cameraShip according to the pedals
//----------------------------------------------------
//
localOrigin.linearPosition.y += controls->pedalsPosition;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledCameraMotion(
CameraControlsMapper *controls,
Scalar time_slice
)
{
Check(this);
Check(controls);
localAcceleration.linearMotion.z =
-25.0f * controls->throttlePosition * time_slice;
if (controls->reverseThrust > 0)
{
localAcceleration.linearMotion.z = -localAcceleration.linearMotion.z;
}
//
//~~~~~~~~~~~~~~~~~~~
// Apply Linear Drag
//~~~~~~~~~~~~~~~~~~~
//
Vector3D drag_force;
drag_force.Multiply(
localVelocity.linearMotion,
positiveLinearDragCoefficients
);
Vector3D new_accel;
new_accel.Subtract(
localAcceleration.linearMotion,
drag_force
);
localAcceleration.linearMotion = new_accel;
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// ApplyWorldAccelerations
//~~~~~~~~~~~~~~~~~~~~~~~~
localVelocity.linearMotion += localAcceleration.linearMotion;
worldLinearVelocity.Multiply(
localVelocity.linearMotion,
localToWorld
);
localOrigin.linearPosition += worldLinearVelocity;
Check_Fpu();
}
//#############################################################################
// Follow GoalEntity Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::FollowGoal(Scalar time_slice)
{
Check(this);
//
//-----------------------------------------------
// If no goalEntity assigned ask for one and wait
//-----------------------------------------------
//
if (!goalEntity)
{
return;
}
Check(goalEntity);
Point3D target;
target.Multiply(focusOffset, goalEntity->localToWorld);
//
//------------------------------------------------------------------------
// If time has not yet expired on this camera, keep with it if can see the
// goal entity
//------------------------------------------------------------------------
//
Check(currentCamera);
if (
lastPerformance - lastSwitch > timeOnCamera
|| !currentCamera->CanCameraSee(target)
)
{
CameraInstance *old_camera = currentCamera;
GoToClosestCamera(target);
if (!currentCamera)
{
currentCamera = old_camera;
}
Check(currentCamera);
//
//------------------------------------------------------------------------
// If we need to switch cameras, have the new camera point directly at the
// target
//------------------------------------------------------------------------
//
if (currentCamera != old_camera)
{
AimCameraAtPoint(target);
lastSwitch = lastPerformance;
}
else
{
goto Rotate_Camera;
}
}
//
//---------------------------------------------------
// Otherwise, rotate the camera as needed and allowed
//---------------------------------------------------
//
else
{
Rotate_Camera:
RotateCameraToPoint(time_slice, target);
}
//
//------------------------
// Set the tranform matrix
//------------------------
//
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::GoToClosestCamera(const Point3D &point_3D)
{
Check(this);
currentCamera = cameraManager.FindClosestCamera(point_3D);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::AimCameraAtPoint(const Point3D &point_3D)
{
Check(this);
Check(currentCamera);
currentCamera->LookAt(&localOrigin, point_3D);
localVelocity.angularMotion = Vector3D::Identity;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::RotateCameraToPoint(
Scalar time_slice,
const Point3D &point_3D
)
{
Check(this);
Check(currentCamera);
Check(&point_3D);
//
//---------------------------------------------------------
// Calculate the rotation needed to point to the goalEntity
//---------------------------------------------------------
//
Origin target;
currentCamera->LookAt(&target, point_3D);
YawPitchRoll new_yaw_pitch_roll;
new_yaw_pitch_roll = target.angularPosition;
Vector3D new_pos(new_yaw_pitch_roll.pitch, new_yaw_pitch_roll.yaw, 0.0f);
YawPitchRoll old_pos_euler;
old_pos_euler = localOrigin.angularPosition;
Vector3D old_pos(old_pos_euler.pitch, old_pos_euler.yaw, 0.0f);
old_pos.x = Radian::Normalize(old_pos.x);
old_pos.y = Radian::Normalize(old_pos.y);
//
// new - old position
//
if (new_pos.x-old_pos.x > PI) {
new_pos.x -= TWO_PI;
}
else if (new_pos.x-old_pos.x < -PI) {
new_pos.x += TWO_PI;
}
if (new_pos.y-old_pos.y > PI) {
new_pos.y -= TWO_PI;
}
else if (new_pos.y-old_pos.y < -PI) {
new_pos.y += TWO_PI;
}
Vector3D delta_rot;
delta_rot.Subtract(
new_pos,
old_pos
);
//
//-------------------
// Apply Angular Drag
//-------------------
//
Vector3D
drag;
drag.Multiply(
localVelocity.angularMotion,
angularDragCoefficients
);
//
//~~~~~~~~~~~~~~~~~~~~~
// Apply SpringConstant
//~~~~~~~~~~~~~~~~~~~~~
//
Vector3D
delta_rot_spring;
delta_rot_spring.Multiply(
delta_rot,
elasticityCoefficient
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Calculate the new angular acceleration
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
localAcceleration.angularMotion.Subtract(
delta_rot_spring,
drag
);
Scalar halft_squared = 0.5 *(time_slice * time_slice);
Vector3D
accel_comp;
accel_comp.Multiply(
localAcceleration.angularMotion,
halft_squared
);
//
// velocity * delta time
//
Vector3D
scaled_velocity;
scaled_velocity.Multiply(
localVelocity.angularMotion,
time_slice
);
Vector3D
tmp_position;
tmp_position.Add(
scaled_velocity,
accel_comp
);
Vector3D
clamped_accel;
clamped_accel.Add(
old_pos,
tmp_position
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Apply Acceleration to angular Position
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
YawPitchRoll
new_yawpitchroll(clamped_accel.y, clamped_accel.x, clamped_accel.z);
LinearMatrix
rot_matrix(LinearMatrix::Identity);
rot_matrix = new_yawpitchroll;
localOrigin.angularPosition = rot_matrix;
//
// Calc new Velocity
//
Vector3D
scaled_accel;
scaled_accel.Multiply(
localAcceleration.angularMotion,
time_slice
);
Vector3D
ang_vel;
ang_vel.Add(
localVelocity.angularMotion,
scaled_accel
);
localVelocity.angularMotion = ang_vel;
Check_Fpu();
}
//#############################################################################
// CameraInstanceManager Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::CreateCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.CreateCameraInstance(localOrigin);
DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DeleteCameraInstance()
{
Check(this);
//
//---------------------------------------------
// If this is the last camera, don't delete it!
//---------------------------------------------
//
Check(&cameraManager);
CameraInstance *next_camera = cameraManager.IncrementIterator();
if (next_camera == currentCamera)
{
return;
}
currentCamera = cameraManager.DeleteCameraInstance();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::IncrementCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.IncrementIterator();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DecrementCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.DecrementIterator();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//#############################################################################
// Motion Support Functions
//
//#############################################################################
// Construction and Destruction Support
//
CameraShip::CameraShip(
CameraShip::MakeMessage *creation_message,
CameraShip::SharedData &virtual_data
):
Mover(creation_message, virtual_data)
{
SetValidFlag();
if (GetInstance() == ReplicantInstance)
{
return;
}
//
//----------------------------
// Initialize local variables
//----------------------------
//
goalEntity = NULL;
localOrigin = Origin::Identity;
focusOffset = Vector3D::Identity;
//
//------------------------------
// Initialize attributes
//------------------------------
//
mapRange = 1000.0; // number of meters across display
mapLinearPosition = NULL; // force nav display to use object's lin. pos
mapAngularPosition = NULL; // force nav display to not turn or tilt
//
//------------------------------
// Initialize the subsystemArray
//------------------------------
//
subsystemCount = BasicSubsystemCount;
Verify(!subsystemArray);
subsystemArray = new (Subsystem (*[subsystemCount]));
Register_Pointer(subsystemArray);
subsystemArray[ControlsMapperSubsystem] = NULL;
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize the camera's viewpoint to the first camera
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
currentCamera = cameraManager.GetCurrent();
if (!currentCamera)
{
CreateCameraInstance();
}
Check(currentCamera);
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
lastSwitch = Now();
timeOnCamera = 0.0f;
SetPerformance(&CameraShip::FollowGoal);
SetSimulationState(DefaultState);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraShip*
CameraShip::Make(MakeMessage *creation_message)
{
return new CameraShip(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraShip::~CameraShip()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraShip::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}