From b0ec8525aab51fea854d1e71c971244deeab7d83 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 1 Sep 2023 12:40:51 +0200 Subject: [PATCH] Add support for editing `WheeledVehicle` wheels config at runtime without full physics state rebuild #1324 --- .../Engine/Physics/Actors/WheeledVehicle.cpp | 25 ++++++++++ .../Physics/PhysX/PhysicsBackendPhysX.cpp | 47 +++++++++++++++++++ Source/Engine/Physics/PhysicsBackend.h | 1 + Source/Engine/Physics/PhysicsBackendEmpty.cpp | 4 ++ 4 files changed, 77 insertions(+) diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index f5f729d39..0ab8e6518 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -40,6 +40,31 @@ const Array& WheeledVehicle::GetWheels() const void WheeledVehicle::SetWheels(const Array& value) { +#if WITH_VEHICLE + // Don't recreate whole vehicle when some wheel properties are only changed (eg. suspension) + if (_actor && _vehicle && _wheels.Count() == value.Count() && _wheelsData.Count() == value.Count()) + { + bool softUpdate = true; + for (int32 wheelIndex = 0; wheelIndex < value.Count(); 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) + { + softUpdate = false; + break; + } + } + if (softUpdate) + { + _wheels = value; + PhysicsBackend::UpdateVehicleWheels(this); + return; + } + } +#endif _wheels = value; Setup(); } diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 4b18804da..619f025ed 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -2923,6 +2923,53 @@ void PhysicsBackend::DestroyVehicle(void* vehicle, int32 driveType) } } +void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor) +{ + auto drive = (PxVehicleWheels*)actor->_vehicle; + PxVehicleWheelsSimData* wheelsSimData = &drive->mWheelsSimData; + 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); + 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->setWheelData(i, wheelData); + } +} + void PhysicsBackend::SetVehicleGearbox(void* vehicle, const void* value) { auto drive = (PxVehicleDrive*)vehicle; diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h index f72c7f679..ba452cda7 100644 --- a/Source/Engine/Physics/PhysicsBackend.h +++ b/Source/Engine/Physics/PhysicsBackend.h @@ -245,6 +245,7 @@ public: // Vehicles static void* CreateVehicle(class WheeledVehicle* actor); static void DestroyVehicle(void* vehicle, int32 driveType); + static void UpdateVehicleWheels(WheeledVehicle* actor); static void SetVehicleGearbox(void* vehicle, const void* value); static int32 GetVehicleTargetGear(void* vehicle); static void SetVehicleTargetGear(void* vehicle, int32 value); diff --git a/Source/Engine/Physics/PhysicsBackendEmpty.cpp b/Source/Engine/Physics/PhysicsBackendEmpty.cpp index 516562e28..28d849a32 100644 --- a/Source/Engine/Physics/PhysicsBackendEmpty.cpp +++ b/Source/Engine/Physics/PhysicsBackendEmpty.cpp @@ -732,6 +732,10 @@ void PhysicsBackend::DestroyVehicle(void* vehicle, int32 driveType) { } +void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor) +{ +} + void PhysicsBackend::SetVehicleGearbox(void* vehicle, const void* value) { }