This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwphys/motorvehicle.h

226 lines
8.8 KiB
C
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWPhys *
* *
* $Archive:: /Commando/Code/wwphys/motorvehicle.h $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 10/22/01 5:52p $*
* *
* $Revision:: 18 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef MOTORVEHICLE_H
#define MOTORVEHICLE_H
#include "vehiclephys.h"
class MotorVehicleDefClass;
class LookupTableClass;
#define RPM_TO_RADS(x) ((x) * (2.0f * WWMATH_PI) / 60.0f)
#define RADS_TO_RPM(x) ((x) * 60.0f / (2.0f * WWMATH_PI))
/**
** MotorVehicleClass
** This is simply a RigidBodyClass with an internal "engine". In derived
** classes, the engine will propel the object in some way.
**
** NOTES:
** March 13,2000:
** --------------
** Adding an engine model which simulates the interaction between the engine speeding up
** and the wheel forces resisting, etc. The goal is to get the following behaviours:
** - when wheels aren't contacting the ground, the engine revs up
** - if the engine is revved up and the wheels come in contact, there is a reaction force
** - wheels can "peel out" in low gears if the parameters are set correctly
** - we have a parameter (EngineAngularVelocity) which can nicely drive a realistic engine sound
**
** To do this, I've added an EngineTorqueCurve which relates the rpm's of the engine
** to the torque it can output. This is transmitted to the drive wheels (equally distributed
** between them). The drive wheels "use up" as much of this torque as they can through
** friction forces on the ground. The net result of this is the amount that the engine
** angular velocity accelerates. In first gear for some vehicles, I'd like the engine to
** normally overpower friction and peel out but tune second and above to stay within the
** friction limits.
**
** (EngineTorque(EngineAngularVel) - ReactionTorque) / DriveTrainInertia = EngineAngularAccel
** ReactionTorque = MIN(EngineTorque,FrictionLimit)
** At higher speeds, something (DriveTrainInertia?) must bring EngineTorque down below
** FrictionLimit or we'll be peeling out again!
** Maybe just fake this: if (gear>1) roll wheels according to actual movement
**
** March 21, 2000:
** Driving engine RPMs the other direction. Normally, set the engine rpm to match the
** actual wheel speed.
*/
class MotorVehicleClass : public VehiclePhysClass
{
public:
MotorVehicleClass(void);
virtual ~MotorVehicleClass(void);
virtual MotorVehicleClass * As_MotorVehicleClass(void) { return this; }
void Init(const MotorVehicleDefClass & def);
virtual void Timestep(float dt);
// Accessors for the current state
float Get_Engine_Angular_Velocity(void) { return EngineAngularVelocity; }
float Get_Engine_RPM(void) { return RADS_TO_RPM(EngineAngularVelocity); }
float Get_Engine_Torque(void);
float Get_Axle_Angular_Velocity(void);
float Get_Axle_Torque(void);
float Get_Normalized_Engine_RPM(void); // for sound effects
int Get_Current_Gear(void) { return CurrentGear; }
bool Is_Braking(void) { return IsBraking; }
// Access to the constants for this motor vehicle
const MotorVehicleDefClass * Get_MotorVehicleDef(void);
float Get_Max_Engine_Torque(void);
// Save-Load system
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
protected:
// Actual vehicles must provide these methods
virtual float Get_Ideal_Drive_Axle_Angular_Velocity(void) = 0;
virtual bool Drive_Wheels_In_Contact(void) = 0;
// Integration system
virtual int Set_State(const StateVectorClass & new_state,int start_index);
// Internal engine simulation methods
float Compute_Engine_Angular_Acceleration(void);
void Shift_Up(void);
void Shift_Down(void);
// Variables
float EngineAngularVelocity; // This is a state variable to be integrated with the others
int CurrentGear;
float ShiftTimer; // delay in seconds between allowed shifting
float AcceleratorFraction; // amount of gas being given to the engine
bool IsBraking; // braking state
private:
// Not implemented..
MotorVehicleClass(const MotorVehicleClass &);
MotorVehicleClass & operator = (const MotorVehicleClass &);
};
inline const MotorVehicleDefClass * MotorVehicleClass::Get_MotorVehicleDef(void)
{
// All motor vehicles have to have definitions... Most of their parameters are only
// stored in the definition now...
WWASSERT(Definition != NULL);
return (MotorVehicleDefClass *)Definition;
}
/**
** MotorVehicleDefClass
** Initialization Structure/Factory/Editor Integration for a MotorVehicleClass
*/
class MotorVehicleDefClass : public VehiclePhysDefClass
{
public:
MotorVehicleDefClass(void);
virtual ~MotorVehicleDefClass(void);
// From PersistClass
virtual uint32 Get_Class_ID (void) const;
// From PhysDefClass
virtual const char * Get_Type_Name(void) { return "MotorVehicleDef"; }
virtual bool Is_Type(const char *);
// From PersistClass
virtual const PersistFactoryClass & Get_Factory (void) const;
virtual bool Save(ChunkSaveClass &csave);
virtual bool Load(ChunkLoadClass &cload);
// Read/Write access (DEBUGGING/TESTING ONLY)
float Get_Max_Engine_Torque(void) const { return MaxEngineTorque; }
int Get_Gear_Count(void) const { return GearCount; }
float Get_Gear_Ratio(int gear) const { return GearRatio[gear]; }
float Get_Shift_Up_Rpm(void) const { return ShiftUpRpm; }
float Get_Shift_Down_Rpm(void) const { return ShiftDownRpm; }
void Set_Max_Engine_Torque(float t) { MaxEngineTorque = t; }
void Set_Gear_Count(int count) { if ((count >= 0) && (count <= 5)) GearCount = count; }
void Set_Gear_Ratio(int gear,float ratio) { if ((gear >= 0) && (gear <= 5))GearRatio[gear] = ratio; }
void Set_Shift_Up_Rpm(float rpm) { ShiftUpRpm = rpm; ShiftUpAvel = RPM_TO_RADS(ShiftUpRpm); }
void Set_Shift_Down_Rpm(float rpm) { ShiftDownRpm = rpm; ShiftDownAvel = RPM_TO_RADS(ShiftDownRpm); }
// Editable interface requirements
DECLARE_EDITABLE(MotorVehicleDefClass,VehiclePhysDefClass);
protected:
// Engine response
float MaxEngineTorque;
StringClass EngineTorqueCurveFilename;
LookupTableClass * EngineTorqueCurve; // pointer to the torque curve
// Transmission and Differential Gear Ratios
enum { MAX_GEAR_COUNT = 6 };
int GearCount;
float GearRatio[MAX_GEAR_COUNT];
float PeakEngineTorque[MAX_GEAR_COUNT];
float FinalDriveGearRatio;
// Inertias in the drive train
float DriveTrainInertia;
// Shifting variables
float ShiftUpRpm;
float ShiftDownRpm;
float ShiftUpAvel; // same as ShiftUpRpm but in radians per second
float ShiftDownAvel; // same as ShiftDownRpm but in radians per second
friend class MotorVehicleClass;
};
#endif