Support for N Wheeled vehicles
This commit is contained in:
parent
207ac8c78c
commit
0a9f67c6c3
|
@ -93,7 +93,8 @@ public class Carla : ModuleRules
|
|||
"PhysXVehicles",
|
||||
"PhysXVehicleLib",
|
||||
"Slate",
|
||||
"SlateCore"
|
||||
"SlateCore",
|
||||
"PhysicsCore"
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "MovementComponents/BaseCarlaMovementComponent.h"
|
||||
#include "DisplayDebugHelpers.h"
|
||||
|
||||
#include "CarlaSimpleVehicle.generated.h"
|
||||
|
||||
|
||||
UCLASS()
|
||||
class CARLA_API ACarlaSimpleVehicle : public APawn
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ACarlaSimpleVehicle(const FObjectInitializer& ObjectInitializer);
|
||||
~ACarlaSimpleVehicle();
|
||||
|
||||
protected:
|
||||
// Called when the game starts or when spawned
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
/** The main skeletal mesh associated with this Vehicle */
|
||||
UPROPERTY(Category = Vehicle, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
|
||||
class USkeletalMeshComponent* Mesh;
|
||||
|
||||
/** vehicle simulation component */
|
||||
UPROPERTY(Category = Vehicle, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
|
||||
class UWheeledVehicleMovementComponent* VehicleMovement;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** Name of the MeshComponent. Use this name if you want to prevent creation of the component (with ObjectInitializer.DoNotCreateDefaultSubobject). */
|
||||
static FName VehicleMeshComponentName;
|
||||
|
||||
/** Name of the VehicleMovement. Use this name if you want to use a different class (with ObjectInitializer.SetDefaultSubobjectClass). */
|
||||
static FName VehicleMovementComponentName;
|
||||
|
||||
/** Util to get the wheeled vehicle movement component */
|
||||
class UWheeledVehicleMovementComponent* GetVehicleMovementComponent() const;
|
||||
|
||||
//~ Begin AActor Interface
|
||||
virtual void DisplayDebug(class UCanvas* Canvas, const FDebugDisplayInfo& DebugDisplay, float& YL, float& YPos) override;
|
||||
//~ End Actor Interface
|
||||
|
||||
/** Returns Mesh subobject **/
|
||||
class USkeletalMeshComponent* GetMesh() const { return Mesh; }
|
||||
/** Returns VehicleMovement subobject **/
|
||||
class UWheeledVehicleMovementComponent* GetVehicleMovement() const { return VehicleMovement; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Category = "CARLA Simple Wheeled Vehicle", VisibleAnywhere)
|
||||
bool bPhysicsEnabled = true;
|
||||
|
||||
// Small workarround to allow optional CarSim plugin usage
|
||||
UPROPERTY(Category = "CARLA Simple Wheeled Vehicle", VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
|
||||
UBaseCarlaMovementComponent* BaseMovementComponent = nullptr;
|
||||
};
|
||||
|
||||
|
||||
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
|
@ -74,6 +74,26 @@ void ACarlaWheeledVehicle::SetWheelCollision(UWheeledVehicleMovementComponent4W
|
|||
|
||||
}
|
||||
|
||||
void ACarlaWheeledVehicle::SetWheelCollisionNW(UWheeledVehicleMovementComponentNW *VehicleNW,
|
||||
const FVehiclePhysicsControl &PhysicsControl ) {
|
||||
|
||||
#ifdef WHEEL_SWEEP_ENABLED
|
||||
const bool IsEqual = VehicleNW->UseSweepWheelCollision == PhysicsControl.UseSweepWheelCollision;
|
||||
|
||||
if (IsEqual)
|
||||
return;
|
||||
|
||||
VehicleNW->UseSweepWheelCollision = PhysicsControl.UseSweepWheelCollision;
|
||||
|
||||
#else
|
||||
|
||||
if (PhysicsControl.UseSweepWheelCollision)
|
||||
UE_LOG(LogCarla, Warning, TEXT("Error: Sweep for wheel collision is not available. \
|
||||
Make sure you have installed the required patch.") );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void ACarlaWheeledVehicle::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
@ -136,42 +156,44 @@ void ACarlaWheeledVehicle::BeginPlay()
|
|||
|
||||
float FrictionScale = 3.5f;
|
||||
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovementComponent());
|
||||
check(Vehicle4W != nullptr);
|
||||
UWheeledVehicleMovementComponent* MovementComponent = GetVehicleMovementComponent();
|
||||
|
||||
// Setup Tire Configs with default value. This is needed to avoid getting
|
||||
// friction values of previously created TireConfigs for the same vehicle
|
||||
// blueprint.
|
||||
TArray<float> OriginalFrictions;
|
||||
OriginalFrictions.Init(FrictionScale, Vehicle4W->Wheels.Num());
|
||||
SetWheelsFrictionScale(OriginalFrictions);
|
||||
|
||||
// Check if it overlaps with a Friction trigger, if so, update the friction
|
||||
// scale.
|
||||
TArray<AActor *> OverlapActors;
|
||||
GetOverlappingActors(OverlapActors, AFrictionTrigger::StaticClass());
|
||||
for (const auto &Actor : OverlapActors)
|
||||
if (MovementComponent)
|
||||
{
|
||||
AFrictionTrigger *FrictionTrigger = Cast<AFrictionTrigger>(Actor);
|
||||
if (FrictionTrigger)
|
||||
check(MovementComponent != nullptr);
|
||||
|
||||
// Setup Tire Configs with default value. This is needed to avoid getting
|
||||
// friction values of previously created TireConfigs for the same vehicle
|
||||
// blueprint.
|
||||
TArray<float> OriginalFrictions;
|
||||
OriginalFrictions.Init(FrictionScale, MovementComponent->Wheels.Num());
|
||||
SetWheelsFrictionScale(OriginalFrictions);
|
||||
|
||||
// Check if it overlaps with a Friction trigger, if so, update the friction
|
||||
// scale.
|
||||
TArray<AActor *> OverlapActors;
|
||||
GetOverlappingActors(OverlapActors, AFrictionTrigger::StaticClass());
|
||||
for (const auto &Actor : OverlapActors)
|
||||
{
|
||||
FrictionScale = FrictionTrigger->Friction;
|
||||
AFrictionTrigger *FrictionTrigger = Cast<AFrictionTrigger>(Actor);
|
||||
if (FrictionTrigger)
|
||||
{
|
||||
FrictionScale = FrictionTrigger->Friction;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the friction scale to Wheel CDO and update wheel setups
|
||||
TArray<FWheelSetup> NewWheelSetups = MovementComponent->WheelSetups;
|
||||
for (const auto &WheelSetup : NewWheelSetups)
|
||||
{
|
||||
UVehicleWheel *Wheel = WheelSetup.WheelClass.GetDefaultObject();
|
||||
check(Wheel != nullptr);
|
||||
}
|
||||
|
||||
MovementComponent->WheelSetups = NewWheelSetups;
|
||||
|
||||
LastPhysicsControl = GetVehiclePhysicsControl();
|
||||
}
|
||||
|
||||
// Set the friction scale to Wheel CDO and update wheel setups
|
||||
TArray<FWheelSetup> NewWheelSetups = Vehicle4W->WheelSetups;
|
||||
|
||||
for (const auto &WheelSetup : NewWheelSetups)
|
||||
{
|
||||
UVehicleWheel *Wheel = WheelSetup.WheelClass.GetDefaultObject();
|
||||
check(Wheel != nullptr);
|
||||
}
|
||||
|
||||
Vehicle4W->WheelSetups = NewWheelSetups;
|
||||
|
||||
LastPhysicsControl = GetVehiclePhysicsControl();
|
||||
}
|
||||
|
||||
void ACarlaWheeledVehicle::AdjustVehicleBounds()
|
||||
|
@ -282,111 +304,199 @@ void ACarlaWheeledVehicle::SetHandbrakeInput(const bool Value)
|
|||
|
||||
TArray<float> ACarlaWheeledVehicle::GetWheelsFrictionScale()
|
||||
{
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
|
||||
UWheeledVehicleMovementComponent* Movement = GetVehicleMovement();
|
||||
TArray<float> WheelsFrictionScale;
|
||||
for (auto &Wheel : Vehicle4W->Wheels)
|
||||
if (Movement)
|
||||
{
|
||||
WheelsFrictionScale.Add(Wheel->TireConfig->GetFrictionScale());
|
||||
check(Movement != nullptr);
|
||||
|
||||
for (auto &Wheel : Movement->Wheels)
|
||||
{
|
||||
WheelsFrictionScale.Add(Wheel->TireConfig->GetFrictionScale());
|
||||
}
|
||||
}
|
||||
return WheelsFrictionScale;
|
||||
}
|
||||
|
||||
void ACarlaWheeledVehicle::SetWheelsFrictionScale(TArray<float> &WheelsFrictionScale)
|
||||
{
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
check(Vehicle4W->Wheels.Num() == WheelsFrictionScale.Num());
|
||||
|
||||
for (int32 i = 0; i < Vehicle4W->Wheels.Num(); ++i)
|
||||
UWheeledVehicleMovementComponent* Movement = GetVehicleMovement();
|
||||
if (Movement)
|
||||
{
|
||||
Vehicle4W->Wheels[i]->TireConfig->SetFrictionScale(WheelsFrictionScale[i]);
|
||||
check(Movement != nullptr);
|
||||
check(Movement->Wheels.Num() == WheelsFrictionScale.Num());
|
||||
|
||||
for (int32 i = 0; i < Movement->Wheels.Num(); ++i)
|
||||
{
|
||||
Movement->Wheels[i]->TireConfig->SetFrictionScale(WheelsFrictionScale[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FVehiclePhysicsControl ACarlaWheeledVehicle::GetVehiclePhysicsControl() const
|
||||
{
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
|
||||
FVehiclePhysicsControl PhysicsControl;
|
||||
|
||||
// Engine Setup
|
||||
PhysicsControl.TorqueCurve = Vehicle4W->EngineSetup.TorqueCurve.EditorCurveData;
|
||||
PhysicsControl.MaxRPM = Vehicle4W->EngineSetup.MaxRPM;
|
||||
PhysicsControl.MOI = Vehicle4W->EngineSetup.MOI;
|
||||
PhysicsControl.DampingRateFullThrottle = Vehicle4W->EngineSetup.DampingRateFullThrottle;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged =
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchEngaged;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged =
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchDisengaged;
|
||||
if (!bIsSixWVehicle) {
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
|
||||
// Transmission Setup
|
||||
PhysicsControl.bUseGearAutoBox = Vehicle4W->TransmissionSetup.bUseGearAutoBox;
|
||||
PhysicsControl.GearSwitchTime = Vehicle4W->TransmissionSetup.GearSwitchTime;
|
||||
PhysicsControl.ClutchStrength = Vehicle4W->TransmissionSetup.ClutchStrength;
|
||||
PhysicsControl.FinalRatio = Vehicle4W->TransmissionSetup.FinalRatio;
|
||||
// Engine Setup
|
||||
PhysicsControl.TorqueCurve = Vehicle4W->EngineSetup.TorqueCurve.EditorCurveData;
|
||||
PhysicsControl.MaxRPM = Vehicle4W->EngineSetup.MaxRPM;
|
||||
PhysicsControl.MOI = Vehicle4W->EngineSetup.MOI;
|
||||
PhysicsControl.DampingRateFullThrottle = Vehicle4W->EngineSetup.DampingRateFullThrottle;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged =
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchEngaged;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged =
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
TArray<FGearPhysicsControl> ForwardGears;
|
||||
// Transmission Setup
|
||||
PhysicsControl.bUseGearAutoBox = Vehicle4W->TransmissionSetup.bUseGearAutoBox;
|
||||
PhysicsControl.GearSwitchTime = Vehicle4W->TransmissionSetup.GearSwitchTime;
|
||||
PhysicsControl.ClutchStrength = Vehicle4W->TransmissionSetup.ClutchStrength;
|
||||
PhysicsControl.FinalRatio = Vehicle4W->TransmissionSetup.FinalRatio;
|
||||
|
||||
for (const auto &Gear : Vehicle4W->TransmissionSetup.ForwardGears)
|
||||
{
|
||||
FGearPhysicsControl GearPhysicsControl;
|
||||
TArray<FGearPhysicsControl> ForwardGears;
|
||||
|
||||
GearPhysicsControl.Ratio = Gear.Ratio;
|
||||
GearPhysicsControl.UpRatio = Gear.UpRatio;
|
||||
GearPhysicsControl.DownRatio = Gear.DownRatio;
|
||||
for (const auto &Gear : Vehicle4W->TransmissionSetup.ForwardGears)
|
||||
{
|
||||
FGearPhysicsControl GearPhysicsControl;
|
||||
|
||||
GearPhysicsControl.Ratio = Gear.Ratio;
|
||||
GearPhysicsControl.UpRatio = Gear.UpRatio;
|
||||
GearPhysicsControl.DownRatio = Gear.DownRatio;
|
||||
|
||||
ForwardGears.Add(GearPhysicsControl);
|
||||
}
|
||||
|
||||
PhysicsControl.ForwardGears = ForwardGears;
|
||||
|
||||
// Vehicle Setup
|
||||
PhysicsControl.Mass = Vehicle4W->Mass;
|
||||
PhysicsControl.DragCoefficient = Vehicle4W->DragCoefficient;
|
||||
|
||||
// Center of mass offset (Center of mass is always zero vector in local
|
||||
// position)
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(Vehicle4W->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
PhysicsControl.CenterOfMass = UpdatedPrimitive->BodyInstance.COMNudge;
|
||||
|
||||
// Transmission Setup
|
||||
PhysicsControl.SteeringCurve = Vehicle4W->SteeringCurve.EditorCurveData;
|
||||
|
||||
// Wheels Setup
|
||||
TArray<FWheelPhysicsControl> Wheels;
|
||||
|
||||
for (int32 i = 0; i < Vehicle4W->WheelSetups.Num(); ++i)
|
||||
{
|
||||
FWheelPhysicsControl PhysicsWheel;
|
||||
|
||||
PxVehicleWheelData PWheelData = Vehicle4W->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
PhysicsWheel.DampingRate = Cm2ToM2(PWheelData.mDampingRate);
|
||||
PhysicsWheel.MaxSteerAngle = FMath::RadiansToDegrees(PWheelData.mMaxSteer);
|
||||
PhysicsWheel.Radius = PWheelData.mRadius;
|
||||
PhysicsWheel.MaxBrakeTorque = Cm2ToM2(PWheelData.mMaxBrakeTorque);
|
||||
PhysicsWheel.MaxHandBrakeTorque = Cm2ToM2(PWheelData.mMaxHandBrakeTorque);
|
||||
|
||||
PxVehicleTireData PTireData = Vehicle4W->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PhysicsWheel.LatStiffMaxLoad = PTireData.mLatStiffX;
|
||||
PhysicsWheel.LatStiffValue = PTireData.mLatStiffY;
|
||||
PhysicsWheel.LongStiffValue = PTireData.mLongitudinalStiffnessPerUnitGravity;
|
||||
|
||||
PhysicsWheel.TireFriction = Vehicle4W->Wheels[i]->TireConfig->GetFrictionScale();
|
||||
PhysicsWheel.Position = Vehicle4W->Wheels[i]->Location;
|
||||
|
||||
Wheels.Add(PhysicsWheel);
|
||||
}
|
||||
|
||||
PhysicsControl.Wheels = Wheels;
|
||||
|
||||
} else {
|
||||
UWheeledVehicleMovementComponentNW *VehicleNW = Cast<UWheeledVehicleMovementComponentNW>(
|
||||
GetVehicleMovement());
|
||||
|
||||
check(VehicleNW != nullptr);
|
||||
|
||||
// Engine Setup
|
||||
PhysicsControl.TorqueCurve = VehicleNW->EngineSetup.TorqueCurve.EditorCurveData;
|
||||
PhysicsControl.MaxRPM = VehicleNW->EngineSetup.MaxRPM;
|
||||
PhysicsControl.MOI = VehicleNW->EngineSetup.MOI;
|
||||
PhysicsControl.DampingRateFullThrottle = VehicleNW->EngineSetup.DampingRateFullThrottle;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged =
|
||||
VehicleNW->EngineSetup.DampingRateZeroThrottleClutchEngaged;
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged =
|
||||
VehicleNW->EngineSetup.DampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
// Transmission Setup
|
||||
PhysicsControl.bUseGearAutoBox = VehicleNW->TransmissionSetup.bUseGearAutoBox;
|
||||
PhysicsControl.GearSwitchTime = VehicleNW->TransmissionSetup.GearSwitchTime;
|
||||
PhysicsControl.ClutchStrength = VehicleNW->TransmissionSetup.ClutchStrength;
|
||||
PhysicsControl.FinalRatio = VehicleNW->TransmissionSetup.FinalRatio;
|
||||
|
||||
TArray<FGearPhysicsControl> ForwardGears;
|
||||
|
||||
for (const auto &Gear : VehicleNW->TransmissionSetup.ForwardGears)
|
||||
{
|
||||
FGearPhysicsControl GearPhysicsControl;
|
||||
|
||||
GearPhysicsControl.Ratio = Gear.Ratio;
|
||||
GearPhysicsControl.UpRatio = Gear.UpRatio;
|
||||
GearPhysicsControl.DownRatio = Gear.DownRatio;
|
||||
|
||||
ForwardGears.Add(GearPhysicsControl);
|
||||
}
|
||||
|
||||
PhysicsControl.ForwardGears = ForwardGears;
|
||||
|
||||
// VehicleNW Setup
|
||||
PhysicsControl.Mass = VehicleNW->Mass;
|
||||
PhysicsControl.DragCoefficient = VehicleNW->DragCoefficient;
|
||||
|
||||
// Center of mass offset (Center of mass is always zero vector in local
|
||||
// position)
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(VehicleNW->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
PhysicsControl.CenterOfMass = UpdatedPrimitive->BodyInstance.COMNudge;
|
||||
|
||||
// Transmission Setup
|
||||
PhysicsControl.SteeringCurve = VehicleNW->SteeringCurve.EditorCurveData;
|
||||
|
||||
// Wheels Setup
|
||||
TArray<FWheelPhysicsControl> Wheels;
|
||||
|
||||
for (int32 i = 0; i < VehicleNW->WheelSetups.Num(); ++i)
|
||||
{
|
||||
FWheelPhysicsControl PhysicsWheel;
|
||||
|
||||
PxVehicleWheelData PWheelData = VehicleNW->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
PhysicsWheel.DampingRate = Cm2ToM2(PWheelData.mDampingRate);
|
||||
PhysicsWheel.MaxSteerAngle = FMath::RadiansToDegrees(PWheelData.mMaxSteer);
|
||||
PhysicsWheel.Radius = PWheelData.mRadius;
|
||||
PhysicsWheel.MaxBrakeTorque = Cm2ToM2(PWheelData.mMaxBrakeTorque);
|
||||
PhysicsWheel.MaxHandBrakeTorque = Cm2ToM2(PWheelData.mMaxHandBrakeTorque);
|
||||
|
||||
PxVehicleTireData PTireData = VehicleNW->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PhysicsWheel.LatStiffMaxLoad = PTireData.mLatStiffX;
|
||||
PhysicsWheel.LatStiffValue = PTireData.mLatStiffY;
|
||||
PhysicsWheel.LongStiffValue = PTireData.mLongitudinalStiffnessPerUnitGravity;
|
||||
|
||||
PhysicsWheel.TireFriction = VehicleNW->Wheels[i]->TireConfig->GetFrictionScale();
|
||||
PhysicsWheel.Position = VehicleNW->Wheels[i]->Location;
|
||||
|
||||
Wheels.Add(PhysicsWheel);
|
||||
}
|
||||
|
||||
PhysicsControl.Wheels = Wheels;
|
||||
|
||||
ForwardGears.Add(GearPhysicsControl);
|
||||
}
|
||||
|
||||
PhysicsControl.ForwardGears = ForwardGears;
|
||||
|
||||
// Vehicle Setup
|
||||
PhysicsControl.Mass = Vehicle4W->Mass;
|
||||
PhysicsControl.DragCoefficient = Vehicle4W->DragCoefficient;
|
||||
|
||||
// Center of mass offset (Center of mass is always zero vector in local
|
||||
// position)
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(Vehicle4W->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
PhysicsControl.CenterOfMass = UpdatedPrimitive->BodyInstance.COMNudge;
|
||||
|
||||
// Transmission Setup
|
||||
PhysicsControl.SteeringCurve = Vehicle4W->SteeringCurve.EditorCurveData;
|
||||
|
||||
// Wheels Setup
|
||||
TArray<FWheelPhysicsControl> Wheels;
|
||||
|
||||
for (int32 i = 0; i < Vehicle4W->WheelSetups.Num(); ++i)
|
||||
{
|
||||
FWheelPhysicsControl PhysicsWheel;
|
||||
|
||||
PxVehicleWheelData PWheelData = Vehicle4W->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
PhysicsWheel.DampingRate = Cm2ToM2(PWheelData.mDampingRate);
|
||||
PhysicsWheel.MaxSteerAngle = FMath::RadiansToDegrees(PWheelData.mMaxSteer);
|
||||
PhysicsWheel.Radius = PWheelData.mRadius;
|
||||
PhysicsWheel.MaxBrakeTorque = Cm2ToM2(PWheelData.mMaxBrakeTorque);
|
||||
PhysicsWheel.MaxHandBrakeTorque = Cm2ToM2(PWheelData.mMaxHandBrakeTorque);
|
||||
|
||||
PxVehicleTireData PTireData = Vehicle4W->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PhysicsWheel.LatStiffMaxLoad = PTireData.mLatStiffX;
|
||||
PhysicsWheel.LatStiffValue = PTireData.mLatStiffY;
|
||||
PhysicsWheel.LongStiffValue = PTireData.mLongitudinalStiffnessPerUnitGravity;
|
||||
|
||||
PhysicsWheel.TireFriction = Vehicle4W->Wheels[i]->TireConfig->GetFrictionScale();
|
||||
PhysicsWheel.Position = Vehicle4W->Wheels[i]->Location;
|
||||
|
||||
Wheels.Add(PhysicsWheel);
|
||||
}
|
||||
|
||||
PhysicsControl.Wheels = Wheels;
|
||||
|
||||
return PhysicsControl;
|
||||
}
|
||||
|
||||
|
@ -403,109 +513,209 @@ void ACarlaWheeledVehicle::RestoreVehiclePhysicsControl()
|
|||
void ACarlaWheeledVehicle::ApplyVehiclePhysicsControl(const FVehiclePhysicsControl &PhysicsControl)
|
||||
{
|
||||
LastPhysicsControl = PhysicsControl;
|
||||
if (!bIsSixWVehicle) {
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
// Engine Setup
|
||||
Vehicle4W->EngineSetup.TorqueCurve.EditorCurveData = PhysicsControl.TorqueCurve;
|
||||
Vehicle4W->EngineSetup.MaxRPM = PhysicsControl.MaxRPM;
|
||||
|
||||
// Engine Setup
|
||||
Vehicle4W->EngineSetup.TorqueCurve.EditorCurveData = PhysicsControl.TorqueCurve;
|
||||
Vehicle4W->EngineSetup.MaxRPM = PhysicsControl.MaxRPM;
|
||||
Vehicle4W->EngineSetup.MOI = PhysicsControl.MOI;
|
||||
|
||||
Vehicle4W->EngineSetup.MOI = PhysicsControl.MOI;
|
||||
Vehicle4W->EngineSetup.DampingRateFullThrottle = PhysicsControl.DampingRateFullThrottle;
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchEngaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged;
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchDisengaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
Vehicle4W->EngineSetup.DampingRateFullThrottle = PhysicsControl.DampingRateFullThrottle;
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchEngaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged;
|
||||
Vehicle4W->EngineSetup.DampingRateZeroThrottleClutchDisengaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged;
|
||||
// Transmission Setup
|
||||
Vehicle4W->TransmissionSetup.bUseGearAutoBox = PhysicsControl.bUseGearAutoBox;
|
||||
Vehicle4W->TransmissionSetup.GearSwitchTime = PhysicsControl.GearSwitchTime;
|
||||
Vehicle4W->TransmissionSetup.ClutchStrength = PhysicsControl.ClutchStrength;
|
||||
Vehicle4W->TransmissionSetup.FinalRatio = PhysicsControl.FinalRatio;
|
||||
|
||||
// Transmission Setup
|
||||
Vehicle4W->TransmissionSetup.bUseGearAutoBox = PhysicsControl.bUseGearAutoBox;
|
||||
Vehicle4W->TransmissionSetup.GearSwitchTime = PhysicsControl.GearSwitchTime;
|
||||
Vehicle4W->TransmissionSetup.ClutchStrength = PhysicsControl.ClutchStrength;
|
||||
Vehicle4W->TransmissionSetup.FinalRatio = PhysicsControl.FinalRatio;
|
||||
TArray<FVehicleGearData> ForwardGears;
|
||||
|
||||
TArray<FVehicleGearData> ForwardGears;
|
||||
for (const auto &Gear : PhysicsControl.ForwardGears)
|
||||
{
|
||||
FVehicleGearData GearData;
|
||||
|
||||
for (const auto &Gear : PhysicsControl.ForwardGears)
|
||||
{
|
||||
FVehicleGearData GearData;
|
||||
GearData.Ratio = Gear.Ratio;
|
||||
GearData.UpRatio = Gear.UpRatio;
|
||||
GearData.DownRatio = Gear.DownRatio;
|
||||
|
||||
GearData.Ratio = Gear.Ratio;
|
||||
GearData.UpRatio = Gear.UpRatio;
|
||||
GearData.DownRatio = Gear.DownRatio;
|
||||
ForwardGears.Add(GearData);
|
||||
}
|
||||
|
||||
Vehicle4W->TransmissionSetup.ForwardGears = ForwardGears;
|
||||
|
||||
// Vehicle Setup
|
||||
Vehicle4W->Mass = PhysicsControl.Mass;
|
||||
Vehicle4W->DragCoefficient = PhysicsControl.DragCoefficient;
|
||||
|
||||
// Center of mass
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(Vehicle4W->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
UpdatedPrimitive->BodyInstance.COMNudge = PhysicsControl.CenterOfMass;
|
||||
|
||||
// Transmission Setup
|
||||
Vehicle4W->SteeringCurve.EditorCurveData = PhysicsControl.SteeringCurve;
|
||||
|
||||
// Wheels Setup
|
||||
const int PhysicsWheelsNum = PhysicsControl.Wheels.Num();
|
||||
if (PhysicsWheelsNum != 4)
|
||||
{
|
||||
UE_LOG(LogCarla, Error, TEXT("Number of WheelPhysicsControl is not 4."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Change, if required, the collision mode for wheels
|
||||
SetWheelCollision(Vehicle4W, PhysicsControl);
|
||||
|
||||
TArray<FWheelSetup> NewWheelSetups = Vehicle4W->WheelSetups;
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
UVehicleWheel *Wheel = NewWheelSetups[i].WheelClass.GetDefaultObject();
|
||||
check(Wheel != nullptr);
|
||||
|
||||
// Assigning new tire config
|
||||
Wheel->TireConfig = DuplicateObject<UTireConfig>(Wheel->TireConfig, nullptr);
|
||||
|
||||
// Setting a new value to friction
|
||||
Wheel->TireConfig->SetFrictionScale(PhysicsControl.Wheels[i].TireFriction);
|
||||
}
|
||||
|
||||
Vehicle4W->WheelSetups = NewWheelSetups;
|
||||
|
||||
// Recreate Physics State for vehicle setup
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->lockWrite();
|
||||
Vehicle4W->RecreatePhysicsState();
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->unlockWrite();
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
PxVehicleWheelData PWheelData = Vehicle4W->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
|
||||
PWheelData.mRadius = PhysicsControl.Wheels[i].Radius;
|
||||
PWheelData.mMaxSteer = FMath::DegreesToRadians(PhysicsControl.Wheels[i].MaxSteerAngle);
|
||||
PWheelData.mDampingRate = M2ToCm2(PhysicsControl.Wheels[i].DampingRate);
|
||||
PWheelData.mMaxBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxBrakeTorque);
|
||||
PWheelData.mMaxHandBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxHandBrakeTorque);
|
||||
Vehicle4W->PVehicle->mWheelsSimData.setWheelData(i, PWheelData);
|
||||
|
||||
PxVehicleTireData PTireData = Vehicle4W->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PTireData.mLatStiffX = PhysicsControl.Wheels[i].LatStiffMaxLoad;
|
||||
PTireData.mLatStiffY = PhysicsControl.Wheels[i].LatStiffValue;
|
||||
PTireData.mLongitudinalStiffnessPerUnitGravity = PhysicsControl.Wheels[i].LongStiffValue;
|
||||
Vehicle4W->PVehicle->mWheelsSimData.setTireData(i, PTireData);
|
||||
}
|
||||
|
||||
ResetConstraints();
|
||||
} else {
|
||||
UWheeledVehicleMovementComponentNW *VehicleNW = Cast<UWheeledVehicleMovementComponentNW>(
|
||||
GetVehicleMovement());
|
||||
|
||||
check(VehicleNW != nullptr);
|
||||
|
||||
// Engine Setup
|
||||
VehicleNW->EngineSetup.TorqueCurve.EditorCurveData = PhysicsControl.TorqueCurve;
|
||||
VehicleNW->EngineSetup.MaxRPM = PhysicsControl.MaxRPM;
|
||||
|
||||
VehicleNW->EngineSetup.MOI = PhysicsControl.MOI;
|
||||
|
||||
VehicleNW->EngineSetup.DampingRateFullThrottle = PhysicsControl.DampingRateFullThrottle;
|
||||
VehicleNW->EngineSetup.DampingRateZeroThrottleClutchEngaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchEngaged;
|
||||
VehicleNW->EngineSetup.DampingRateZeroThrottleClutchDisengaged =
|
||||
PhysicsControl.DampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
// Transmission Setup
|
||||
VehicleNW->TransmissionSetup.bUseGearAutoBox = PhysicsControl.bUseGearAutoBox;
|
||||
VehicleNW->TransmissionSetup.GearSwitchTime = PhysicsControl.GearSwitchTime;
|
||||
VehicleNW->TransmissionSetup.ClutchStrength = PhysicsControl.ClutchStrength;
|
||||
VehicleNW->TransmissionSetup.FinalRatio = PhysicsControl.FinalRatio;
|
||||
|
||||
TArray<FVehicleNWGearData> ForwardGears;
|
||||
|
||||
for (const auto &Gear : PhysicsControl.ForwardGears)
|
||||
{
|
||||
FVehicleNWGearData GearData;
|
||||
|
||||
GearData.Ratio = Gear.Ratio;
|
||||
GearData.UpRatio = Gear.UpRatio;
|
||||
GearData.DownRatio = Gear.DownRatio;
|
||||
|
||||
ForwardGears.Add(GearData);
|
||||
}
|
||||
|
||||
VehicleNW->TransmissionSetup.ForwardGears = ForwardGears;
|
||||
|
||||
// VehicleNW Setup
|
||||
VehicleNW->Mass = PhysicsControl.Mass;
|
||||
VehicleNW->DragCoefficient = PhysicsControl.DragCoefficient;
|
||||
|
||||
// Center of mass
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(VehicleNW->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
UpdatedPrimitive->BodyInstance.COMNudge = PhysicsControl.CenterOfMass;
|
||||
|
||||
// Transmission Setup
|
||||
VehicleNW->SteeringCurve.EditorCurveData = PhysicsControl.SteeringCurve;
|
||||
|
||||
// Wheels Setup
|
||||
const int PhysicsWheelsNum = PhysicsControl.Wheels.Num();
|
||||
|
||||
// Change, if required, the collision mode for wheels
|
||||
SetWheelCollisionNW(VehicleNW, PhysicsControl);
|
||||
|
||||
TArray<FWheelSetup> NewWheelSetups = VehicleNW->WheelSetups;
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
UVehicleWheel *Wheel = NewWheelSetups[i].WheelClass.GetDefaultObject();
|
||||
check(Wheel != nullptr);
|
||||
|
||||
// Assigning new tire config
|
||||
Wheel->TireConfig = DuplicateObject<UTireConfig>(Wheel->TireConfig, nullptr);
|
||||
|
||||
// Setting a new value to friction
|
||||
Wheel->TireConfig->SetFrictionScale(PhysicsControl.Wheels[i].TireFriction);
|
||||
}
|
||||
|
||||
VehicleNW->WheelSetups = NewWheelSetups;
|
||||
|
||||
// Recreate Physics State for vehicle setup
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->lockWrite();
|
||||
VehicleNW->RecreatePhysicsState();
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->unlockWrite();
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
PxVehicleWheelData PWheelData = VehicleNW->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
|
||||
PWheelData.mRadius = PhysicsControl.Wheels[i].Radius;
|
||||
PWheelData.mMaxSteer = FMath::DegreesToRadians(PhysicsControl.Wheels[i].MaxSteerAngle);
|
||||
PWheelData.mDampingRate = M2ToCm2(PhysicsControl.Wheels[i].DampingRate);
|
||||
PWheelData.mMaxBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxBrakeTorque);
|
||||
PWheelData.mMaxHandBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxHandBrakeTorque);
|
||||
VehicleNW->PVehicle->mWheelsSimData.setWheelData(i, PWheelData);
|
||||
|
||||
PxVehicleTireData PTireData = VehicleNW->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PTireData.mLatStiffX = PhysicsControl.Wheels[i].LatStiffMaxLoad;
|
||||
PTireData.mLatStiffY = PhysicsControl.Wheels[i].LatStiffValue;
|
||||
PTireData.mLongitudinalStiffnessPerUnitGravity = PhysicsControl.Wheels[i].LongStiffValue;
|
||||
VehicleNW->PVehicle->mWheelsSimData.setTireData(i, PTireData);
|
||||
}
|
||||
|
||||
ResetConstraints();
|
||||
|
||||
ForwardGears.Add(GearData);
|
||||
}
|
||||
|
||||
Vehicle4W->TransmissionSetup.ForwardGears = ForwardGears;
|
||||
|
||||
// Vehicle Setup
|
||||
Vehicle4W->Mass = PhysicsControl.Mass;
|
||||
Vehicle4W->DragCoefficient = PhysicsControl.DragCoefficient;
|
||||
|
||||
// Center of mass
|
||||
UPrimitiveComponent *UpdatedPrimitive = Cast<UPrimitiveComponent>(Vehicle4W->UpdatedComponent);
|
||||
check(UpdatedPrimitive != nullptr);
|
||||
|
||||
UpdatedPrimitive->BodyInstance.COMNudge = PhysicsControl.CenterOfMass;
|
||||
|
||||
// Transmission Setup
|
||||
Vehicle4W->SteeringCurve.EditorCurveData = PhysicsControl.SteeringCurve;
|
||||
|
||||
// Wheels Setup
|
||||
const int PhysicsWheelsNum = PhysicsControl.Wheels.Num();
|
||||
if (PhysicsWheelsNum != 4)
|
||||
{
|
||||
UE_LOG(LogCarla, Error, TEXT("Number of WheelPhysicsControl is not 4."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Change, if required, the collision mode for wheels
|
||||
SetWheelCollision(Vehicle4W, PhysicsControl);
|
||||
|
||||
TArray<FWheelSetup> NewWheelSetups = Vehicle4W->WheelSetups;
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
UVehicleWheel *Wheel = NewWheelSetups[i].WheelClass.GetDefaultObject();
|
||||
check(Wheel != nullptr);
|
||||
|
||||
// Assigning new tire config
|
||||
Wheel->TireConfig = DuplicateObject<UTireConfig>(Wheel->TireConfig, nullptr);
|
||||
|
||||
// Setting a new value to friction
|
||||
Wheel->TireConfig->SetFrictionScale(PhysicsControl.Wheels[i].TireFriction);
|
||||
}
|
||||
|
||||
Vehicle4W->WheelSetups = NewWheelSetups;
|
||||
|
||||
// Recreate Physics State for vehicle setup
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->lockWrite();
|
||||
Vehicle4W->RecreatePhysicsState();
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->unlockWrite();
|
||||
|
||||
for (int32 i = 0; i < PhysicsWheelsNum; ++i)
|
||||
{
|
||||
PxVehicleWheelData PWheelData = Vehicle4W->PVehicle->mWheelsSimData.getWheelData(i);
|
||||
|
||||
PWheelData.mRadius = PhysicsControl.Wheels[i].Radius;
|
||||
PWheelData.mMaxSteer = FMath::DegreesToRadians(PhysicsControl.Wheels[i].MaxSteerAngle);
|
||||
PWheelData.mDampingRate = M2ToCm2(PhysicsControl.Wheels[i].DampingRate);
|
||||
PWheelData.mMaxBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxBrakeTorque);
|
||||
PWheelData.mMaxHandBrakeTorque = M2ToCm2(PhysicsControl.Wheels[i].MaxHandBrakeTorque);
|
||||
Vehicle4W->PVehicle->mWheelsSimData.setWheelData(i, PWheelData);
|
||||
|
||||
PxVehicleTireData PTireData = Vehicle4W->PVehicle->mWheelsSimData.getTireData(i);
|
||||
PTireData.mLatStiffX = PhysicsControl.Wheels[i].LatStiffMaxLoad;
|
||||
PTireData.mLatStiffY = PhysicsControl.Wheels[i].LatStiffValue;
|
||||
PTireData.mLongitudinalStiffnessPerUnitGravity = PhysicsControl.Wheels[i].LongStiffValue;
|
||||
Vehicle4W->PVehicle->mWheelsSimData.setTireData(i, PTireData);
|
||||
}
|
||||
|
||||
ResetConstraints();
|
||||
|
||||
auto * Recorder = UCarlaStatics::GetRecorder(GetWorld());
|
||||
if (Recorder && Recorder->IsEnabled())
|
||||
{
|
||||
|
@ -568,7 +778,6 @@ void ACarlaWheeledVehicle::SetWheelSteerDirection(EVehicleWheelLocation WheelLoc
|
|||
if (bPhysicsEnabled == false)
|
||||
{
|
||||
check((uint8)WheelLocation >= 0)
|
||||
check((uint8)WheelLocation < 4)
|
||||
UVehicleAnimInstance *VehicleAnim = Cast<UVehicleAnimInstance>(GetMesh()->GetAnimInstance());
|
||||
check(VehicleAnim != nullptr)
|
||||
VehicleAnim->SetWheelRotYaw((uint8)WheelLocation, AngleInDeg);
|
||||
|
@ -582,7 +791,6 @@ void ACarlaWheeledVehicle::SetWheelSteerDirection(EVehicleWheelLocation WheelLoc
|
|||
float ACarlaWheeledVehicle::GetWheelSteerAngle(EVehicleWheelLocation WheelLocation) {
|
||||
|
||||
check((uint8)WheelLocation >= 0)
|
||||
check((uint8)WheelLocation < 4)
|
||||
UVehicleAnimInstance *VehicleAnim = Cast<UVehicleAnimInstance>(GetMesh()->GetAnimInstance());
|
||||
check(VehicleAnim != nullptr)
|
||||
check(VehicleAnim->GetWheeledVehicleMovementComponent() != nullptr)
|
||||
|
@ -603,37 +811,39 @@ void ACarlaWheeledVehicle::SetSimulatePhysics(bool enabled) {
|
|||
return;
|
||||
}
|
||||
|
||||
UWheeledVehicleMovementComponent4W *Vehicle4W = Cast<UWheeledVehicleMovementComponent4W>(
|
||||
GetVehicleMovement());
|
||||
check(Vehicle4W != nullptr);
|
||||
|
||||
if(bPhysicsEnabled == enabled)
|
||||
return;
|
||||
|
||||
SetActorEnableCollision(true);
|
||||
auto RootComponent = Cast<UPrimitiveComponent>(GetRootComponent());
|
||||
RootComponent->SetSimulatePhysics(enabled);
|
||||
RootComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
|
||||
UVehicleAnimInstance *VehicleAnim = Cast<UVehicleAnimInstance>(GetMesh()->GetAnimInstance());
|
||||
check(VehicleAnim != nullptr)
|
||||
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->lockWrite();
|
||||
if (enabled)
|
||||
UWheeledVehicleMovementComponent* Movement = GetVehicleMovement();
|
||||
if (Movement)
|
||||
{
|
||||
Vehicle4W->RecreatePhysicsState();
|
||||
VehicleAnim->ResetWheelCustomRotations();
|
||||
check(Movement != nullptr);
|
||||
|
||||
if(bPhysicsEnabled == enabled)
|
||||
return;
|
||||
|
||||
SetActorEnableCollision(true);
|
||||
auto RootComponent = Cast<UPrimitiveComponent>(GetRootComponent());
|
||||
RootComponent->SetSimulatePhysics(enabled);
|
||||
RootComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
|
||||
UVehicleAnimInstance *VehicleAnim = Cast<UVehicleAnimInstance>(GetMesh()->GetAnimInstance());
|
||||
check(VehicleAnim != nullptr)
|
||||
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->lockWrite();
|
||||
if (enabled)
|
||||
{
|
||||
Movement->RecreatePhysicsState();
|
||||
VehicleAnim->ResetWheelCustomRotations();
|
||||
}
|
||||
else
|
||||
{
|
||||
Movement->DestroyPhysicsState();
|
||||
}
|
||||
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->unlockWrite();
|
||||
|
||||
bPhysicsEnabled = enabled;
|
||||
|
||||
ResetConstraints();
|
||||
}
|
||||
else
|
||||
{
|
||||
Vehicle4W->DestroyPhysicsState();
|
||||
}
|
||||
|
||||
GetWorld()->GetPhysicsScene()->GetPxScene()->unlockWrite();
|
||||
|
||||
bPhysicsEnabled = enabled;
|
||||
|
||||
ResetConstraints();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Vehicle/VehiclePhysicsControl.h"
|
||||
#include "VehicleVelocityControl.h"
|
||||
#include "WheeledVehicleMovementComponent4W.h"
|
||||
#include "WheeledVehicleMovementComponentNW.h"
|
||||
#include "VehicleAnimInstance.h"
|
||||
#include "PhysicsEngine/PhysicsConstraintComponent.h"
|
||||
#include "MovementComponents/BaseCarlaMovementComponent.h"
|
||||
|
@ -160,6 +161,8 @@ public:
|
|||
|
||||
void SetWheelCollision(UWheeledVehicleMovementComponent4W *Vehicle4W, const FVehiclePhysicsControl &PhysicsControl);
|
||||
|
||||
void SetWheelCollisionNW(UWheeledVehicleMovementComponentNW *VehicleNW, const FVehiclePhysicsControl &PhysicsControl);
|
||||
|
||||
void SetVehicleLightState(const FVehicleLightState &LightState);
|
||||
|
||||
UFUNCTION(BlueprintNativeEvent)
|
||||
|
@ -328,6 +331,9 @@ public:
|
|||
float CarSimOriginOffset = 150.f;
|
||||
//-------------------------------------------
|
||||
|
||||
UPROPERTY(Category="CARLA Wheeled Vehicle", EditAnywhere)
|
||||
bool bIsSixWVehicle = false;
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Category="CARLA Wheeled Vehicle", VisibleAnywhere)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) 2022 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
// Copyright (c) 2019 Intel Corporation
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "CarlaWheeledVehicleNW.h"
|
||||
#include "WheeledVehicleMovementComponentNW.h"
|
||||
|
||||
ACarlaWheeledVehicleNW::ACarlaWheeledVehicleNW(const FObjectInitializer& ObjectInitializer) :
|
||||
Super(ObjectInitializer.SetDefaultSubobjectClass<UWheeledVehicleMovementComponentNW>(AWheeledVehicle::VehicleMovementComponentName))
|
||||
{}
|
||||
|
||||
ACarlaWheeledVehicleNW::~ACarlaWheeledVehicleNW() {}
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2022 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CarlaWheeledVehicle.h"
|
||||
|
||||
#include "CarlaWheeledVehicleNW.generated.h"
|
||||
|
||||
/// Base class for CARLA wheeled vehicles.
|
||||
UCLASS()
|
||||
class CARLA_API ACarlaWheeledVehicleNW : public ACarlaWheeledVehicle
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// ===========================================================================
|
||||
/// @name Constructor and destructor
|
||||
// ===========================================================================
|
||||
/// @{
|
||||
public:
|
||||
|
||||
ACarlaWheeledVehicleNW(const FObjectInitializer &ObjectInitializer);
|
||||
|
||||
~ACarlaWheeledVehicleNW();
|
||||
};
|
|
@ -0,0 +1,404 @@
|
|||
#include "WheeledVehicleMovementComponentNW.h"
|
||||
#include "PhysicsPublic.h"
|
||||
#include "PhysXPublic.h"
|
||||
#include "PhysXVehicleManager.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Logging/MessageLog.h"
|
||||
|
||||
UWheeledVehicleMovementComponentNW::UWheeledVehicleMovementComponentNW(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
||||
{
|
||||
// grab default values from physx
|
||||
PxVehicleEngineData DefEngineData;
|
||||
EngineSetup.MOI = DefEngineData.mMOI;
|
||||
EngineSetup.MaxRPM = OmegaToRPM(DefEngineData.mMaxOmega);
|
||||
EngineSetup.DampingRateFullThrottle = DefEngineData.mDampingRateFullThrottle;
|
||||
EngineSetup.DampingRateZeroThrottleClutchEngaged = DefEngineData.mDampingRateZeroThrottleClutchEngaged;
|
||||
EngineSetup.DampingRateZeroThrottleClutchDisengaged = DefEngineData.mDampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
// Convert from PhysX curve to ours
|
||||
FRichCurve* TorqueCurveData = EngineSetup.TorqueCurve.GetRichCurve();
|
||||
for (PxU32 KeyIdx = 0; KeyIdx < DefEngineData.mTorqueCurve.getNbDataPairs(); ++KeyIdx)
|
||||
{
|
||||
float Input = DefEngineData.mTorqueCurve.getX(KeyIdx) * EngineSetup.MaxRPM;
|
||||
float Output = DefEngineData.mTorqueCurve.getY(KeyIdx) * DefEngineData.mPeakTorque;
|
||||
TorqueCurveData->AddKey(Input, Output);
|
||||
}
|
||||
|
||||
PxVehicleClutchData DefClutchData;
|
||||
TransmissionSetup.ClutchStrength = DefClutchData.mStrength;
|
||||
|
||||
PxVehicleGearsData DefGearSetup;
|
||||
TransmissionSetup.GearSwitchTime = DefGearSetup.mSwitchTime;
|
||||
TransmissionSetup.ReverseGearRatio = DefGearSetup.mRatios[PxVehicleGearsData::eREVERSE];
|
||||
TransmissionSetup.FinalRatio = DefGearSetup.mFinalRatio;
|
||||
|
||||
PxVehicleAutoBoxData DefAutoBoxSetup;
|
||||
TransmissionSetup.NeutralGearUpRatio = DefAutoBoxSetup.mUpRatios[PxVehicleGearsData::eNEUTRAL];
|
||||
TransmissionSetup.GearAutoBoxLatency = DefAutoBoxSetup.getLatency();
|
||||
TransmissionSetup.bUseGearAutoBox = true;
|
||||
|
||||
for (uint32 i = PxVehicleGearsData::eFIRST; i < DefGearSetup.mNbRatios; ++i)
|
||||
{
|
||||
FVehicleNWGearData GearData;
|
||||
GearData.DownRatio = DefAutoBoxSetup.mDownRatios[i];
|
||||
GearData.UpRatio = DefAutoBoxSetup.mUpRatios[i];
|
||||
GearData.Ratio = DefGearSetup.mRatios[i];
|
||||
TransmissionSetup.ForwardGears.Add(GearData);
|
||||
}
|
||||
|
||||
// Init steering speed curve
|
||||
FRichCurve* SteeringCurveData = SteeringCurve.GetRichCurve();
|
||||
SteeringCurveData->AddKey(0.0f, 1.0f);
|
||||
SteeringCurveData->AddKey(20.0f, 0.9f);
|
||||
SteeringCurveData->AddKey(60.0f, 0.8f);
|
||||
SteeringCurveData->AddKey(120.0f, 0.7f);
|
||||
|
||||
// Initialize WheelSetups array with 4 wheels, this can be modified via editor later
|
||||
const int32 NbrWheels = 4;
|
||||
WheelSetups.SetNum(NbrWheels);
|
||||
DifferentialSetup.SetNum(NbrWheels);
|
||||
|
||||
IdleBrakeInput = 10;
|
||||
}
|
||||
|
||||
#if WITH_EDITOR
|
||||
void UWheeledVehicleMovementComponentNW::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
const FName PropertyName = PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None;
|
||||
|
||||
if (PropertyName == TEXT("DownRatio"))
|
||||
{
|
||||
for (int32 GearIdx = 0; GearIdx < TransmissionSetup.ForwardGears.Num(); ++GearIdx)
|
||||
{
|
||||
FVehicleNWGearData& GearData = TransmissionSetup.ForwardGears[GearIdx];
|
||||
GearData.DownRatio = FMath::Min(GearData.DownRatio, GearData.UpRatio);
|
||||
}
|
||||
}
|
||||
else if (PropertyName == TEXT("UpRatio"))
|
||||
{
|
||||
for (int32 GearIdx = 0; GearIdx < TransmissionSetup.ForwardGears.Num(); ++GearIdx)
|
||||
{
|
||||
FVehicleNWGearData& GearData = TransmissionSetup.ForwardGears[GearIdx];
|
||||
GearData.UpRatio = FMath::Max(GearData.DownRatio, GearData.UpRatio);
|
||||
}
|
||||
}
|
||||
else if (PropertyName == TEXT("SteeringCurve"))
|
||||
{
|
||||
//make sure values are capped between 0 and 1
|
||||
TArray<FRichCurveKey> SteerKeys = SteeringCurve.GetRichCurve()->GetCopyOfKeys();
|
||||
for (int32 KeyIdx = 0; KeyIdx < SteerKeys.Num(); ++KeyIdx)
|
||||
{
|
||||
float NewValue = FMath::Clamp(SteerKeys[KeyIdx].Value, 0.0f, 1.0f);
|
||||
SteeringCurve.GetRichCurve()->UpdateOrAddKey(SteerKeys[KeyIdx].Time, NewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void GetVehicleDifferentialNWSetup(const TArray<FVehicleNWWheelDifferentialData>& Setup, PxVehicleDifferentialNWData& PxSetup)
|
||||
{
|
||||
for (int32 i = 0; i < Setup.Num(); ++i)
|
||||
{
|
||||
PxSetup.setDrivenWheel(i, Setup[i].bDriven);
|
||||
}
|
||||
}
|
||||
|
||||
float FVehicleNWEngineData::FindPeakTorque() const
|
||||
{
|
||||
// Find max torque
|
||||
float PeakTorque = 0.0f;
|
||||
TArray<FRichCurveKey> TorqueKeys = TorqueCurve.GetRichCurveConst()->GetCopyOfKeys();
|
||||
for (int32 KeyIdx = 0; KeyIdx < TorqueKeys.Num(); ++KeyIdx)
|
||||
{
|
||||
FRichCurveKey& Key = TorqueKeys[KeyIdx];
|
||||
PeakTorque = FMath::Max(PeakTorque, Key.Value);
|
||||
}
|
||||
return PeakTorque;
|
||||
}
|
||||
|
||||
static void GetVehicleEngineSetup(const FVehicleNWEngineData& Setup, PxVehicleEngineData& PxSetup)
|
||||
{
|
||||
PxSetup.mMOI = M2ToCm2(Setup.MOI);
|
||||
PxSetup.mMaxOmega = RPMToOmega(Setup.MaxRPM);
|
||||
PxSetup.mDampingRateFullThrottle = M2ToCm2(Setup.DampingRateFullThrottle);
|
||||
PxSetup.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(Setup.DampingRateZeroThrottleClutchEngaged);
|
||||
PxSetup.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(Setup.DampingRateZeroThrottleClutchDisengaged);
|
||||
|
||||
float PeakTorque = Setup.FindPeakTorque(); // In Nm
|
||||
PxSetup.mPeakTorque = M2ToCm2(PeakTorque); // convert Nm to (kg cm^2/s^2)
|
||||
|
||||
// Convert from our curve to PhysX
|
||||
PxSetup.mTorqueCurve.clear();
|
||||
TArray<FRichCurveKey> TorqueKeys = Setup.TorqueCurve.GetRichCurveConst()->GetCopyOfKeys();
|
||||
int32 NumTorqueCurveKeys = FMath::Min<int32>(TorqueKeys.Num(), PxVehicleEngineData::eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES);
|
||||
for (int32 KeyIdx = 0; KeyIdx < NumTorqueCurveKeys; ++KeyIdx)
|
||||
{
|
||||
FRichCurveKey& Key = TorqueKeys[KeyIdx];
|
||||
PxSetup.mTorqueCurve.addPair(FMath::Clamp(Key.Time / Setup.MaxRPM, 0.0f, 1.0f), Key.Value / PeakTorque); // Normalize torque to 0-1 range
|
||||
}
|
||||
}
|
||||
|
||||
static void GetVehicleGearSetup(const FVehicleNWTransmissionData& Setup, PxVehicleGearsData& PxSetup)
|
||||
{
|
||||
PxSetup.mSwitchTime = Setup.GearSwitchTime;
|
||||
PxSetup.mRatios[PxVehicleGearsData::eREVERSE] = Setup.ReverseGearRatio;
|
||||
for (int32 i = 0; i < Setup.ForwardGears.Num(); i++)
|
||||
{
|
||||
PxSetup.mRatios[i + PxVehicleGearsData::eFIRST] = Setup.ForwardGears[i].Ratio;
|
||||
}
|
||||
PxSetup.mFinalRatio = Setup.FinalRatio;
|
||||
PxSetup.mNbRatios = Setup.ForwardGears.Num() + PxVehicleGearsData::eFIRST;
|
||||
}
|
||||
|
||||
static void GetVehicleAutoBoxSetup(const FVehicleNWTransmissionData& Setup, PxVehicleAutoBoxData& PxSetup)
|
||||
{
|
||||
for (int32 i = 0; i < Setup.ForwardGears.Num(); ++i)
|
||||
{
|
||||
const FVehicleNWGearData& GearData = Setup.ForwardGears[i];
|
||||
PxSetup.mUpRatios[i + PxVehicleGearsData::eFIRST] = GearData.UpRatio;
|
||||
PxSetup.mDownRatios[i + PxVehicleGearsData::eFIRST] = GearData.DownRatio;
|
||||
}
|
||||
PxSetup.mUpRatios[PxVehicleGearsData::eNEUTRAL] = Setup.NeutralGearUpRatio;
|
||||
PxSetup.setLatency(Setup.GearAutoBoxLatency);
|
||||
|
||||
}
|
||||
|
||||
int32 UWheeledVehicleMovementComponentNW::GetCustomGearBoxNumForwardGears() const
|
||||
{
|
||||
return TransmissionSetup.ForwardGears.Num();
|
||||
}
|
||||
|
||||
void SetupDriveHelper(const UWheeledVehicleMovementComponentNW* VehicleData, const PxVehicleWheelsSimData* PWheelsSimData, PxVehicleDriveSimDataNW& DriveData)
|
||||
{
|
||||
PxVehicleDifferentialNWData DifferentialSetup;
|
||||
GetVehicleDifferentialNWSetup(VehicleData->DifferentialSetup, DifferentialSetup);
|
||||
|
||||
DriveData.setDiffData(DifferentialSetup);
|
||||
|
||||
PxVehicleEngineData EngineSetup;
|
||||
GetVehicleEngineSetup(VehicleData->EngineSetup, EngineSetup);
|
||||
DriveData.setEngineData(EngineSetup);
|
||||
|
||||
PxVehicleClutchData ClutchSetup;
|
||||
ClutchSetup.mStrength = M2ToCm2(VehicleData->TransmissionSetup.ClutchStrength);
|
||||
DriveData.setClutchData(ClutchSetup);
|
||||
|
||||
PxVehicleGearsData GearSetup;
|
||||
GetVehicleGearSetup(VehicleData->TransmissionSetup, GearSetup);
|
||||
DriveData.setGearsData(GearSetup);
|
||||
|
||||
PxVehicleAutoBoxData AutoBoxSetup;
|
||||
GetVehicleAutoBoxSetup(VehicleData->TransmissionSetup, AutoBoxSetup);
|
||||
DriveData.setAutoBoxData(AutoBoxSetup);
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::SetupVehicle()
|
||||
{
|
||||
if (!UpdatedPrimitive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (WheelSetups.Num() < 2)
|
||||
{
|
||||
PVehicle = nullptr;
|
||||
PVehicleDrive = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 WheelIdx = 0; WheelIdx < WheelSetups.Num(); ++WheelIdx)
|
||||
{
|
||||
const FWheelSetup& WheelSetup = WheelSetups[WheelIdx];
|
||||
if (WheelSetup.BoneName == NAME_None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the chassis and wheel shapes
|
||||
SetupVehicleShapes();
|
||||
|
||||
// Setup mass properties
|
||||
SetupVehicleMass();
|
||||
|
||||
// Setup the wheels
|
||||
PxVehicleWheelsSimData* PWheelsSimData = PxVehicleWheelsSimData::allocate(WheelSetups.Num());
|
||||
SetupWheels(PWheelsSimData);
|
||||
|
||||
// Setup drive data
|
||||
PxVehicleDriveSimDataNW DriveData;
|
||||
SetupDriveHelper(this, PWheelsSimData, DriveData);
|
||||
|
||||
// Create the vehicle
|
||||
PxVehicleDriveNW* PVehicleDriveNW = PxVehicleDriveNW::allocate(WheelSetups.Num());
|
||||
check(PVehicleDriveNW);
|
||||
|
||||
FBodyInstance* TargetInstance = UpdatedPrimitive->GetBodyInstance();
|
||||
|
||||
FPhysicsCommand::ExecuteWrite(TargetInstance->ActorHandle, [&](const FPhysicsActorHandle& Actor)
|
||||
{
|
||||
PxRigidActor* PActor = FPhysicsInterface::GetPxRigidActor_AssumesLocked(Actor);
|
||||
if (!PActor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PxRigidDynamic* PVehicleActor = PActor->is<PxRigidDynamic>())
|
||||
{
|
||||
PVehicleDriveNW->setup(GPhysXSDK, PVehicleActor, *PWheelsSimData, DriveData, 0);
|
||||
PVehicleDriveNW->setToRestState();
|
||||
|
||||
// cleanup
|
||||
PWheelsSimData->free();
|
||||
}
|
||||
});
|
||||
|
||||
PWheelsSimData = nullptr;
|
||||
|
||||
// cache values
|
||||
PVehicle = PVehicleDriveNW;
|
||||
PVehicleDrive = PVehicleDriveNW;
|
||||
|
||||
SetUseAutoGears(TransmissionSetup.bUseGearAutoBox);
|
||||
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::UpdateSimulation(float DeltaTime)
|
||||
{
|
||||
if (PVehicleDrive == nullptr)
|
||||
return;
|
||||
|
||||
FBodyInstance* TargetInstance = UpdatedPrimitive->GetBodyInstance();
|
||||
|
||||
FPhysicsCommand::ExecuteWrite(TargetInstance->ActorHandle, [&](const FPhysicsActorHandle& Actor)
|
||||
{
|
||||
PxVehicleDriveNWRawInputData RawInputData;
|
||||
RawInputData.setAnalogAccel(ThrottleInput);
|
||||
RawInputData.setAnalogSteer(SteeringInput);
|
||||
RawInputData.setAnalogBrake(BrakeInput);
|
||||
RawInputData.setAnalogHandbrake(HandbrakeInput);
|
||||
|
||||
if (!PVehicleDrive->mDriveDynData.getUseAutoGears())
|
||||
{
|
||||
RawInputData.setGearUp(bRawGearUpInput);
|
||||
RawInputData.setGearDown(bRawGearDownInput);
|
||||
}
|
||||
|
||||
// Convert from our curve to PxFixedSizeLookupTable
|
||||
PxFixedSizeLookupTable<8> SpeedSteerLookup;
|
||||
TArray<FRichCurveKey> SteerKeys = SteeringCurve.GetRichCurve()->GetCopyOfKeys();
|
||||
const int32 MaxSteeringSamples = FMath::Min(8, SteerKeys.Num());
|
||||
for (int32 KeyIdx = 0; KeyIdx < MaxSteeringSamples; KeyIdx++)
|
||||
{
|
||||
FRichCurveKey& Key = SteerKeys[KeyIdx];
|
||||
SpeedSteerLookup.addPair(KmHToCmS(Key.Time), FMath::Clamp(Key.Value, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
PxVehiclePadSmoothingData SmoothData = {
|
||||
{ ThrottleInputRate.RiseRate, BrakeInputRate.RiseRate, HandbrakeInputRate.RiseRate, SteeringInputRate.RiseRate, SteeringInputRate.RiseRate },
|
||||
{ ThrottleInputRate.FallRate, BrakeInputRate.FallRate, HandbrakeInputRate.FallRate, SteeringInputRate.FallRate, SteeringInputRate.FallRate }
|
||||
};
|
||||
|
||||
PxVehicleDriveNW* PVehicleDriveNW = (PxVehicleDriveNW*)PVehicleDrive;
|
||||
PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs(SmoothData, SpeedSteerLookup, RawInputData, DeltaTime, false, *PVehicleDriveNW);
|
||||
});
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::UpdateEngineSetup(const FVehicleNWEngineData& NewEngineSetup)
|
||||
{
|
||||
if (PVehicleDrive)
|
||||
{
|
||||
PxVehicleEngineData EngineData;
|
||||
GetVehicleEngineSetup(NewEngineSetup, EngineData);
|
||||
|
||||
PxVehicleDriveNW* PVehicleDriveNW = (PxVehicleDriveNW*)PVehicleDrive;
|
||||
PVehicleDriveNW->mDriveSimData.setEngineData(EngineData);
|
||||
}
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::UpdateDifferentialSetup(const TArray<FVehicleNWWheelDifferentialData>& NewDifferentialSetup)
|
||||
{
|
||||
if (PVehicleDrive)
|
||||
{
|
||||
PxVehicleDifferentialNWData DifferentialData;
|
||||
GetVehicleDifferentialNWSetup(NewDifferentialSetup, DifferentialData);
|
||||
|
||||
PxVehicleDriveNW* PVehicleDriveNW = (PxVehicleDriveNW*)PVehicleDrive;
|
||||
PVehicleDriveNW->mDriveSimData.setDiffData(DifferentialData);
|
||||
}
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::UpdateTransmissionSetup(const FVehicleNWTransmissionData& NewTransmissionSetup)
|
||||
{
|
||||
if (PVehicleDrive)
|
||||
{
|
||||
PxVehicleGearsData GearData;
|
||||
GetVehicleGearSetup(NewTransmissionSetup, GearData);
|
||||
|
||||
PxVehicleAutoBoxData AutoBoxData;
|
||||
GetVehicleAutoBoxSetup(NewTransmissionSetup, AutoBoxData);
|
||||
|
||||
PxVehicleDriveNW* PVehicleDriveNW = (PxVehicleDriveNW*)PVehicleDrive;
|
||||
PVehicleDriveNW->mDriveSimData.setGearsData(GearData);
|
||||
PVehicleDriveNW->mDriveSimData.setAutoBoxData(AutoBoxData);
|
||||
}
|
||||
}
|
||||
|
||||
void BackwardsConvertCm2ToM2NW(float& val, float defaultValue)
|
||||
{
|
||||
if (val != defaultValue)
|
||||
{
|
||||
val = Cm2ToM2(val);
|
||||
}
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::Serialize(FArchive& Ar)
|
||||
{
|
||||
Super::Serialize(Ar);
|
||||
if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_VEHICLES_UNIT_CHANGE)
|
||||
{
|
||||
PxVehicleEngineData DefEngineData;
|
||||
const float DefaultRPM = OmegaToRPM(DefEngineData.mMaxOmega);
|
||||
|
||||
// We need to convert from old units to new. This backwards compatible code fails in the rare case that they were using very strange values that are the new defaults in the correct units.
|
||||
EngineSetup.MaxRPM = EngineSetup.MaxRPM != DefaultRPM ? OmegaToRPM(EngineSetup.MaxRPM) : DefaultRPM; //need to convert from rad/s to RPM
|
||||
}
|
||||
|
||||
if (Ar.IsLoading() && Ar.UE4Ver() < VER_UE4_VEHICLES_UNIT_CHANGE2)
|
||||
{
|
||||
PxVehicleEngineData DefEngineData;
|
||||
PxVehicleClutchData DefClutchData;
|
||||
|
||||
// We need to convert from old units to new. This backwards compatable code fails in the rare case that they were using very strange values that are the new defaults in the correct units.
|
||||
BackwardsConvertCm2ToM2NW(EngineSetup.DampingRateFullThrottle, DefEngineData.mDampingRateFullThrottle);
|
||||
BackwardsConvertCm2ToM2NW(EngineSetup.DampingRateZeroThrottleClutchDisengaged, DefEngineData.mDampingRateZeroThrottleClutchDisengaged);
|
||||
BackwardsConvertCm2ToM2NW(EngineSetup.DampingRateZeroThrottleClutchEngaged, DefEngineData.mDampingRateZeroThrottleClutchEngaged);
|
||||
BackwardsConvertCm2ToM2NW(EngineSetup.MOI, DefEngineData.mMOI);
|
||||
BackwardsConvertCm2ToM2NW(TransmissionSetup.ClutchStrength, DefClutchData.mStrength);
|
||||
}
|
||||
}
|
||||
|
||||
void UWheeledVehicleMovementComponentNW::ComputeConstants()
|
||||
{
|
||||
Super::ComputeConstants();
|
||||
MaxEngineRPM = EngineSetup.MaxRPM;
|
||||
}
|
||||
|
||||
const void* UWheeledVehicleMovementComponentNW::GetTireData(physx::PxVehicleWheels* InWheels, UVehicleWheel* InWheel)
|
||||
{
|
||||
const void* realShaderData = &InWheels->mWheelsSimData.getTireData((PxU32)InWheel->WheelIndex);
|
||||
return realShaderData;
|
||||
}
|
||||
|
||||
const int32 UWheeledVehicleMovementComponentNW::GetWheelShapeMapping(physx::PxVehicleWheels* InWheels, uint32 InWheel)
|
||||
{
|
||||
const physx::PxI32 ShapeIndex = InWheels->mWheelsSimData.getWheelShapeMapping((PxU32)InWheel);
|
||||
return ShapeIndex;
|
||||
}
|
||||
|
||||
const physx::PxVehicleWheelData UWheeledVehicleMovementComponentNW::GetWheelData(physx::PxVehicleWheels* InWheels, uint32 InWheel)
|
||||
{
|
||||
const physx::PxVehicleWheelData WheelData = InWheels->mWheelsSimData.getWheelData((physx::PxU32)InWheel);
|
||||
return WheelData;
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
#pragma once
|
||||
#include "WheeledVehicleMovementComponent.h"
|
||||
#include "Curves/CurveFloat.h"
|
||||
#include "WheeledVehicleMovementComponentNW.generated.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxVehicleWheelData;
|
||||
}
|
||||
|
||||
USTRUCT()
|
||||
struct FVehicleNWWheelDifferentialData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/** If True, torque is applied to this wheel */
|
||||
UPROPERTY(EditAnywhere, Category = Setup)
|
||||
bool bDriven;
|
||||
|
||||
FVehicleNWWheelDifferentialData()
|
||||
: bDriven(true)
|
||||
{ }
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FVehicleNWEngineData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/** Torque (Nm) at a given RPM*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup)
|
||||
FRuntimeFloatCurve TorqueCurve;
|
||||
|
||||
/** Maximum revolutions per minute of the engine */
|
||||
UPROPERTY(EditAnywhere, Category = Setup, meta = (ClampMin = "0.01", UIMin = "0.01"))
|
||||
float MaxRPM;
|
||||
|
||||
/** Moment of inertia of the engine around the axis of rotation (Kgm^2). */
|
||||
UPROPERTY(EditAnywhere, Category = Setup, meta = (ClampMin = "0.01", UIMin = "0.01"))
|
||||
float MOI;
|
||||
|
||||
/** Damping rate of engine when full throttle is applied (Kgm^2/s) */
|
||||
UPROPERTY(EditAnywhere, Category = Setup, AdvancedDisplay, meta = (ClampMin = "0.0", UIMin = "0.0"))
|
||||
float DampingRateFullThrottle;
|
||||
|
||||
/** Damping rate of engine in at zero throttle when the clutch is engaged (Kgm^2/s)*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup, AdvancedDisplay, meta = (ClampMin = "0.0", UIMin = "0.0"))
|
||||
float DampingRateZeroThrottleClutchEngaged;
|
||||
|
||||
/** Damping rate of engine in at zero throttle when the clutch is disengaged (in neutral gear) (Kgm^2/s)*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup, AdvancedDisplay, meta = (ClampMin = "0.0", UIMin = "0.0"))
|
||||
float DampingRateZeroThrottleClutchDisengaged;
|
||||
|
||||
/** Find the peak torque produced by the TorqueCurve */
|
||||
float FindPeakTorque() const;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FVehicleNWGearData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
/** Determines the amount of torque multiplication*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup)
|
||||
float Ratio;
|
||||
|
||||
/** Value of engineRevs/maxEngineRevs that is low enough to gear down*/
|
||||
UPROPERTY(EditAnywhere, meta = (ClampMin = "0.0", UIMin = "0.0", ClampMax = "1.0", UIMax = "1.0"), Category = Setup)
|
||||
float DownRatio;
|
||||
|
||||
/** Value of engineRevs/maxEngineRevs that is high enough to gear up*/
|
||||
UPROPERTY(EditAnywhere, meta = (ClampMin = "0.0", UIMin = "0.0", ClampMax = "1.0", UIMax = "1.0"), Category = Setup)
|
||||
float UpRatio;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FVehicleNWTransmissionData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
/** Whether to use automatic transmission */
|
||||
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (DisplayName = "Automatic Transmission"))
|
||||
bool bUseGearAutoBox;
|
||||
|
||||
/** Time it takes to switch gears (seconds) */
|
||||
UPROPERTY(EditAnywhere, Category = Setup, meta = (ClampMin = "0.0", UIMin = "0.0"))
|
||||
float GearSwitchTime;
|
||||
|
||||
/** Minimum time it takes the automatic transmission to initiate a gear change (seconds)*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup, meta = (editcondition = "bUseGearAutoBox", ClampMin = "0.0", UIMin = "0.0"))
|
||||
float GearAutoBoxLatency;
|
||||
|
||||
/** The final gear ratio multiplies the transmission gear ratios.*/
|
||||
UPROPERTY(EditAnywhere, AdvancedDisplay, Category = Setup)
|
||||
float FinalRatio;
|
||||
|
||||
/** Forward gear ratios (up to 30) */
|
||||
UPROPERTY(EditAnywhere, Category = Setup, AdvancedDisplay)
|
||||
TArray<FVehicleNWGearData> ForwardGears;
|
||||
|
||||
/** Reverse gear ratio */
|
||||
UPROPERTY(EditAnywhere, AdvancedDisplay, Category = Setup)
|
||||
float ReverseGearRatio;
|
||||
|
||||
/** Value of engineRevs/maxEngineRevs that is high enough to increment gear*/
|
||||
UPROPERTY(EditAnywhere, AdvancedDisplay, Category = Setup, meta = (ClampMin = "0.0", UIMin = "0.0", ClampMax = "1.0", UIMax = "1.0"))
|
||||
float NeutralGearUpRatio;
|
||||
|
||||
/** Strength of clutch (Kgm^2/s)*/
|
||||
UPROPERTY(EditAnywhere, Category = Setup, AdvancedDisplay, meta = (ClampMin = "0.0", UIMin = "0.0"))
|
||||
float ClutchStrength;
|
||||
};
|
||||
|
||||
UCLASS(ClassGroup = (Physics), meta = (BlueprintSpawnableComponent), hidecategories = (PlanarMovement, "Components|Movement|Planar", Activation, "Components|Activation"))
|
||||
class PHYSXVEHICLES_API UWheeledVehicleMovementComponentNW : public UWheeledVehicleMovementComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
/** Engine */
|
||||
UPROPERTY(EditAnywhere, Category = MechanicalSetup)
|
||||
FVehicleNWEngineData EngineSetup;
|
||||
|
||||
/** Differential */
|
||||
UPROPERTY(EditAnywhere, Category = MechanicalSetup)
|
||||
TArray<FVehicleNWWheelDifferentialData> DifferentialSetup;
|
||||
|
||||
/** Transmission data */
|
||||
UPROPERTY(EditAnywhere, Category = MechanicalSetup)
|
||||
FVehicleNWTransmissionData TransmissionSetup;
|
||||
|
||||
/** Maximum steering versus forward speed (km/h) */
|
||||
UPROPERTY(EditAnywhere, Category = SteeringSetup)
|
||||
FRuntimeFloatCurve SteeringCurve;
|
||||
|
||||
virtual void Serialize(FArchive& Ar) override;
|
||||
virtual void ComputeConstants() override;
|
||||
#if WITH_EDITOR
|
||||
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
virtual const void* GetTireData(physx::PxVehicleWheels* Wheels, UVehicleWheel* Wheel);
|
||||
virtual const int32 GetWheelShapeMapping(physx::PxVehicleWheels* Wheels, uint32 Wheel);
|
||||
virtual const physx::PxVehicleWheelData GetWheelData(physx::PxVehicleWheels* Wheels, uint32 Wheel);
|
||||
|
||||
/** Allocate and setup the PhysX vehicle */
|
||||
virtual void SetupVehicle() override;
|
||||
|
||||
virtual int32 GetCustomGearBoxNumForwardGears() const;
|
||||
|
||||
virtual void UpdateSimulation(float DeltaTime) override;
|
||||
|
||||
/** update simulation data: engine */
|
||||
virtual void UpdateEngineSetup(const FVehicleNWEngineData& NewEngineSetup);
|
||||
|
||||
/** update simulation data: differential */
|
||||
virtual void UpdateDifferentialSetup(const TArray<FVehicleNWWheelDifferentialData>& NewDifferentialSetup);
|
||||
|
||||
/** update simulation data: transmission */
|
||||
virtual void UpdateTransmissionSetup(const FVehicleNWTransmissionData& NewGearSetup);
|
||||
};
|
Loading…
Reference in New Issue