diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index 388aa1f21..2c21e8880 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -300,6 +300,7 @@ void WheeledVehicle::Setup() auto& data = _wheelsData[i]; data.Collider = wheel.Collider; data.LocalOrientation = wheel.Collider->GetLocalOrientation(); + data.ChildrenPoses.Resize(0); PxVehicleSuspensionData suspensionData; const float suspensionFrequency = 7.0f; @@ -507,11 +508,25 @@ void WheeledVehicle::Setup() void WheeledVehicle::DrawPhysicsDebug(RenderView& view) { // Wheels shapes - for (auto& wheel : _wheels) + for (auto& data : _wheelsData) { + int32 wheelIndex = 0; + for (; wheelIndex < _wheels.Count(); wheelIndex++) + { + if (_wheels[wheelIndex].Collider == data.Collider) + break; + } + if (wheelIndex == _wheels.Count()) + break; + auto& wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { - DEBUG_DRAW_WIRE_CYLINDER(wheel.Collider->GetPosition(), wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.8f, 0, true); + const Vector3 basePos = wheel.Collider->GetPosition(); + const Vector3 currentPos = basePos + Vector3(0, data.State.SuspensionOffset, 0); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(basePos, wheel.Radius * 0.07f), Color::Blue * 0.3f, 0, true); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(currentPos, wheel.Radius * 0.08f), Color::Blue * 0.8f, 0, true); + DEBUG_DRAW_LINE(basePos, currentPos, Color::Blue, 0, true); + DEBUG_DRAW_WIRE_CYLINDER(currentPos, wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.8f, 0, true); } } } @@ -519,11 +534,25 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view) void WheeledVehicle::OnDebugDrawSelected() { // Wheels shapes - for (auto& wheel : _wheels) + for (auto& data : _wheelsData) { + int32 wheelIndex = 0; + for (; wheelIndex < _wheels.Count(); wheelIndex++) + { + if (_wheels[wheelIndex].Collider == data.Collider) + break; + } + if (wheelIndex == _wheels.Count()) + break; + auto& wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { - DEBUG_DRAW_WIRE_CYLINDER(wheel.Collider->GetPosition(), wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.4f, 0, false); + const Vector3 basePos = wheel.Collider->GetPosition(); + const Vector3 currentPos = basePos + Vector3(0, data.State.SuspensionOffset, 0); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(basePos, wheel.Radius * 0.07f), Color::Blue * 0.3f, 0, false); + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(currentPos, wheel.Radius * 0.08f), Color::Blue * 0.8f, 0, false); + DEBUG_DRAW_LINE(basePos, currentPos, Color::Blue, 0, false); + DEBUG_DRAW_WIRE_CYLINDER(currentPos, wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.4f, 0, false); } } diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index a6a1708ad..12b5c864c 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -285,6 +285,12 @@ private: Collider* Collider; Quaternion LocalOrientation; WheelState State; + struct ChildPose + { + Actor* Child; + Vector3 Pose; + }; + Array> ChildrenPoses; }; void* _drive = nullptr; diff --git a/Source/Engine/Physics/Physics.cpp b/Source/Engine/Physics/Physics.cpp index 8066f404d..07b9de909 100644 --- a/Source/Engine/Physics/Physics.cpp +++ b/Source/Engine/Physics/Physics.cpp @@ -847,10 +847,24 @@ void Physics::CollectResults() state.TireFriction = perWheel.tireFriction; state.SteerAngle = RadiansToDegrees * perWheel.steerAngle; state.RotationAngle = -RadiansToDegrees * drive->mWheelsDynData.getWheelRotationAngle(j); - const float suspensionOffsetDelta = perWheel.suspJounce - state.SuspensionOffset; state.SuspensionOffset = perWheel.suspJounce; + // Rotate wheel wheelData.Collider->SetLocalOrientation(Quaternion::Euler(0, state.SteerAngle, state.RotationAngle) * wheelData.LocalOrientation); + + // Apply suspension offset (cannot move collider because it breaks driving so move it's children but preserve the initial pose) + for (auto child : wheelData.Collider->Children) + { + int32 poseIndex = 0; + for (; poseIndex < wheelData.ChildrenPoses.Count(); poseIndex++) + { + if (wheelData.ChildrenPoses[poseIndex].Child == child) + break; + } + if (poseIndex == wheelData.ChildrenPoses.Count()) + wheelData.ChildrenPoses.Add({ child, child->GetLocalPosition() }); + child->SetPosition(wheelData.Collider->GetTransform().LocalToWorld(wheelData.ChildrenPoses[poseIndex].Pose) + Vector3(0, perWheel.suspJounce, 0)); + } } } }