diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index afb5309ea..9051c7eed 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -14,7 +14,7 @@ #include "Engine/Core/Log.h" #endif -WheeledVehicle::WheeledVehicle(const SpawnParams& params) +WheeledVehicle::WheeledVehicle(const SpawnParams ¶ms) : RigidBody(params) { _useCCD = 1; @@ -33,12 +33,22 @@ void WheeledVehicle::SetDriveType(DriveTypes value) Setup(); } -const Array& WheeledVehicle::GetWheels() const +void WheeledVehicle::SetDriveMode(DriveModes value) +{ + _driveMode = value; +} + +WheeledVehicle::DriveModes WheeledVehicle::GetDriveMode() const +{ + return _driveMode; +} + +const Array &WheeledVehicle::GetWheels() const { return _wheels; } -void WheeledVehicle::SetWheels(const Array& value) +void WheeledVehicle::SetWheels(const Array &value) { #if WITH_VEHICLE // Don't recreate whole vehicle when some wheel properties are only changed (eg. suspension) @@ -47,8 +57,8 @@ void WheeledVehicle::SetWheels(const Array& value) bool softUpdate = true; for (int32 wheelIndex = 0; wheelIndex < value.Count(); wheelIndex++) { - auto& oldWheel = _wheels.Get()[wheelIndex]; - auto& newWheel = value.Get()[wheelIndex]; + auto &oldWheel = _wheels.Get()[wheelIndex]; + auto &newWheel = value.Get()[wheelIndex]; if (oldWheel.Type != newWheel.Type || Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) || oldWheel.Collider != newWheel.Collider) @@ -74,7 +84,7 @@ WheeledVehicle::EngineSettings WheeledVehicle::GetEngine() const return _engine; } -void WheeledVehicle::SetEngine(const EngineSettings& value) +void WheeledVehicle::SetEngine(const EngineSettings &value) { #if WITH_VEHICLE if (_vehicle) @@ -88,7 +98,7 @@ WheeledVehicle::DifferentialSettings WheeledVehicle::GetDifferential() const return _differential; } -void WheeledVehicle::SetDifferential(const DifferentialSettings& value) +void WheeledVehicle::SetDifferential(const DifferentialSettings &value) { #if WITH_VEHICLE if (_vehicle) @@ -102,7 +112,7 @@ WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const return _gearbox; } -void WheeledVehicle::SetGearbox(const GearboxSettings& value) +void WheeledVehicle::SetGearbox(const GearboxSettings &value) { #if WITH_VEHICLE if (_vehicle) @@ -131,11 +141,35 @@ void WheeledVehicle::SetHandbrake(float value) _handBrake = Math::Saturate(value); } +void WheeledVehicle::SetTankLeftThrottle(float value) +{ + _tankLeftThrottle = Math::Clamp(value, -1.0f, 1.0f); +} + +void WheeledVehicle::SetTankRightThrottle(float value) +{ + _tankRightThrottle = Math::Clamp(value, -1.0f, 1.0f); +} + +void WheeledVehicle::SetTankLeftBrake(float value) +{ + _tankLeftBrake = Math::Saturate(value); +} + +void WheeledVehicle::SetTankRightBrake(float value) +{ + _tankRightBrake = Math::Saturate(value); +} + void WheeledVehicle::ClearInput() { _throttle = 0; _steering = 0; _brake = 0; + _tankLeftThrottle = 0; + _tankRightThrottle = 0; + _tankLeftBrake = 0; + _tankRightBrake = 0; _handBrake = 0; } @@ -200,12 +234,12 @@ void WheeledVehicle::SetTargetGear(int32 value) #endif } -void WheeledVehicle::GetWheelState(int32 index, WheelState& result) +void WheeledVehicle::GetWheelState(int32 index, WheelState &result) { if (index >= 0 && index < _wheels.Count()) { const auto collider = _wheels[index].Collider.Get(); - for (auto& wheelData : _wheelsData) + for (auto &wheelData : _wheelsData) { if (wheelData.Collider == collider) { @@ -223,7 +257,7 @@ void WheeledVehicle::Setup() return; // Release previous - void* scene = GetPhysicsScene()->GetPhysicsScene(); + void *scene = GetPhysicsScene()->GetPhysicsScene(); if (_vehicle) { PhysicsBackend::RemoveVehicle(scene, this); @@ -246,10 +280,10 @@ void WheeledVehicle::Setup() #if USE_EDITOR -void WheeledVehicle::DrawPhysicsDebug(RenderView& view) +void WheeledVehicle::DrawPhysicsDebug(RenderView &view) { // Wheels shapes - for (const auto& data : _wheelsData) + for (const auto &data : _wheelsData) { int32 wheelIndex = 0; for (; wheelIndex < _wheels.Count(); wheelIndex++) @@ -259,7 +293,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view) } if (wheelIndex == _wheels.Count()) break; - const auto& wheel = _wheels[wheelIndex]; + const auto &wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { const Vector3 currentPos = wheel.Collider->GetPosition(); @@ -280,7 +314,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view) void WheeledVehicle::OnDebugDrawSelected() { // Wheels shapes - for (const auto& data : _wheelsData) + for (const auto &data : _wheelsData) { int32 wheelIndex = 0; for (; wheelIndex < _wheels.Count(); wheelIndex++) @@ -290,7 +324,7 @@ void WheeledVehicle::OnDebugDrawSelected() } if (wheelIndex == _wheels.Count()) break; - const auto& wheel = _wheels[wheelIndex]; + const auto &wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { const Vector3 currentPos = wheel.Collider->GetPosition(); @@ -314,6 +348,14 @@ void WheeledVehicle::OnDebugDrawSelected() DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(data.State.TireContactPoint, 5.0f), Color::Green, 0, false); } } + + // Draw wheels axes + if (wheelIndex % 2 == 0 && wheelIndex + 1 < _wheels.Count()) + { + const Vector3 wheelPos = _wheels[wheelIndex].Collider->GetPosition(); + const Vector3 nextWheelPos = _wheels[wheelIndex + 1].Collider->GetPosition(); + DEBUG_DRAW_LINE(wheelPos, nextWheelPos, Color::Yellow, 0, false); + } } // Center of mass @@ -324,13 +366,14 @@ void WheeledVehicle::OnDebugDrawSelected() #endif -void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj) +void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj) { RigidBody::Serialize(stream, otherObj); SERIALIZE_GET_OTHER_OBJ(WheeledVehicle); SERIALIZE_MEMBER(DriveType, _driveType); + SERIALIZE_MEMBER(DriveModes, _driveMode); SERIALIZE_MEMBER(Wheels, _wheels); SERIALIZE(UseReverseAsBrake); SERIALIZE(UseAnalogSteering); @@ -339,11 +382,12 @@ void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_MEMBER(Gearbox, _gearbox); } -void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) +void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier) { RigidBody::Deserialize(stream, modifier); DESERIALIZE_MEMBER(DriveType, _driveType); + DESERIALIZE_MEMBER(DriveModes, _driveMode); DESERIALIZE_MEMBER(Wheels, _wheels); DESERIALIZE(UseReverseAsBrake); DESERIALIZE(UseAnalogSteering); @@ -355,7 +399,7 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* _fixInvalidForwardDir |= modifier->EngineBuild < 6341; } -void WheeledVehicle::OnColliderChanged(Collider* c) +void WheeledVehicle::OnColliderChanged(Collider *c) { RigidBody::OnColliderChanged(c); @@ -378,7 +422,7 @@ void WheeledVehicle::OnActiveInTreeChanged() Setup(); } -void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene* previous) +void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene *previous) { RigidBody::OnPhysicsSceneChanged(previous); @@ -401,9 +445,10 @@ void WheeledVehicle::OnTransformChanged() // Transform all vehicle children around the vehicle origin to fix the vehicle facing direction const Quaternion rotationDelta(0.0f, -0.7071068f, 0.0f, 0.7071068f); const Vector3 origin = GetPosition(); - for (Actor* child : Children) + for (Actor *child : Children) { - Transform trans = child->GetTransform();; + Transform trans = child->GetTransform(); + ; const Vector3 pivotOffset = trans.Translation - origin; if (pivotOffset.IsZero()) { @@ -423,7 +468,7 @@ void WheeledVehicle::OnTransformChanged() } } -void WheeledVehicle::BeginPlay(SceneBeginData* data) +void WheeledVehicle::BeginPlay(SceneBeginData *data) { RigidBody::BeginPlay(data); diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index 3a329edc4..49c00b17a 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -26,6 +26,18 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo DriveNW, // Non-drivable vehicle. NoDrive, + Tank, + }; + /// + /// Vehicle driving types. + /// Used only on tanks to specify the drive mode. + /// + API_ENUM() enum class DriveModes + { + // Drive turning the vehicle using only one track + Standard, + // Drive turning the vehicle using all tracks inverse direction. + Special }; /// @@ -128,6 +140,11 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo /// API_FIELD() bool AutoGear = true; + /// + /// Number of gears to move to forward + /// + API_FIELD(Attributes = "Limit(1, 30)") int ForwardGearsRatios = 5; + /// /// Time it takes to switch gear. Specified in seconds (s). /// @@ -322,8 +339,9 @@ private: void* _vehicle = nullptr; DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent; + DriveModes _driveMode = DriveModes::Standard; Array> _wheelsData; - float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f; + float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake; Array _wheels; EngineSettings _engine; DifferentialSettings _differential; @@ -347,17 +365,27 @@ public: /// /// Gets the vehicle driving model type. /// - API_PROPERTY(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const; + API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const; /// /// Sets the vehicle driving model type. /// API_PROPERTY() void SetDriveType(DriveTypes value); + /// + /// Used only for tanks, set the drive mode. + /// + API_PROPERTY() void SetDriveMode(DriveModes value); + + /// + /// Gets the vehicle driving mode. Used only on tanks + /// + API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") DriveModes GetDriveMode() const; + /// /// Gets the vehicle wheels settings. /// - API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const; + API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const; /// /// Sets the vehicle wheels settings. @@ -367,7 +395,7 @@ public: /// /// Gets the vehicle engine settings. /// - API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const; + API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const; /// /// Sets the vehicle engine settings. @@ -377,7 +405,7 @@ public: /// /// Gets the vehicle differential settings. /// - API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const; + API_PROPERTY(Attributes="EditorOrder(6), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const; /// /// Sets the vehicle differential settings. @@ -387,7 +415,7 @@ public: /// /// Gets the vehicle gearbox settings. /// - API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const; + API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const; /// /// Sets the vehicle gearbox settings. @@ -419,6 +447,32 @@ public: /// The value (0,1 range). API_FUNCTION() void SetHandbrake(float value); + /// + /// Sets the input for tank left track throttle. It is the analog accelerator pedal value in range (-1,1) where 1 represents the pedal fully pressed to move to forward, 0 to represents the + /// pedal in its rest state and -1 represents the pedal fully pressed to move to backward. The track direction will be inverted if the vehicle current gear is rear. + /// + /// The value (-1,1 range). + API_FUNCTION() void SetTankLeftThrottle(float value); + + /// + /// Sets the input for tank right track throttle. It is the analog accelerator pedal value in range (-1,1) where 1 represents the pedal fully pressed to move to forward, 0 to represents the + /// pedal in its rest state and -1 represents the pedal fully pressed to move to backward. The track direction will be inverted if the vehicle current gear is rear. + /// + /// The value (-1,1 range). + API_FUNCTION() void SetTankRightThrottle(float value); + + /// + /// Sets the input for tank brakes the left track. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state. + /// + /// The value (0,1 range). + API_FUNCTION() void SetTankLeftBrake(float value); + + /// + /// Sets the input for tank brakes the right track. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state. + /// + /// The value (0,1 range). + API_FUNCTION() void SetTankRightBrake(float value); + /// /// Clears all the vehicle control inputs to the default values (throttle, steering, breaks). /// diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index cbc381142..99bc093fc 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #endif @@ -961,7 +962,6 @@ void PhysicalMaterial::UpdatePhysicsMaterial() bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& output) { - PROFILE_CPU(); ENSURE_CAN_COOK; if (input.VertexCount == 0) LOG(Warning, "Empty mesh data for collision cooking."); @@ -1005,7 +1005,6 @@ bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& outpu bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& output) { - PROFILE_CPU(); ENSURE_CAN_COOK; if (input.VertexCount == 0 || input.IndexCount == 0) LOG(Warning, "Empty mesh data for collision cooking."); @@ -1040,7 +1039,6 @@ bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& out bool CollisionCooking::CookHeightField(int32 cols, int32 rows, const PhysicsBackend::HeightFieldSample* data, WriteStream& stream) { - PROFILE_CPU(); ENSURE_CAN_COOK; PxHeightFieldDesc heightFieldDesc; @@ -1386,62 +1384,172 @@ void PhysicsBackend::EndSimulateScene(void* scene) WheelVehiclesCache.Add(drive); wheelsCount += drive->mWheelsSimData.getNbWheels(); + const float deadZone = 0.1f; + bool isTank = wheelVehicle->_driveType == WheeledVehicle::DriveTypes::Tank; float throttle = wheelVehicle->_throttle; + float steering = wheelVehicle->_steering; float brake = wheelVehicle->_brake; + float leftThrottle = wheelVehicle->_tankLeftThrottle; + float rightThrottle = wheelVehicle->_tankRightThrottle; + float leftBrake = Math::Max(wheelVehicle->_tankLeftBrake, wheelVehicle->_handBrake); + float rightBrake = Math::Max(wheelVehicle->_tankRightBrake, wheelVehicle->_handBrake); + + WheeledVehicle::DriveModes vehicleDriveMode = wheelVehicle->_driveMode; + + if (isTank) + { + // Converting default vehicle controls to tank controls. + if (throttle != 0 || steering != 0) + { + leftThrottle = throttle + steering; + rightThrottle = throttle - steering; + } + } + + // Converting special tank drive mode to standard tank mode when is turning. + if (isTank && vehicleDriveMode == WheeledVehicle::DriveModes::Standard) + { + // Special inputs when turning vehicle -1 1 to left or 1 -1 to turn right + // to: + // Standard inputs when turning vehicle 0 1 to left or 1 0 to turn right + + if (leftThrottle < -deadZone && rightThrottle > deadZone) + { + leftThrottle = 0; + } + else if (leftThrottle > deadZone && rightThrottle < -deadZone) + { + rightThrottle = 0; + } + } + if (wheelVehicle->UseReverseAsBrake) { const float invalidDirectionThreshold = 80.0f; const float breakThreshold = 8.0f; const float forwardSpeed = wheelVehicle->GetForwardSpeed(); + int currentGear = wheelVehicle->GetCurrentGear(); + // Tank tracks direction: 1 forward -1 backward 0 neutral + bool toForward = false; + toForward |= throttle > deadZone; + toForward |= (leftThrottle > deadZone) && (rightThrottle > deadZone); // 1 1 + bool toBackward = false; + toBackward |= throttle < -deadZone; + toBackward |= (leftThrottle < -deadZone) && (rightThrottle < -deadZone); // -1 -1 + toBackward |= (leftThrottle < -deadZone) && (rightThrottle < deadZone); // -1 0 + toBackward |= (leftThrottle < deadZone) && (rightThrottle < -deadZone); // 0 -1 + + bool isTankTurning = false; + + if (isTank) + { + isTankTurning |= leftThrottle > deadZone && rightThrottle < -deadZone; // 1 -1 + isTankTurning |= leftThrottle < -deadZone && rightThrottle > deadZone; // -1 1 + isTankTurning |= leftThrottle < deadZone && rightThrottle > deadZone; // 0 1 + isTankTurning |= leftThrottle > deadZone && rightThrottle < deadZone; // 1 0 + isTankTurning |= leftThrottle < -deadZone && rightThrottle < deadZone; // -1 0 + isTankTurning |= leftThrottle < deadZone && rightThrottle < -deadZone; // 0 -1 + + if (toForward || toBackward) + { + isTankTurning = false; + } + } + // Automatic gear change when changing driving direction if (Math::Abs(forwardSpeed) < invalidDirectionThreshold) { - if (throttle < -ZeroTolerance && wheelVehicle->GetCurrentGear() >= 0 && wheelVehicle->GetTargetGear() >= 0) + int targetGear = wheelVehicle->GetTargetGear(); + if (toBackward && currentGear > 0 && targetGear >= 0) { - wheelVehicle->SetCurrentGear(-1); + currentGear = -1; } - else if (throttle > ZeroTolerance && wheelVehicle->GetCurrentGear() <= 0 && wheelVehicle->GetTargetGear() <= 0) + else if (!toBackward && currentGear <= 0 && targetGear <= 0) { - wheelVehicle->SetCurrentGear(1); + currentGear = 1; + } + else if (isTankTurning && currentGear <= 0) + { + currentGear = 1; + } + + if (wheelVehicle->GetCurrentGear() != currentGear) + { + wheelVehicle->SetCurrentGear(currentGear); } } // Automatic break when changing driving direction - if (throttle > 0.0f) + if (toForward) { if (forwardSpeed < -invalidDirectionThreshold) { brake = 1.0f; + leftBrake = 1.0f; + rightBrake = 1.0f; } } - else if (throttle < 0.0f) + else if (toBackward) { if (forwardSpeed > invalidDirectionThreshold) { brake = 1.0f; + leftBrake = 1.0f; + rightBrake = 1.0f; } } else { - if (forwardSpeed < breakThreshold && forwardSpeed > -breakThreshold) + if (forwardSpeed < breakThreshold && forwardSpeed > -breakThreshold && !isTankTurning) // not accelerating, very slow speed -> stop { brake = 1.0f; + leftBrake = 1.0f; + rightBrake = 1.0f; } } // Block throttle if user is changing driving direction - if ((throttle > 0.0f && wheelVehicle->GetTargetGear() < 0) || (throttle < 0.0f && wheelVehicle->GetTargetGear() > 0)) + if ((toForward && currentGear < 0) || (toBackward && currentGear > 0)) { throttle = 0.0f; + leftThrottle = 0; + rightThrottle = 0; } throttle = Math::Abs(throttle); + + if (isTank) + { + // invert acceleration when moving to backward because tank inputs can be < 0 + if (currentGear < 0) + { + float lt = -leftThrottle; + float rt = -rightThrottle; + float lb = leftBrake; + float rb = rightBrake; + leftThrottle = rt; + rightThrottle = lt; + leftBrake = rb; + rightBrake = lb; + } + } } else { throttle = Math::Max(throttle, 0.0f); } + + // Force brake the another side track to turn more faster. + if (Math::Abs(leftThrottle) > deadZone && Math::Abs(rightThrottle) < deadZone) + { + rightBrake = 1.0f; + } + if (Math::Abs(rightThrottle) > deadZone && Math::Abs(leftThrottle) < deadZone) + { + leftBrake = 1.0f; + } + // @formatter:off // Reference: PhysX SDK docs // TODO: expose input control smoothing data @@ -1518,11 +1626,23 @@ void PhysicsBackend::EndSimulateScene(void* scene) PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, steerVsForwardSpeed, rawInputData, scenePhysX->LastDeltaTime, false, *(PxVehicleDriveNW*)drive); break; } + case WheeledVehicle::DriveTypes::Tank: + { + PxVehicleDriveTankRawInputData driveMode = vehicleDriveMode == WheeledVehicle::DriveModes::Standard ? PxVehicleDriveTankControlModel::eSTANDARD : PxVehicleDriveTankControlModel::eSPECIAL; + PxVehicleDriveTankRawInputData rawInputData = PxVehicleDriveTankRawInputData(driveMode); + rawInputData.setAnalogAccel(Math::Max(Math::Abs(leftThrottle), Math::Abs(rightThrottle))); + rawInputData.setAnalogLeftBrake(leftBrake); + rawInputData.setAnalogRightBrake(rightBrake); + rawInputData.setAnalogLeftThrust(leftThrottle); + rawInputData.setAnalogRightThrust(rightThrottle); + + PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank*)drive); + break; + } } } else - { - const float deadZone = 0.1f; + { switch (wheelVehicle->_driveTypeCurrent) { case WheeledVehicle::DriveTypes::Drive4W: @@ -1547,6 +1667,26 @@ void PhysicsBackend::EndSimulateScene(void* scene) PxVehicleDriveNWSmoothDigitalRawInputsAndSetAnalogInputs(keySmoothing, steerVsForwardSpeed, rawInputData, scenePhysX->LastDeltaTime, false, *(PxVehicleDriveNW*)drive); break; } + case WheeledVehicle::DriveTypes::Tank: + { + // Convert analogic inputs to digital inputs. + leftThrottle = Math::Round(leftThrottle); + rightThrottle = Math::Round(rightThrottle); + leftBrake = Math::Round(leftBrake); + rightBrake = Math::Round(rightBrake); + + PxVehicleDriveTankRawInputData driveMode = vehicleDriveMode == WheeledVehicle::DriveModes::Standard ? PxVehicleDriveTankControlModel::eSTANDARD : PxVehicleDriveTankControlModel::eSPECIAL; + PxVehicleDriveTankRawInputData rawInputData = PxVehicleDriveTankRawInputData(driveMode); + rawInputData.setAnalogAccel(Math::Max(Math::Abs(leftThrottle), Math::Abs(rightThrottle))); + rawInputData.setAnalogLeftBrake(leftBrake); + rawInputData.setAnalogRightBrake(rightBrake); + rawInputData.setAnalogLeftThrust(leftThrottle); + rawInputData.setAnalogRightThrust(rightThrottle); + + // Needs to pass analogic values to vehicle to maintein current moviment direction because digital inputs accept only true/false values to tracks thrust instead of -1 to 1 + PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank *)drive); + break; + } } } } @@ -2803,7 +2943,7 @@ void PhysicsBackend::SetHingeJointLimit(void* joint, const LimitAngularRange& va void PhysicsBackend::SetHingeJointDrive(void* joint, const HingeJointDrive& value) { auto jointPhysX = (PxRevoluteJoint*)joint; - jointPhysX->setDriveVelocity(value.Velocity); + jointPhysX->setDriveVelocity(Math::Max(value.Velocity, 0.0f)); jointPhysX->setDriveForceLimit(Math::Max(value.ForceLimit, 0.0f)); jointPhysX->setDriveGearRatio(Math::Max(value.GearRatio, 0.0f)); jointPhysX->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, value.FreeSpin); @@ -3086,6 +3226,147 @@ int32 PhysicsBackend::MoveController(void* controller, void* shape, const Vector #if WITH_VEHICLE +PxVehicleDifferential4WData CreatePxVehicleDifferential4WData(const WheeledVehicle::DifferentialSettings& settings) +{ + PxVehicleDifferential4WData differential4WData; + differential4WData.mType = (PxVehicleDifferential4WData::Enum)settings.Type; + differential4WData.mFrontRearSplit = settings.FrontRearSplit; + differential4WData.mFrontLeftRightSplit = settings.FrontLeftRightSplit; + differential4WData.mRearLeftRightSplit = settings.RearLeftRightSplit; + differential4WData.mCentreBias = settings.CentreBias; + differential4WData.mFrontBias = settings.FrontBias; + differential4WData.mRearBias = settings.RearBias; + return differential4WData; +} + +PxVehicleDifferentialNWData CreatePxVehicleDifferentialNWData(const WheeledVehicle::DifferentialSettings& settings, const Array>& wheels) +{ + PxVehicleDifferentialNWData differentialNwData; + for (int32 i = 0; i < wheels.Count(); i++) + differentialNwData.setDrivenWheel(i, true); + + return differentialNwData; +} + +PxVehicleEngineData CreatePxVehicleEngineData(const WheeledVehicle::EngineSettings& settings) +{ + PxVehicleEngineData engineData; + engineData.mMOI = M2ToCm2(settings.MOI); + engineData.mPeakTorque = M2ToCm2(settings.MaxTorque); + engineData.mMaxOmega = RpmToRadPerS(settings.MaxRotationSpeed); + engineData.mDampingRateFullThrottle = M2ToCm2(0.15f); + engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f); + engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f); + return engineData; +} + +PxVehicleGearsData CreatePxVehicleGearsData(const WheeledVehicle::GearboxSettings& settings) +{ + PxVehicleGearsData gears; + + // Total gears is forward gears + neutral/rear gears + int gearsAmount = settings.ForwardGearsRatios + 2; + + // Setup gears torque/top speed relations + // Higher torque = less speed + // Low torque = high speed + + // Example: + // ForwardGearsRatios = 4 + // GearRev = -5 + // Gear0 = 0 + // Gear1 = 4.2 + // Gear2 = 3.4 + // Gear3 = 2.6 + // Gear4 = 1.8 + // Gear5 = 1 + + gears.mRatios[0] = -(gearsAmount - 2); // reverse + gears.mRatios[1] = 0; // neutral + + // Setup all gears except neutral and reverse + for (int i = gearsAmount; i > 2; i--) { + + float gearsRatios = settings.ForwardGearsRatios; + float currentGear = i - 2; + + gears.mRatios[i] = Math::Lerp(gearsRatios, 1.0f, (currentGear / gearsRatios)); + } + + // reset unused gears + for (int i = gearsAmount; i < PxVehicleGearsData::eGEARSRATIO_COUNT; i++) + gears.mRatios[i] = 0; + + gears.mSwitchTime = Math::Max(settings.SwitchTime, 0.0f); + gears.mNbRatios = Math::Clamp(gearsAmount, 2, (int)PxVehicleGearsData::eGEARSRATIO_COUNT); + return gears; +} + +PxVehicleAutoBoxData CreatePxVehicleAutoBoxData() +{ + return PxVehicleAutoBoxData(); +} + +PxVehicleClutchData CreatePxVehicleClutchData(const WheeledVehicle::GearboxSettings& settings) +{ + PxVehicleClutchData clutch; + clutch.mStrength = M2ToCm2(settings.ClutchStrength); + return clutch; +} + +PxVehicleSuspensionData CreatePxVehicleSuspensionData(const WheeledVehicle::Wheel& settings, const PxReal wheelSprungMass) +{ + PxVehicleSuspensionData suspensionData; + const float suspensionFrequency = 7.0f; + suspensionData.mMaxCompression = settings.SuspensionMaxRaise; + suspensionData.mMaxDroop = settings.SuspensionMaxDrop; + suspensionData.mSprungMass = wheelSprungMass; + suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass; + suspensionData.mSpringDamperRate = settings.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass); + return suspensionData; +} + +PxVehicleTireData CreatePxVehicleTireData(const WheeledVehicle::Wheel& settings) +{ + PxVehicleTireData tire; + int32 tireIndex = WheelTireTypes.Find(settings.TireFrictionScale); + if (tireIndex == -1) + { + // New tire type + tireIndex = WheelTireTypes.Count(); + WheelTireTypes.Add(settings.TireFrictionScale); + WheelTireFrictionsDirty = true; + } + tire.mType = tireIndex; + tire.mLatStiffX = settings.TireLateralMax; + tire.mLatStiffY = settings.TireLateralStiffness; + tire.mLongitudinalStiffnessPerUnitGravity = settings.TireLongitudinalStiffness; + return tire; +} + +PxVehicleWheelData CreatePxVehicleWheelData(const WheeledVehicle::Wheel& settings) +{ + PxVehicleWheelData wheelData; + wheelData.mMass = settings.Mass; + wheelData.mRadius = settings.Radius; + wheelData.mWidth = settings.Width; + wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius); + wheelData.mDampingRate = M2ToCm2(settings.DampingRate); + wheelData.mMaxSteer = settings.MaxSteerAngle * DegreesToRadians; + wheelData.mMaxBrakeTorque = M2ToCm2(settings.MaxBrakeTorque); + wheelData.mMaxHandBrakeTorque = M2ToCm2(settings.MaxHandBrakeTorque); + return wheelData; +} + +PxVehicleAckermannGeometryData CreatePxVehicleAckermannGeometryData(PxVehicleWheelsSimData* wheelsSimData) +{ + PxVehicleAckermannGeometryData ackermann; + ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z); + ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x); + ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x); + return ackermann; +} + bool SortWheels(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b) { return (int32)a.Type < (int32)b.Type; @@ -3158,42 +3439,14 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) data.Collider = wheel.Collider; data.LocalOrientation = wheel.Collider->GetLocalOrientation(); - PxVehicleSuspensionData suspensionData; - const float suspensionFrequency = 7.0f; - suspensionData.mMaxCompression = wheel.SuspensionMaxRaise; - suspensionData.mMaxDroop = wheel.SuspensionMaxDrop; - suspensionData.mSprungMass = sprungMasses[i]; - suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass; - suspensionData.mSpringDamperRate = wheel.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass); - - PxVehicleTireData tire; - int32 tireIndex = WheelTireTypes.Find(wheel.TireFrictionScale); - if (tireIndex == -1) - { - // New tire type - tireIndex = WheelTireTypes.Count(); - WheelTireTypes.Add(wheel.TireFrictionScale); - WheelTireFrictionsDirty = true; - } - tire.mType = tireIndex; - tire.mLatStiffX = wheel.TireLateralMax; - tire.mLatStiffY = wheel.TireLateralStiffness; - tire.mLongitudinalStiffnessPerUnitGravity = wheel.TireLongitudinalStiffness; - - PxVehicleWheelData wheelData; - wheelData.mMass = wheel.Mass; - wheelData.mRadius = wheel.Radius; - wheelData.mWidth = wheel.Width; - wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius); - wheelData.mDampingRate = M2ToCm2(wheel.DampingRate); - wheelData.mMaxSteer = wheel.MaxSteerAngle * DegreesToRadians; - wheelData.mMaxBrakeTorque = M2ToCm2(wheel.MaxBrakeTorque); - wheelData.mMaxHandBrakeTorque = M2ToCm2(wheel.MaxHandBrakeTorque); - PxVec3 centreOffset = centerOfMassOffset.transformInv(offsets[i]); PxVec3 forceAppPointOffset(centreOffset.x, wheel.SuspensionForceOffset, centreOffset.z); - wheelsSimData->setTireData(i, tire); + const PxVehicleTireData& tireData = CreatePxVehicleTireData(wheel); + const PxVehicleWheelData& wheelData = CreatePxVehicleWheelData(wheel); + const PxVehicleSuspensionData& suspensionData = CreatePxVehicleSuspensionData(wheel, sprungMasses[i]); + + wheelsSimData->setTireData(i,tireData); wheelsSimData->setWheelData(i, wheelData); wheelsSimData->setSuspensionData(i, suspensionData); wheelsSimData->setSuspTravelDirection(i, centerOfMassOffset.rotate(PxVec3(0.0f, -1.0f, 0.0f))); @@ -3260,48 +3513,19 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) case WheeledVehicle::DriveTypes::Drive4W: { PxVehicleDriveSimData4W driveSimData; + const PxVehicleDifferential4WData& differentialData = CreatePxVehicleDifferential4WData(differential); + const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine); + const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox); + const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData(); + const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData); - // Differential - PxVehicleDifferential4WData differential4WData; - differential4WData.mType = (PxVehicleDifferential4WData::Enum)differential.Type; - differential4WData.mFrontRearSplit = differential.FrontRearSplit; - differential4WData.mFrontLeftRightSplit = differential.FrontLeftRightSplit; - differential4WData.mRearLeftRightSplit = differential.RearLeftRightSplit; - differential4WData.mCentreBias = differential.CentreBias; - differential4WData.mFrontBias = differential.FrontBias; - differential4WData.mRearBias = differential.RearBias; - driveSimData.setDiffData(differential4WData); - - // Engine - PxVehicleEngineData engineData; - engineData.mMOI = M2ToCm2(engine.MOI); - engineData.mPeakTorque = M2ToCm2(engine.MaxTorque); - engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed); - engineData.mDampingRateFullThrottle = M2ToCm2(0.15f); - engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f); - engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f); + driveSimData.setDiffData(differentialData); driveSimData.setEngineData(engineData); - - // Gears - PxVehicleGearsData gears; - gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f); - driveSimData.setGearsData(gears); - - // Auto Box - PxVehicleAutoBoxData autoBox; - driveSimData.setAutoBoxData(autoBox); - - // Clutch - PxVehicleClutchData clutch; - clutch.mStrength = M2ToCm2(gearbox.ClutchStrength); - driveSimData.setClutchData(clutch); - - // Ackermann steer accuracy - PxVehicleAckermannGeometryData ackermann; - ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z); - ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x); - ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x); - driveSimData.setAckermannGeometryData(ackermann); + driveSimData.setGearsData(gearsData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(cluchData); + driveSimData.setAckermannGeometryData(geometryData); // Create vehicle drive auto drive4W = PxVehicleDrive4W::allocate(wheels.Count()); @@ -3315,36 +3539,18 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) case WheeledVehicle::DriveTypes::DriveNW: { PxVehicleDriveSimDataNW driveSimData; + const PxVehicleDifferentialNWData& differentialData = CreatePxVehicleDifferentialNWData(differential, wheels); + const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine); + const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox); + const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData(); + const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData); - // Differential - PxVehicleDifferentialNWData differentialNwData; - for (int32 i = 0; i < wheels.Count(); i++) - differentialNwData.setDrivenWheel(i, true); - driveSimData.setDiffData(differentialNwData); - - // Engine - PxVehicleEngineData engineData; - engineData.mMOI = M2ToCm2(engine.MOI); - engineData.mPeakTorque = M2ToCm2(engine.MaxTorque); - engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed); - engineData.mDampingRateFullThrottle = M2ToCm2(0.15f); - engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f); - engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f); + driveSimData.setDiffData(differentialData); driveSimData.setEngineData(engineData); - - // Gears - PxVehicleGearsData gears; - gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f); - driveSimData.setGearsData(gears); - - // Auto Box - PxVehicleAutoBoxData autoBox; - driveSimData.setAutoBoxData(autoBox); - - // Clutch - PxVehicleClutchData clutch; - clutch.mStrength = M2ToCm2(gearbox.ClutchStrength); - driveSimData.setClutchData(clutch); + driveSimData.setGearsData(gearsData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(cluchData); // Create vehicle drive auto driveNW = PxVehicleDriveNW::allocate(wheels.Count()); @@ -3364,6 +3570,32 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) vehicle = driveNo; break; } + case WheeledVehicle::DriveTypes::Tank: + { + PxVehicleDriveSimData4W driveSimData; + const PxVehicleDifferential4WData &differentialData = CreatePxVehicleDifferential4WData(differential); + const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine); + const PxVehicleGearsData &gearsData = CreatePxVehicleGearsData(gearbox); + const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData(); + const PxVehicleClutchData &cluchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAckermannGeometryData &geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData); + + driveSimData.setDiffData(differentialData); + driveSimData.setEngineData(engineData); + driveSimData.setGearsData(gearsData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(cluchData); + driveSimData.setAckermannGeometryData(geometryData); + + // Create vehicle drive + auto driveTank = PxVehicleDriveTank::allocate(wheels.Count()); + driveTank->setup(PhysX, actorPhysX, *wheelsSimData, driveSimData, wheels.Count()); + driveTank->setToRestState(); + driveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST); + driveTank->mDriveDynData.setUseAutoGears(gearbox.AutoGear); + vehicle = driveTank; + break; + } default: CRASH; } @@ -3385,6 +3617,9 @@ void PhysicsBackend::DestroyVehicle(void* vehicle, int32 driveType) case WheeledVehicle::DriveTypes::NoDrive: ((PxVehicleNoDrive*)vehicle)->free(); break; + case WheeledVehicle::DriveTypes::Tank: + ((PxVehicleDriveTank*)vehicle)->free(); + break; } } @@ -3395,42 +3630,11 @@ void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor) for (uint32 i = 0; i < wheelsSimData->getNbWheels(); i++) { auto& wheel = actor->_wheels[i]; - - // Update suspension data - PxVehicleSuspensionData suspensionData = wheelsSimData->getSuspensionData(i); - const float suspensionFrequency = 7.0f; - suspensionData.mMaxCompression = wheel.SuspensionMaxRaise; - suspensionData.mMaxDroop = wheel.SuspensionMaxDrop; - suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass; - suspensionData.mSpringDamperRate = wheel.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass); + const PxVehicleSuspensionData& suspensionData = CreatePxVehicleSuspensionData(wheel, wheelsSimData->getSuspensionData(i).mSprungMass); + const PxVehicleTireData& tireData = CreatePxVehicleTireData(wheel); + const PxVehicleWheelData& wheelData = CreatePxVehicleWheelData(wheel); wheelsSimData->setSuspensionData(i, suspensionData); - - // Update tire data - PxVehicleTireData tire; - int32 tireIndex = WheelTireTypes.Find(wheel.TireFrictionScale); - if (tireIndex == -1) - { - // New tire type - tireIndex = WheelTireTypes.Count(); - WheelTireTypes.Add(wheel.TireFrictionScale); - WheelTireFrictionsDirty = true; - } - tire.mType = tireIndex; - tire.mLatStiffX = wheel.TireLateralMax; - tire.mLatStiffY = wheel.TireLateralStiffness; - tire.mLongitudinalStiffnessPerUnitGravity = wheel.TireLongitudinalStiffness; - wheelsSimData->setTireData(i, tire); - - // Update wheel data - PxVehicleWheelData wheelData; - wheelData.mMass = wheel.Mass; - wheelData.mRadius = wheel.Radius; - wheelData.mWidth = wheel.Width; - wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius); - wheelData.mDampingRate = M2ToCm2(wheel.DampingRate); - wheelData.mMaxSteer = wheel.MaxSteerAngle * DegreesToRadians; - wheelData.mMaxBrakeTorque = M2ToCm2(wheel.MaxBrakeTorque); - wheelData.mMaxHandBrakeTorque = M2ToCm2(wheel.MaxHandBrakeTorque); + wheelsSimData->setTireData(i, tireData); wheelsSimData->setWheelData(i, wheelData); } } @@ -3444,28 +3648,24 @@ void PhysicsBackend::SetVehicleEngine(void* vehicle, const void* value) case PxVehicleTypes::eDRIVE4W: { auto drive4W = (PxVehicleDrive4W*)drive; + const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine); PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData; - PxVehicleEngineData engineData; - engineData.mMOI = M2ToCm2(engine.MOI); - engineData.mPeakTorque = M2ToCm2(engine.MaxTorque); - engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed); - engineData.mDampingRateFullThrottle = M2ToCm2(0.15f); - engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f); - engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f); driveSimData.setEngineData(engineData); break; } case PxVehicleTypes::eDRIVENW: { auto drive4W = (PxVehicleDriveNW*)drive; + const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine); PxVehicleDriveSimDataNW& driveSimData = drive4W->mDriveSimData; - PxVehicleEngineData engineData; - engineData.mMOI = M2ToCm2(engine.MOI); - engineData.mPeakTorque = M2ToCm2(engine.MaxTorque); - engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed); - engineData.mDampingRateFullThrottle = M2ToCm2(0.15f); - engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f); - engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f); + driveSimData.setEngineData(engineData); + break; + } + case PxVehicleTypes::eDRIVETANK: + { + auto driveTank = (PxVehicleDriveTank*)drive; + const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine); + PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData; driveSimData.setEngineData(engineData); break; } @@ -3481,16 +3681,9 @@ void PhysicsBackend::SetVehicleDifferential(void* vehicle, const void* value) case PxVehicleTypes::eDRIVE4W: { auto drive4W = (PxVehicleDrive4W*)drive; + const PxVehicleDifferential4WData& differentialData = CreatePxVehicleDifferential4WData(differential); PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData; - PxVehicleDifferential4WData differential4WData; - differential4WData.mType = (PxVehicleDifferential4WData::Enum)differential.Type; - differential4WData.mFrontRearSplit = differential.FrontRearSplit; - differential4WData.mFrontLeftRightSplit = differential.FrontLeftRightSplit; - differential4WData.mRearLeftRightSplit = differential.RearLeftRightSplit; - differential4WData.mCentreBias = differential.CentreBias; - differential4WData.mFrontBias = differential.FrontBias; - differential4WData.mRearBias = differential.RearBias; - driveSimData.setDiffData(differential4WData); + driveSimData.setDiffData(differentialData); break; } } @@ -3507,41 +3700,37 @@ void PhysicsBackend::SetVehicleGearbox(void* vehicle, const void* value) case PxVehicleTypes::eDRIVE4W: { auto drive4W = (PxVehicleDrive4W*)drive; + const PxVehicleGearsData& gearData = CreatePxVehicleGearsData(gearbox); + const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData(); PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData; - - // Gears - PxVehicleGearsData gears; - gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f); - driveSimData.setGearsData(gears); - - // Auto Box - PxVehicleAutoBoxData autoBox; - driveSimData.setAutoBoxData(autoBox); - - // Clutch - PxVehicleClutchData clutch; - clutch.mStrength = M2ToCm2(gearbox.ClutchStrength); - driveSimData.setClutchData(clutch); + driveSimData.setGearsData(gearData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(clutchData); break; } case PxVehicleTypes::eDRIVENW: { auto drive4W = (PxVehicleDriveNW*)drive; + const PxVehicleGearsData& gearData = CreatePxVehicleGearsData(gearbox); + const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData(); PxVehicleDriveSimDataNW& driveSimData = drive4W->mDriveSimData; - - // Gears - PxVehicleGearsData gears; - gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f); - driveSimData.setGearsData(gears); - - // Auto Box - PxVehicleAutoBoxData autoBox; - driveSimData.setAutoBoxData(autoBox); - - // Clutch - PxVehicleClutchData clutch; - clutch.mStrength = M2ToCm2(gearbox.ClutchStrength); - driveSimData.setClutchData(clutch); + driveSimData.setGearsData(gearData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(clutchData); + break; + } + case PxVehicleTypes::eDRIVETANK: + { + auto driveTank = (PxVehicleDriveTank *)drive; + const PxVehicleGearsData &gearData = CreatePxVehicleGearsData(gearbox); + const PxVehicleClutchData &clutchData = CreatePxVehicleClutchData(gearbox); + const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData(); + PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData; + driveSimData.setGearsData(gearData); + driveSimData.setAutoBoxData(autoBoxData); + driveSimData.setClutchData(clutchData); break; } }