Add option for WheeledVehicle drive type
This commit is contained in:
@@ -11,7 +11,9 @@
|
||||
#endif
|
||||
#if WITH_VEHICLE
|
||||
#include <ThirdParty/PhysX/vehicle/PxVehicleSDK.h>
|
||||
#include <ThirdParty/PhysX/vehicle/PxVehicleNoDrive.h>
|
||||
#include <ThirdParty/PhysX/vehicle/PxVehicleDrive4W.h>
|
||||
#include <ThirdParty/PhysX/vehicle/PxVehicleDriveNW.h>
|
||||
#include <ThirdParty/PhysX/vehicle/PxVehicleUtilSetup.h>
|
||||
#include <ThirdParty/PhysX/PxFiltering.h>
|
||||
#endif
|
||||
@@ -21,12 +23,47 @@ extern void InitVehicleSDK();
|
||||
extern Array<WheeledVehicle*> WheelVehicles;
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void FreeDrive(WheeledVehicle::DriveTypes driveType, PxVehicleWheels* drive)
|
||||
{
|
||||
switch (driveType)
|
||||
{
|
||||
case WheeledVehicle::DriveTypes::Drive4W:
|
||||
((PxVehicleDrive4W*)drive)->free();
|
||||
break;
|
||||
case WheeledVehicle::DriveTypes::DriveNW:
|
||||
((PxVehicleDriveNW*)drive)->free();
|
||||
break;
|
||||
case WheeledVehicle::DriveTypes::NoDrive:
|
||||
((PxVehicleNoDrive*)drive)->free();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WheeledVehicle::WheeledVehicle(const SpawnParams& params)
|
||||
: RigidBody(params)
|
||||
{
|
||||
_useCCD = 1;
|
||||
}
|
||||
|
||||
WheeledVehicle::DriveTypes WheeledVehicle::GetDriveType() const
|
||||
{
|
||||
return _driveType;
|
||||
}
|
||||
|
||||
void WheeledVehicle::SetDriveType(DriveTypes value)
|
||||
{
|
||||
if (_driveType == value)
|
||||
return;
|
||||
_driveType = value;
|
||||
if (IsDuringPlay())
|
||||
{
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
|
||||
const Array<WheeledVehicle::Wheel>& WheeledVehicle::GetWheels() const
|
||||
{
|
||||
return _wheels;
|
||||
@@ -49,7 +86,7 @@ WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const
|
||||
void WheeledVehicle::SetGearbox(const GearboxSettings& value)
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||
auto& drive = (PxVehicleDrive*&)_drive;
|
||||
if (drive)
|
||||
{
|
||||
drive->mDriveDynData.setUseAutoGears(value.AutoGear);
|
||||
@@ -90,7 +127,7 @@ void WheeledVehicle::ClearInput()
|
||||
float WheeledVehicle::GetForwardSpeed() const
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (const PxVehicleDrive4W*&)_drive;
|
||||
auto& drive = (const PxVehicleWheels*&)_drive;
|
||||
return drive ? drive->computeForwardSpeed() : 0.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
@@ -100,7 +137,7 @@ float WheeledVehicle::GetForwardSpeed() const
|
||||
float WheeledVehicle::GetSidewaysSpeed() const
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (const PxVehicleDrive4W*&)_drive;
|
||||
auto& drive = (const PxVehicleWheels*&)_drive;
|
||||
return drive ? drive->computeSidewaysSpeed() : 0.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
@@ -110,8 +147,8 @@ float WheeledVehicle::GetSidewaysSpeed() const
|
||||
float WheeledVehicle::GetEngineRotationSpeed() const
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (const PxVehicleDrive4W*&)_drive;
|
||||
return drive ? RadPerSToRpm(drive->mDriveDynData.getEngineRotationSpeed()) : 0.0f;
|
||||
auto& drive = (const PxVehicleDrive*&)_drive;
|
||||
return drive && _driveType != DriveTypes::NoDrive ? RadPerSToRpm(drive->mDriveDynData.getEngineRotationSpeed()) : 0.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
@@ -120,8 +157,8 @@ float WheeledVehicle::GetEngineRotationSpeed() const
|
||||
int32 WheeledVehicle::GetCurrentGear() const
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (const PxVehicleDrive4W*&)_drive;
|
||||
return drive ? (int32)drive->mDriveDynData.getCurrentGear() - 1 : 0;
|
||||
auto& drive = (const PxVehicleDrive*&)_drive;
|
||||
return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getCurrentGear() - 1 : 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -130,8 +167,8 @@ int32 WheeledVehicle::GetCurrentGear() const
|
||||
void WheeledVehicle::SetCurrentGear(int32 value)
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||
if (drive)
|
||||
auto& drive = (PxVehicleDrive*&)_drive;
|
||||
if (drive && _driveType != DriveTypes::NoDrive)
|
||||
{
|
||||
drive->mDriveDynData.forceGearChange((PxU32)(value + 1));
|
||||
}
|
||||
@@ -141,8 +178,8 @@ void WheeledVehicle::SetCurrentGear(int32 value)
|
||||
int32 WheeledVehicle::GetTargetGear() const
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (const PxVehicleDrive4W*&)_drive;
|
||||
return drive ? (int32)drive->mDriveDynData.getTargetGear() - 1 : 0;
|
||||
auto& drive = (const PxVehicleDrive*&)_drive;
|
||||
return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getTargetGear() - 1 : 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -151,8 +188,8 @@ int32 WheeledVehicle::GetTargetGear() const
|
||||
void WheeledVehicle::SetTargetGear(int32 value)
|
||||
{
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||
if (drive)
|
||||
auto& drive = (PxVehicleDrive*&)_drive;
|
||||
if (drive && _driveType != DriveTypes::NoDrive)
|
||||
{
|
||||
drive->mDriveDynData.startGearChange((PxU32)(value + 1));
|
||||
}
|
||||
@@ -180,13 +217,13 @@ void WheeledVehicle::Setup()
|
||||
#if WITH_VEHICLE
|
||||
if (!_actor)
|
||||
return;
|
||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||
auto& drive = (PxVehicleWheels*&)_drive;
|
||||
|
||||
// Release previous
|
||||
if (drive)
|
||||
{
|
||||
WheelVehicles.Remove(this);
|
||||
drive->free();
|
||||
FreeDrive(_driveTypeCurrent, drive);
|
||||
drive = nullptr;
|
||||
}
|
||||
|
||||
@@ -270,15 +307,15 @@ void WheeledVehicle::Setup()
|
||||
wheelData.mDampingRate = M2ToCm2(0.25f);
|
||||
switch (wheel.Type)
|
||||
{
|
||||
case WheelType::FrontLeft:
|
||||
case WheelType::FrontRight:
|
||||
case WheelTypes::FrontLeft:
|
||||
case WheelTypes::FrontRight:
|
||||
// Enable steering for the front wheels only
|
||||
// TODO: expose as settings
|
||||
wheelData.mMaxSteer = PI * 0.3333f;
|
||||
wheelData.mMaxSteer = PI * 0.3333f;
|
||||
break;
|
||||
case WheelType::RearLeft:
|
||||
case WheelType::ReadRight:
|
||||
case WheelTypes::RearLeft:
|
||||
case WheelTypes::ReadRight:
|
||||
// Enable the handbrake for the rear wheels only
|
||||
// TODO: expose as settings
|
||||
wheelData.mMaxHandBrakeTorque = M2ToCm2(4000.0f);
|
||||
@@ -342,9 +379,14 @@ void WheeledVehicle::Setup()
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize vehicle drive simulation data
|
||||
PxVehicleDriveSimData4W driveSimData;
|
||||
// Initialize vehicle drive
|
||||
_driveTypeCurrent = _driveType;
|
||||
switch (_driveType)
|
||||
{
|
||||
case DriveTypes::Drive4W:
|
||||
{
|
||||
PxVehicleDriveSimData4W driveSimData;
|
||||
|
||||
// Differential
|
||||
PxVehicleDifferential4WData diff;
|
||||
// TODO: expose Differential options
|
||||
@@ -383,20 +425,79 @@ void WheeledVehicle::Setup()
|
||||
ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z);
|
||||
ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z);
|
||||
driveSimData.setAckermannGeometryData(ackermann);
|
||||
|
||||
// Create vehicle drive
|
||||
auto drive4W = PxVehicleDrive4W::allocate(wheels.Count());
|
||||
drive4W->setup(CPhysX, _actor, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
|
||||
drive4W->setToRestState();
|
||||
drive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
|
||||
drive4W->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
|
||||
drive = drive4W;
|
||||
break;
|
||||
}
|
||||
case DriveTypes::DriveNW:
|
||||
{
|
||||
PxVehicleDriveSimDataNW driveSimData;
|
||||
|
||||
// Differential
|
||||
PxVehicleDifferentialNWData diff;
|
||||
// TODO: expose Differential options
|
||||
for (int32 i = 0; i < wheels.Count(); i++)
|
||||
diff.setDrivenWheel(i, true);
|
||||
driveSimData.setDiffData(diff);
|
||||
|
||||
// Engine
|
||||
PxVehicleEngineData engine;
|
||||
// TODO: expose Engine options
|
||||
engine.mMOI = M2ToCm2(1.0f);
|
||||
engine.mPeakTorque = M2ToCm2(500.0f);
|
||||
engine.mMaxOmega = RpmToRadPerS(6000.0f);
|
||||
engine.mDampingRateFullThrottle = M2ToCm2(0.15f);
|
||||
engine.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
|
||||
engine.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
|
||||
driveSimData.setEngineData(engine);
|
||||
|
||||
// Gears
|
||||
PxVehicleGearsData gears;
|
||||
gears.mSwitchTime = Math::Max(_gearbox.SwitchTime, 0.0f);
|
||||
driveSimData.setGearsData(gears);
|
||||
|
||||
// Auto Box
|
||||
PxVehicleAutoBoxData autoBox;
|
||||
driveSimData.setAutoBoxData(autoBox);
|
||||
|
||||
// Clutch
|
||||
PxVehicleClutchData clutch;
|
||||
// TODO: expose Clutch options
|
||||
clutch.mStrength = M2ToCm2(10.0f);
|
||||
driveSimData.setClutchData(clutch);
|
||||
|
||||
// Create vehicle drive
|
||||
auto driveNW = PxVehicleDriveNW::allocate(wheels.Count());
|
||||
driveNW->setup(CPhysX, _actor, *wheelsSimData, driveSimData, wheels.Count());
|
||||
driveNW->setToRestState();
|
||||
driveNW->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
|
||||
driveNW->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
|
||||
drive = driveNW;
|
||||
break;
|
||||
}
|
||||
case DriveTypes::NoDrive:
|
||||
{
|
||||
// Create vehicle drive
|
||||
auto driveNo = PxVehicleNoDrive::allocate(wheels.Count());
|
||||
driveNo->setup(CPhysX, _actor, *wheelsSimData);
|
||||
driveNo->setToRestState();
|
||||
drive = driveNo;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CRASH;
|
||||
}
|
||||
|
||||
// Create vehicle drive
|
||||
drive = PxVehicleDrive4W::allocate(wheels.Count());
|
||||
_actor->setSolverIterationCounts(12, 4);
|
||||
drive->setup(CPhysX, _actor, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
|
||||
WheelVehicles.Add(this);
|
||||
|
||||
// Initialize
|
||||
drive->setToRestState();
|
||||
drive->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
|
||||
drive->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
|
||||
|
||||
wheelsSimData->free();
|
||||
_actor->setSolverIterationCounts(12, 4);
|
||||
|
||||
#else
|
||||
LOG(Fatal, "PhysX Vehicle SDK is not supported.");
|
||||
#endif
|
||||
@@ -441,6 +542,7 @@ void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
|
||||
SERIALIZE_GET_OTHER_OBJ(WheeledVehicle);
|
||||
|
||||
SERIALIZE_MEMBER(DriveType, _driveType);
|
||||
SERIALIZE_MEMBER(Wheels, _wheels);
|
||||
SERIALIZE(UseReverseAsBrake);
|
||||
SERIALIZE_MEMBER(Gearbox, _gearbox);
|
||||
@@ -450,6 +552,7 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier*
|
||||
{
|
||||
RigidBody::Deserialize(stream, modifier);
|
||||
|
||||
DESERIALIZE_MEMBER(DriveType, _driveType);
|
||||
DESERIALIZE_MEMBER(Wheels, _wheels);
|
||||
DESERIALIZE(UseReverseAsBrake);
|
||||
DESERIALIZE_MEMBER(Gearbox, _gearbox);
|
||||
@@ -483,12 +586,12 @@ void WheeledVehicle::EndPlay()
|
||||
#endif
|
||||
|
||||
#if WITH_VEHICLE
|
||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||
auto& drive = (PxVehicleWheels*&)_drive;
|
||||
if (drive)
|
||||
{
|
||||
// Parkway Drive
|
||||
WheelVehicles.Remove(this);
|
||||
drive->free();
|
||||
FreeDrive(_driveTypeCurrent, drive);
|
||||
drive = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,19 @@ API_CLASS() class FLAXENGINE_API WheeledVehicle : public RigidBody
|
||||
DECLARE_SCENE_OBJECT(WheeledVehicle);
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Vehicle driving mode types.
|
||||
/// </summary>
|
||||
API_ENUM() enum class DriveTypes
|
||||
{
|
||||
// Four-wheel drive. Any additional wheels are non-drivable. Optimized for 4-wheel cars.
|
||||
Drive4W,
|
||||
// N-wheel drive. Up to 20 drivable wheels. Suits generic wheels configurations.
|
||||
DriveNW,
|
||||
// Non-drivable vehicle.
|
||||
NoDrive,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Vehicle gearbox settings.
|
||||
/// </summary>
|
||||
@@ -40,7 +53,7 @@ public:
|
||||
/// <summary>
|
||||
/// Vehicle wheel types.
|
||||
/// </summary>
|
||||
API_ENUM() enum class WheelType
|
||||
API_ENUM() enum class WheelTypes
|
||||
{
|
||||
// Left wheel of the front axle.
|
||||
FrontLeft,
|
||||
@@ -65,7 +78,7 @@ public:
|
||||
/// <summary>
|
||||
/// Wheel placement type.
|
||||
/// </summary>
|
||||
API_FIELD() WheelType Type = WheelType::FrontLeft;
|
||||
API_FIELD() WheelTypes Type = WheelTypes::FrontLeft;
|
||||
|
||||
/// <summary>
|
||||
/// Combined mass of the wheel and the tire in kg. Typically, a wheel has mass between 20Kg and 80Kg but can be lower and higher depending on the vehicle.
|
||||
@@ -131,6 +144,7 @@ private:
|
||||
};
|
||||
|
||||
void* _drive = nullptr;
|
||||
DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
|
||||
Array<WheelData, FixedAllocation<20>> _wheelsData;
|
||||
float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f;
|
||||
GearboxSettings _gearbox;
|
||||
@@ -144,10 +158,20 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Vehicle\")")
|
||||
bool UseReverseAsBrake = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vehicle driving model type.
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the vehicle driving model type.
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetDriveType(DriveTypes value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the vehicle wheels settings.
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") const Array<Wheel>& GetWheels() const;
|
||||
API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") const Array<Wheel>& GetWheels() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the vehicle wheels settings.
|
||||
|
||||
Reference in New Issue
Block a user