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>
This commit is contained in:
+401
@@ -0,0 +1,401 @@
|
||||
#include "rp.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "thruster.h"
|
||||
#include "vtvmppr.h"
|
||||
#include "..\munga\boxsolid.h"
|
||||
#include "vtv.h"
|
||||
|
||||
//#############################################################################
|
||||
// Shared Data Support
|
||||
//
|
||||
Thruster::SharedData
|
||||
Thruster::DefaultData(
|
||||
Thruster::GetClassDerivations(),
|
||||
Thruster::GetMessageHandlers(),
|
||||
Thruster::GetAttributeIndex(),
|
||||
Thruster::StateCount
|
||||
);
|
||||
|
||||
Derivation* Thruster::GetClassDerivations()
|
||||
{
|
||||
static Derivation classDerivations(Subsystem::GetClassDerivations(), "Thruster");
|
||||
return &classDerivations;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Attribute Support
|
||||
//
|
||||
const Thruster::IndexEntry
|
||||
Thruster::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(Thruster, ThrusterOffset, thrusterOffset),
|
||||
ATTRIBUTE_ENTRY(Thruster, ThrusterPosition, thrusterPosition),
|
||||
ATTRIBUTE_ENTRY(Thruster, CurrentAcceleration, currentAcceleration),
|
||||
ATTRIBUTE_ENTRY(Thruster, CurrentHeight, currentHeight),
|
||||
ATTRIBUTE_ENTRY(Thruster, MaxThrusterRotationRate, maxThrusterRotationRate),
|
||||
ATTRIBUTE_ENTRY(Thruster, MomentArm, momentArm),
|
||||
ATTRIBUTE_ENTRY(Thruster, MomentArmLength, momentArmLength)
|
||||
};
|
||||
|
||||
Thruster::AttributeIndexSet& Thruster::GetAttributeIndex()
|
||||
{
|
||||
static Thruster::AttributeIndexSet attributeIndex(ELEMENTS(Thruster::AttributePointers),
|
||||
Thruster::AttributePointers,
|
||||
Subsystem::GetAttributeIndex()
|
||||
);
|
||||
return attributeIndex;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Model Support
|
||||
//
|
||||
void
|
||||
Thruster::PrimeThruster(Scalar time_slice)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get pointers to the other subsystems we will have to deal with inside the
|
||||
// VTV
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
if (vtv->GetSimulationState() == VTV::BurningState)
|
||||
{
|
||||
Check_Fpu();
|
||||
return;
|
||||
}
|
||||
|
||||
VTVControlsMapper* controls =
|
||||
Cast_Object(
|
||||
VTVControlsMapper*,
|
||||
vtv->GetSubsystem(VTV::ControlsMapperSubsystem)
|
||||
);
|
||||
Check(controls);
|
||||
Vector3D power_demand = controls->powerDemand;
|
||||
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// Rotate the engines so that they can match to power demand requests
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
Scalar desire,new_rad;
|
||||
if (
|
||||
controls->controlMode == VTVControlsMapper::BasicMode
|
||||
&& Small_Enough(vtv->localVelocity.linearMotion.z, 1.0f)
|
||||
)
|
||||
{
|
||||
desire = 0.0f;
|
||||
}
|
||||
else if (Small_Enough(power_demand.z) && Small_Enough(power_demand.y))
|
||||
{
|
||||
desire = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
desire = Arctan(power_demand.z, power_demand.y);
|
||||
}
|
||||
|
||||
Check(thrusterPosition);
|
||||
if (thrusterPosition->GetRadians() < desire)
|
||||
{
|
||||
new_rad =
|
||||
thrusterPosition->GetRadians()
|
||||
+ time_slice * maxThrusterRotationRate;
|
||||
Max_Clamp(new_rad, desire);
|
||||
vtv->thrusterAngle = new_rad;
|
||||
}
|
||||
else if (thrusterPosition->GetRadians() > desire)
|
||||
{
|
||||
new_rad =
|
||||
thrusterPosition->GetRadians()
|
||||
- time_slice * maxThrusterRotationRate;
|
||||
Min_Clamp(new_rad, desire);
|
||||
vtv->thrusterAngle = new_rad;
|
||||
}
|
||||
thrusterPosition->SetRotation(vtv->thrusterAngle);
|
||||
|
||||
if (!Close_Enough(desire, updatedPosition, 10.0f*RAD_PER_DEG))
|
||||
{
|
||||
ForceUpdate();
|
||||
updatedPosition = desire;
|
||||
}
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// Calculate the vertical thrust based upon the height of each engine
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
Verify(vtv->GetMoverCollisionRoot());
|
||||
BoundingBoxTreeNode *tree = vtv->GetMoverCollisionRoot();
|
||||
|
||||
currentHeight = 0.0f;
|
||||
Point3D test_point;
|
||||
test_point.Multiply(thrusterOffset, vtv->localToWorld);
|
||||
tree->FindBoundingBoxUnder(test_point, ¤tHeight);
|
||||
|
||||
Vector3D force;
|
||||
force.Multiply(power_demand, currentAcceleration);
|
||||
if (power_demand.y > SMALL)
|
||||
{
|
||||
Vector3D ge = Vector3D::Identity;
|
||||
ge.y =
|
||||
vtv->groundEffectRange * power_demand.y * powerScale
|
||||
/ (1.0f + vtv->groundEffectDomainSquared*currentHeight*currentHeight);
|
||||
Check_Fpu();
|
||||
Vector3D local_ge;
|
||||
local_ge.MultiplyByInverse(ge, vtv->localToWorld);
|
||||
force += local_ge;
|
||||
}
|
||||
#if defined(WOOBLY)
|
||||
vtv->ApplyLocalAcceleration(force, momentArm);
|
||||
#else
|
||||
vtv->localAcceleration.linearMotion += force;
|
||||
#endif
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Thruster::SlaveThruster(Scalar)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get pointers to the other subsystems we will have to deal with inside the
|
||||
// VTV
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
if (vtv->GetSimulationState() == VTV::BurningState)
|
||||
{
|
||||
Check_Fpu();
|
||||
return;
|
||||
}
|
||||
|
||||
VTVControlsMapper* controls =
|
||||
Cast_Object(
|
||||
VTVControlsMapper*,
|
||||
vtv->GetSubsystem(VTV::ControlsMapperSubsystem)
|
||||
);
|
||||
Check(controls);
|
||||
Vector3D power_demand = controls->powerDemand;
|
||||
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// Rotate the engines so that they can match to power demand requests
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
thrusterPosition->SetRotation(vtv->thrusterAngle);
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------
|
||||
// Calculate the vertical thrust based upon the height of each engine
|
||||
//-------------------------------------------------------------------
|
||||
//
|
||||
Verify(vtv->GetMoverCollisionRoot());
|
||||
BoundingBoxTreeNode *tree = vtv->GetMoverCollisionRoot();
|
||||
|
||||
currentHeight = 0.0f;
|
||||
Point3D test_point;
|
||||
test_point.Multiply(thrusterOffset, vtv->localToWorld);
|
||||
tree->FindBoundingBoxUnder(test_point, ¤tHeight);
|
||||
|
||||
Vector3D force;
|
||||
force.Multiply(power_demand, currentAcceleration);
|
||||
if (power_demand.y > SMALL)
|
||||
{
|
||||
Vector3D ge = Vector3D::Identity;
|
||||
ge.y =
|
||||
vtv->groundEffectRange * power_demand.y * powerScale
|
||||
/ (1.0f + vtv->groundEffectDomainSquared*currentHeight*currentHeight);
|
||||
Check_Fpu();
|
||||
Vector3D local_ge;
|
||||
local_ge.MultiplyByInverse(ge, vtv->localToWorld);
|
||||
force += local_ge;
|
||||
}
|
||||
#if defined(WOOBLY)
|
||||
vtv->ApplyLocalAcceleration(force, momentArm);
|
||||
#else
|
||||
vtv->localAcceleration.linearMotion += force;
|
||||
#endif
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// Model Support
|
||||
//
|
||||
void
|
||||
Thruster::PrimeDeadReckon(Scalar time_slice)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get pointers to the other subsystems we will have to deal with inside the
|
||||
// VTV
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
if (vtv->GetSimulationState() == VTV::BurningState)
|
||||
{
|
||||
Check_Fpu();
|
||||
return;
|
||||
}
|
||||
|
||||
Check(thrusterPosition);
|
||||
Scalar new_rad;
|
||||
if (thrusterPosition->GetRadians() < updatedPosition)
|
||||
{
|
||||
new_rad =
|
||||
thrusterPosition->GetRadians()
|
||||
+ time_slice * maxThrusterRotationRate;
|
||||
Max_Clamp(new_rad, updatedPosition);
|
||||
vtv->thrusterAngle = new_rad;
|
||||
}
|
||||
else if (thrusterPosition->GetRadians() > updatedPosition)
|
||||
{
|
||||
new_rad =
|
||||
thrusterPosition->GetRadians()
|
||||
- time_slice * maxThrusterRotationRate;
|
||||
Min_Clamp(new_rad, updatedPosition);
|
||||
vtv->thrusterAngle = new_rad;
|
||||
}
|
||||
thrusterPosition->SetRotation(vtv->thrusterAngle);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Thruster::SlaveDeadReckon(Scalar)
|
||||
{
|
||||
Check(this);
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
// Get pointers to the other subsystems we will have to deal with inside the
|
||||
// VTV
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
VTV* vtv = GetEntity();
|
||||
Check(vtv);
|
||||
if (vtv->GetSimulationState() == VTV::BurningState)
|
||||
{
|
||||
Check_Fpu();
|
||||
return;
|
||||
}
|
||||
|
||||
thrusterPosition->SetRotation(vtv->thrusterAngle);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Thruster::ReadUpdateRecord(Simulation::UpdateRecord *message)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
Subsystem::ReadUpdateRecord(message);
|
||||
UpdateRecord* record = (UpdateRecord*) message;
|
||||
|
||||
updatedPosition = record->thrusterRotation;
|
||||
|
||||
Check_Fpu();
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
void
|
||||
Thruster::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(record);
|
||||
|
||||
Subsystem::WriteUpdateRecord(record, update_model);
|
||||
UpdateRecord* update = (UpdateRecord*) record;
|
||||
|
||||
update->recordLength = sizeof(*update);
|
||||
update->thrusterRotation = updatedPosition;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Thruster::Thruster(
|
||||
VTV *owner,
|
||||
int subsystem_ID,
|
||||
SubsystemResource *subsystem_resource
|
||||
):
|
||||
Subsystem(owner, subsystem_ID, subsystem_resource, DefaultData)
|
||||
{
|
||||
if (owner->GetInstance() != VTV::ReplicantInstance)
|
||||
{
|
||||
if (subsystem_resource->primeThruster)
|
||||
{
|
||||
SetPerformance(&Thruster::PrimeThruster);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPerformance(&Thruster::SlaveThruster);
|
||||
}
|
||||
}
|
||||
else if (subsystem_resource->primeThruster)
|
||||
{
|
||||
SetPerformance(&Thruster::PrimeDeadReckon);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPerformance(&Thruster::SlaveDeadReckon);
|
||||
}
|
||||
|
||||
//
|
||||
// Get the offset from the linear matrix by peeliong
|
||||
// off the translation part
|
||||
//
|
||||
EntitySegment *segment = owner->GetSegment(segmentIndex);
|
||||
momentArm = thrusterOffset = segment->GetBaseOffset();
|
||||
|
||||
thrusterOffset.y = owner->GetCollisionTemplate()->minY;
|
||||
momentArm.y = 0.0f;
|
||||
momentArmLength = momentArm.Length();
|
||||
powerScale = 0.0f;
|
||||
//
|
||||
// Get the thruster position from the joint subsystem of the VTV
|
||||
//
|
||||
JointSubsystem *joint_subsystem = owner->GetJointSubsystem();
|
||||
Check(joint_subsystem);
|
||||
|
||||
thrusterPosition = joint_subsystem->GetJoint(subsystem_resource->jointIndex);
|
||||
|
||||
currentAcceleration = 0.0f;
|
||||
currentHeight = 0.0f;
|
||||
maxThrusterRotationRate = subsystem_resource->maxThrusterRotationRate;
|
||||
updatedPosition = 0.0f;
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Thruster::~Thruster()
|
||||
{
|
||||
Check(this);
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
Logical
|
||||
Thruster::TestInstance() const
|
||||
{
|
||||
return IsDerivedFrom(*GetClassDerivations());
|
||||
}
|
||||
Reference in New Issue
Block a user