1308 lines
40 KiB
C++
1308 lines
40 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "Templates/SubclassOf.h"
|
|
#include "AI/Navigation/NavigationAvoidanceTypes.h"
|
|
#include "AI/RVOAvoidanceInterface.h"
|
|
#include "Curves/CurveFloat.h"
|
|
#include "GameFramework/PawnMovementComponent.h"
|
|
#include "ChaosVehicleWheel.h"
|
|
#include "AerofoilSystem.h"
|
|
#include "ThrustSystem.h"
|
|
#include "TransmissionSystem.h"
|
|
#include "PhysicsProxy/SingleParticlePhysicsProxyFwd.h"
|
|
#include "SnapshotData.h"
|
|
#include "DeferredForces.h"
|
|
#include "ChaosVehicleManagerAsyncCallback.h"
|
|
#include "CollisionQueryParams.h"
|
|
#include "RewindData.h"
|
|
|
|
#include "ChaosVehicleMovementComponent.generated.h"
|
|
|
|
class CHAOSVEHICLES_API UChaosVehicleMovementComponent;
|
|
|
|
DECLARE_LOG_CATEGORY_EXTERN(LogVehicle, Log, All);
|
|
|
|
class UCanvas;
|
|
|
|
struct FChaosVehicleAsyncInput;
|
|
struct FChaosVehicleManagerAsyncOutput;
|
|
|
|
struct CHAOSVEHICLES_API FVehicleDebugParams
|
|
{
|
|
bool ShowCOM = false;
|
|
bool ShowModelOrigin = false;
|
|
bool ShowAllForces = false;
|
|
bool ShowAerofoilForces = false;
|
|
bool ShowAerofoilSurface = false;
|
|
bool DisableTorqueControl = false;
|
|
bool DisableStabilizeControl = false;
|
|
bool DisableAerodynamics = false;
|
|
bool DisableAerofoils = false;
|
|
bool DisableThrusters = false;
|
|
bool BatchQueries = false;
|
|
bool CacheTraceOverlap = false;
|
|
float ForceDebugScaling = 0.0006f;
|
|
float SleepCounterThreshold = 15;
|
|
bool DisableVehicleSleep = false;
|
|
bool EnableMultithreading = true;
|
|
float SetMaxMPH = 0.0f;
|
|
float ControlInputWakeTolerance = 0.02f;
|
|
};
|
|
|
|
struct FBodyInstance;
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleReplicatedState : public FVehicleInputs
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleReplicatedState() : FVehicleInputs()
|
|
{
|
|
TargetGear = 0;
|
|
ThrottleUp = 0.f;
|
|
ThrottleDown = 0.f;
|
|
}
|
|
|
|
// state replication: gear
|
|
UPROPERTY()
|
|
int32 TargetGear;
|
|
|
|
// input replication: increase throttle
|
|
UPROPERTY()
|
|
float ThrottleUp;
|
|
|
|
// input replication: decrease throttle
|
|
UPROPERTY()
|
|
float ThrottleDown;
|
|
};
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleTorqueControlConfig
|
|
{
|
|
public:
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleTorqueControlConfig()
|
|
{
|
|
InitDefaults();
|
|
}
|
|
|
|
/** Torque Control Enabled */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
bool Enabled;
|
|
|
|
/** Yaw Torque Scaling */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float YawTorqueScaling;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float YawFromSteering;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float YawFromRollTorqueScaling;
|
|
|
|
/** Pitch Torque Scaling */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float PitchTorqueScaling;
|
|
|
|
/** Roll Torque Scaling */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RollTorqueScaling;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RollFromSteering;
|
|
|
|
/** Rotation damping */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RotationDamping;
|
|
|
|
const Chaos::FTorqueControlConfig& GetTorqueControlConfig()
|
|
{
|
|
FillTorqueControlSetup();
|
|
return PTorqueControlConfig;
|
|
}
|
|
|
|
void InitDefaults()
|
|
{
|
|
Enabled = false;
|
|
YawTorqueScaling = 0.0f;
|
|
YawFromSteering = 0.0f;
|
|
YawFromRollTorqueScaling = 0.0f;
|
|
PitchTorqueScaling = 0.0f;
|
|
RollTorqueScaling = 0.0f;
|
|
RollFromSteering = 0.0f;
|
|
RotationDamping = 0.02f;
|
|
}
|
|
|
|
private:
|
|
void FillTorqueControlSetup()
|
|
{
|
|
PTorqueControlConfig.Enabled = Enabled;
|
|
PTorqueControlConfig.YawTorqueScaling = YawTorqueScaling;
|
|
PTorqueControlConfig.YawFromSteering = YawFromSteering;
|
|
PTorqueControlConfig.YawFromRollTorqueScaling = YawFromRollTorqueScaling;
|
|
PTorqueControlConfig.PitchTorqueScaling = PitchTorqueScaling;
|
|
PTorqueControlConfig.RollTorqueScaling = RollTorqueScaling;
|
|
PTorqueControlConfig.RollFromSteering = RollFromSteering;
|
|
PTorqueControlConfig.RotationDamping = RotationDamping;
|
|
|
|
}
|
|
|
|
Chaos::FTorqueControlConfig PTorqueControlConfig;
|
|
};
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleTargetRotationControlConfig
|
|
{
|
|
public:
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleTargetRotationControlConfig()
|
|
{
|
|
InitDefaults();
|
|
}
|
|
|
|
/** Rotation Control Enabled */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
bool Enabled;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
bool bRollVsSpeedEnabled;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RollControlScaling;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RollMaxAngle;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float PitchControlScaling;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float PitchMaxAngle;
|
|
|
|
/** Rotation stiffness */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RotationStiffness;
|
|
|
|
/** Rotation damping */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float RotationDamping;
|
|
|
|
/** Rotation mac accel */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float MaxAccel;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float AutoCentreRollStrength;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float AutoCentrePitchStrength;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float AutoCentreYawStrength;
|
|
|
|
const Chaos::FTargetRotationControlConfig& GetTargetRotationControlConfig()
|
|
{
|
|
FillTargetRotationControlSetup();
|
|
return PTargetRotationControlConfig;
|
|
}
|
|
|
|
void InitDefaults()
|
|
{
|
|
Enabled = false;
|
|
|
|
bRollVsSpeedEnabled = false;
|
|
|
|
RollControlScaling = 0.f;
|
|
RollMaxAngle = 0.f;
|
|
PitchControlScaling = 0.f;
|
|
PitchMaxAngle = 0.f;
|
|
|
|
RotationStiffness = 0.f;
|
|
RotationDamping = 0.2;
|
|
MaxAccel = 0.f;
|
|
|
|
AutoCentreRollStrength = 0.f;
|
|
AutoCentrePitchStrength = 0.f;
|
|
AutoCentreYawStrength = 0.f;
|
|
}
|
|
|
|
private:
|
|
void FillTargetRotationControlSetup()
|
|
{
|
|
PTargetRotationControlConfig.Enabled = Enabled;
|
|
PTargetRotationControlConfig.bRollVsSpeedEnabled = bRollVsSpeedEnabled;
|
|
PTargetRotationControlConfig.RollControlScaling = RollControlScaling;
|
|
PTargetRotationControlConfig.RollMaxAngle = RollMaxAngle;
|
|
PTargetRotationControlConfig.PitchControlScaling = PitchControlScaling;
|
|
PTargetRotationControlConfig.PitchMaxAngle = PitchMaxAngle;
|
|
PTargetRotationControlConfig.RotationStiffness = RotationStiffness;
|
|
PTargetRotationControlConfig.RotationDamping = RotationDamping;
|
|
PTargetRotationControlConfig.MaxAccel = MaxAccel;
|
|
PTargetRotationControlConfig.AutoCentreRollStrength = AutoCentreRollStrength;
|
|
PTargetRotationControlConfig.AutoCentrePitchStrength = AutoCentrePitchStrength;
|
|
PTargetRotationControlConfig.AutoCentreYawStrength = AutoCentreYawStrength;
|
|
}
|
|
|
|
Chaos::FTargetRotationControlConfig PTargetRotationControlConfig;
|
|
};
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleStabilizeControlConfig
|
|
{
|
|
public:
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleStabilizeControlConfig()
|
|
{
|
|
InitDefaults();
|
|
}
|
|
|
|
/** Torque Control Enabled */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
bool Enabled;
|
|
|
|
/** Yaw Torque Scaling */
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float AltitudeHoldZ;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Setup)
|
|
float PositionHoldXY;
|
|
|
|
const Chaos::FStabilizeControlConfig& GetStabilizeControlConfig()
|
|
{
|
|
FillStabilizeControlSetup();
|
|
return PStabilizeControlConfig;
|
|
}
|
|
|
|
void InitDefaults()
|
|
{
|
|
Enabled = false;
|
|
AltitudeHoldZ = 4.0f;
|
|
PositionHoldXY = 8.0f;
|
|
}
|
|
|
|
private:
|
|
void FillStabilizeControlSetup()
|
|
{
|
|
PStabilizeControlConfig.Enabled = this->Enabled;
|
|
PStabilizeControlConfig.AltitudeHoldZ = this->AltitudeHoldZ;
|
|
PStabilizeControlConfig.PositionHoldXY = this->PositionHoldXY;
|
|
}
|
|
|
|
Chaos::FStabilizeControlConfig PStabilizeControlConfig;
|
|
|
|
};
|
|
|
|
/** Commonly used state - evaluated once used wherever required */
|
|
struct CHAOSVEHICLES_API FVehicleState
|
|
{
|
|
FVehicleState()
|
|
: VehicleWorldTransform(FTransform::Identity)
|
|
, VehicleWorldVelocity(FVector::ZeroVector)
|
|
, VehicleLocalVelocity(FVector::ZeroVector)
|
|
, VehicleWorldAngularVelocity(FVector::ZeroVector)
|
|
, VehicleWorldCOM(FVector::ZeroVector)
|
|
, WorldVelocityNormal(FVector::ZeroVector)
|
|
, VehicleUpAxis(FVector(0.f, 0.f, 1.f))
|
|
, VehicleForwardAxis(FVector(1.f, 0.f, 0.f))
|
|
, VehicleRightAxis(FVector(0.f, 1.f, 0.f))
|
|
, LocalAcceleration(FVector::ZeroVector)
|
|
, LocalGForce(FVector::ZeroVector)
|
|
, LastFrameVehicleLocalVelocity(FVector::ZeroVector)
|
|
, ForwardSpeed(0.f)
|
|
, ForwardsAcceleration(0.f)
|
|
, NumWheelsOnGround(0)
|
|
, bAllWheelsOnGround(false)
|
|
, bVehicleInAir(true)
|
|
, bSleeping(false)
|
|
, SleepCounter(0)
|
|
{
|
|
|
|
}
|
|
|
|
/** Cache some useful data at the start of the frame from GT BodyInstance */
|
|
void CaptureState(const FBodyInstance* TargetInstance, float GravityZ, float DeltaTime);
|
|
|
|
/** Cache some useful data at the start of the frame from Physics thread Particle Handle */
|
|
void CaptureState(const Chaos::FRigidBodyHandle_Internal* Handle, float GravityZ, float DeltaTime);
|
|
|
|
FTransform VehicleWorldTransform;
|
|
FVector VehicleWorldVelocity;
|
|
FVector VehicleLocalVelocity;
|
|
FVector VehicleWorldAngularVelocity;
|
|
FVector VehicleWorldCOM;
|
|
FVector WorldVelocityNormal;
|
|
|
|
FVector VehicleUpAxis;
|
|
FVector VehicleForwardAxis;
|
|
FVector VehicleRightAxis;
|
|
FVector LocalAcceleration;
|
|
FVector LocalGForce;
|
|
FVector LastFrameVehicleLocalVelocity;
|
|
|
|
float ForwardSpeed;
|
|
float ForwardsAcceleration;
|
|
|
|
int NumWheelsOnGround;
|
|
bool bAllWheelsOnGround;
|
|
bool bVehicleInAir;
|
|
bool bSleeping;
|
|
int SleepCounter;
|
|
};
|
|
|
|
/** Input Options */
|
|
UENUM()
|
|
enum class EInputFunctionType : uint8
|
|
{
|
|
LinearFunction = 0,
|
|
SquaredFunction,
|
|
CustomCurve
|
|
};
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleInputRateConfig
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
/**
|
|
* Rate at which the input value rises
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category=VehicleInputRate)
|
|
float RiseRate;
|
|
|
|
/**
|
|
* Rate at which the input value falls
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category=VehicleInputRate)
|
|
float FallRate;
|
|
|
|
/**
|
|
* Controller input curve, various predefined options, linear, squared, or user can specify a custom curve function
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category=VehicleInputRate)
|
|
EInputFunctionType InputCurveFunction;
|
|
|
|
/**
|
|
* Controller input curve - should be a normalized float curve, i.e. time from 0 to 1 and values between 0 and 1
|
|
* This curve is only sued if the InputCurveFunction above is set to CustomCurve
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleInputRate)
|
|
FRuntimeFloatCurve UserCurve;
|
|
|
|
FVehicleInputRateConfig() : RiseRate(5.0f), FallRate(5.0f), InputCurveFunction(EInputFunctionType::LinearFunction) { }
|
|
|
|
/** Change an output value using max rise and fall rates */
|
|
float InterpInputValue(float DeltaTime, float CurrentValue, float NewValue) const
|
|
{
|
|
const float DeltaValue = NewValue - CurrentValue;
|
|
|
|
// We are "rising" when DeltaValue has the same sign as CurrentValue (i.e. delta causes an absolute magnitude gain)
|
|
// OR we were at 0 before, and our delta is no longer 0.
|
|
const bool bRising = ((DeltaValue > 0.0f) == (CurrentValue > 0.0f)) ||
|
|
((DeltaValue != 0.f) && (CurrentValue == 0.f));
|
|
|
|
const float MaxDeltaValue = DeltaTime * (bRising ? RiseRate : FallRate);
|
|
const float ClampedDeltaValue = FMath::Clamp(DeltaValue, -MaxDeltaValue, MaxDeltaValue);
|
|
return CurrentValue + ClampedDeltaValue;
|
|
}
|
|
|
|
float CalcControlFunction(float InputValue)
|
|
{
|
|
// user defined curve
|
|
|
|
// else use option from drop down list
|
|
switch (InputCurveFunction)
|
|
{
|
|
case EInputFunctionType::CustomCurve:
|
|
{
|
|
if (UserCurve.GetRichCurveConst() && !UserCurve.GetRichCurveConst()->IsEmpty())
|
|
{
|
|
float Output = FMath::Clamp(UserCurve.GetRichCurveConst()->Eval(FMath::Abs(InputValue)), 0.0f, 1.0f);
|
|
return (InputValue < 0.f) ? -Output : Output;
|
|
}
|
|
else
|
|
{
|
|
return InputValue;
|
|
}
|
|
}
|
|
break;
|
|
case EInputFunctionType::SquaredFunction:
|
|
{
|
|
return (InputValue < 0.f) ? -InputValue * InputValue : InputValue * InputValue;
|
|
}
|
|
break;
|
|
|
|
case EInputFunctionType::LinearFunction:
|
|
default:
|
|
{
|
|
return InputValue;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
|
|
UENUM()
|
|
enum class EVehicleAerofoilType : uint8
|
|
{
|
|
Fixed = 0,
|
|
Wing, // affected by Roll input
|
|
Rudder, // affected by steering/yaw input
|
|
Elevator // affected by Pitch input
|
|
};
|
|
|
|
|
|
UENUM()
|
|
enum class EVehicleThrustType : uint8
|
|
{
|
|
Fixed = 0,
|
|
Wing, // affected by Roll input
|
|
Rudder, // affected by steering/yaw input
|
|
Elevator, // affected by Pitch input
|
|
// HelicopterRotor, // affected by pitch/roll inputs
|
|
};
|
|
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleAerofoilConfig
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleAerofoilConfig()
|
|
{
|
|
InitDefaults();
|
|
}
|
|
|
|
// Does this aerofoil represent a fixed spoiler, an aircraft wing, etc how is controlled.
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
EVehicleAerofoilType AerofoilType;
|
|
|
|
// Bone name on mesh where aerofoil is centered
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
FName BoneName;
|
|
|
|
// Additional offset to give the aerofoil.
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
FVector Offset;
|
|
|
|
// Up Axis of aerofoil.
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
FVector UpAxis;
|
|
|
|
// Area of aerofoil surface [Meters Squared] - larger value creates more lift but also more drag
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float Area;
|
|
|
|
// camber of wing - leave as zero for a rudder - can be used to trim/level elevator for level flight
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float Camber;
|
|
|
|
// The angle in degrees through which the control surface moves - leave at 0 if it is a fixed surface
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float MaxControlAngle;
|
|
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float StallAngle;
|
|
|
|
// cheat to control amount of lift independently from lift
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float LiftMultiplier;
|
|
|
|
// cheat to control amount of drag independently from lift, a value of zero will offer no drag
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
float DragMultiplier;
|
|
|
|
const Chaos::FAerofoilConfig& GetPhysicsAerofoilConfig(const UChaosVehicleMovementComponent& MovementComponent)
|
|
{
|
|
FillAerofoilSetup(MovementComponent);
|
|
return PAerofoilConfig;
|
|
}
|
|
|
|
void InitDefaults()
|
|
{
|
|
AerofoilType = EVehicleAerofoilType::Fixed;
|
|
BoneName = NAME_None;
|
|
Offset = FVector::ZeroVector;
|
|
UpAxis = FVector(0.f, 0.f, -1.f);
|
|
Area = 1.f;
|
|
Camber = 3.f;
|
|
MaxControlAngle = 0.f;
|
|
StallAngle = 16.f;
|
|
LiftMultiplier = 1.0f;
|
|
DragMultiplier = 1.0f;
|
|
}
|
|
|
|
private:
|
|
|
|
void FillAerofoilSetup(const UChaosVehicleMovementComponent& MovementComponent);
|
|
|
|
Chaos::FAerofoilConfig PAerofoilConfig;
|
|
};
|
|
|
|
USTRUCT()
|
|
struct CHAOSVEHICLES_API FVehicleThrustConfig
|
|
{
|
|
GENERATED_USTRUCT_BODY()
|
|
|
|
FVehicleThrustConfig()
|
|
{
|
|
InitDefaults();
|
|
}
|
|
|
|
// Does this aerofoil represent a fixed spoiler, an aircraft wing, etc how is controlled.
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
EVehicleThrustType ThrustType;
|
|
|
|
/** Bone name on mesh where thrust is located */
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
FName BoneName;
|
|
|
|
/** Additional offset to give the location, or use in preference to the bone */
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
FVector Offset;
|
|
|
|
/** Up Axis of thrust. */
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
FVector ThrustAxis;
|
|
|
|
///** How the thrust is applied as the speed increases */
|
|
//UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
//FRuntimeFloatCurve ThrustCurve;
|
|
|
|
///** Maximum speed after which the thrust will cut off */
|
|
//UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
//float MaxSpeed;
|
|
|
|
/** Maximum thrust force */
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
float MaxThrustForce;
|
|
|
|
/** The angle in degrees through which the control surface moves - leave at 0 if it is a fixed surface */
|
|
UPROPERTY(EditAnywhere, Category = ThrustSetup)
|
|
float MaxControlAngle;
|
|
|
|
// #todo:ControlAxes - X, Y, Z, or X & Y, etc
|
|
const Chaos::FSimpleThrustConfig& GetPhysicsThrusterConfig(const UChaosVehicleMovementComponent& MovementComponent)
|
|
{
|
|
FillThrusterSetup(MovementComponent);
|
|
return PThrusterConfig;
|
|
}
|
|
|
|
void InitDefaults()
|
|
{
|
|
ThrustType = EVehicleThrustType::Fixed;
|
|
BoneName = NAME_None;
|
|
Offset = FVector::ZeroVector;
|
|
ThrustAxis = FVector(1, 0, 0);
|
|
//ThrustCurve.GetRichCurve()->AddKey(0.f, 1.f);
|
|
//ThrustCurve.GetRichCurve()->AddKey(1.f, 1.f);
|
|
MaxThrustForce = 1000.0f;
|
|
MaxControlAngle = 0.f;
|
|
}
|
|
|
|
private:
|
|
void FillThrusterSetup(const UChaosVehicleMovementComponent& MovementComponent);
|
|
|
|
Chaos::FSimpleThrustConfig PThrusterConfig;
|
|
|
|
};
|
|
|
|
class CHAOSVEHICLES_API UChaosVehicleSimulation
|
|
{
|
|
public:
|
|
virtual ~UChaosVehicleSimulation()
|
|
{
|
|
PVehicle.Reset(nullptr);
|
|
}
|
|
|
|
virtual void Init(TUniquePtr<Chaos::FSimpleWheeledVehicle>& PVehicleIn)
|
|
{
|
|
PVehicle = MoveTemp(PVehicleIn);
|
|
}
|
|
|
|
virtual void UpdateConstraintHandles(TArray<FPhysicsConstraintHandle>& ConstraintHandlesIn) {}
|
|
|
|
virtual void TickVehicle(UWorld* WorldIn, float DeltaTime, const FChaosVehicleAsyncInput& InputData, FChaosVehicleAsyncOutput& OutputData, Chaos::FRigidBodyHandle_Internal* Handle);
|
|
|
|
/** Update the async inputs and the history ones*/
|
|
void SyncHistoryInputs(const FChaosVehicleAsyncInput& InputData, Chaos::FRigidBodyHandle_Internal* Handle);
|
|
|
|
/** Apply the defered forces onto the vehicles */
|
|
virtual void ApplyDeferredForces(Chaos::FRigidBodyHandle_Internal* Handle);
|
|
|
|
/** Update the vehicle state */
|
|
virtual void UpdateState(float DeltaTime, const FChaosVehicleAsyncInput& InputData, Chaos::FRigidBodyHandle_Internal* Handle);
|
|
|
|
/** Advance the vehicle simulation */
|
|
virtual void UpdateSimulation(float DeltaTime, const FChaosVehicleAsyncInput& InputData, Chaos::FRigidBodyHandle_Internal* Handle);
|
|
|
|
/** Fill the vehicle output state */
|
|
virtual void FillOutputState(FChaosVehicleAsyncOutput& Output);
|
|
|
|
/** Are enough vehicle systems specified such that physics vehicle simulation is possible */
|
|
virtual bool CanSimulate() const { return true; }
|
|
|
|
/** Pass control Input to the vehicle systems */
|
|
virtual void ApplyInput(const FControlInputs& ControlInputs, float DeltaTime);
|
|
|
|
/** Apply aerodynamic forces to vehicle body */
|
|
virtual void ApplyAerodynamics(float DeltaTime);
|
|
|
|
/** Apply Aerofoil forces to vehicle body */
|
|
virtual void ApplyAerofoilForces(float DeltaTime);
|
|
|
|
/** Apply Thruster forces to vehicle body */
|
|
virtual void ApplyThrustForces(float DeltaTime);
|
|
|
|
/** Apply direct control over vehicle body rotation */
|
|
virtual void ApplyTorqueControl(float DeltaTime, const FChaosVehicleAsyncInput& InputData);
|
|
|
|
/** Add a force to this vehicle */
|
|
void AddForce(const FVector& Force, bool bAllowSubstepping = true, bool bAccelChange = false);
|
|
|
|
/** Add a force at a particular position (world space when bIsLocalForce = false, body space otherwise) */
|
|
void AddForceAtPosition(const FVector& Force, const FVector& Position, bool bAllowSubstepping = true, bool bIsLocalForce = false);
|
|
|
|
/** Add an impulse to this vehicle */
|
|
void AddImpulse(const FVector& Impulse, bool bVelChange);
|
|
|
|
/** Add an impulse to this vehicle and a particular world position */
|
|
void AddImpulseAtPosition(const FVector& Impulse, const FVector& Position);
|
|
|
|
/** Add a torque to this vehicle */
|
|
void AddTorqueInRadians(const FVector& Torque, bool bAllowSubstepping = true, bool bAccelChange = false);
|
|
|
|
/** Reinitialize a wheel at runtime */
|
|
void InitializeWheel(int WheelIndex, const Chaos::FSimpleWheelConfig* InWheelSetup);
|
|
|
|
/** Reinitialize the physics suspension at runtime */
|
|
void InitializeSuspension(int WheelIndex, const Chaos::FSimpleSuspensionConfig* InSuspensionSetup);
|
|
|
|
/** Draw debug text for the wheels and suspension */
|
|
virtual void DrawDebug3D();
|
|
UWorld* World;
|
|
|
|
// Physics Thread Representation of chassis rigid body
|
|
Chaos::FRigidBodyHandle_Internal* RigidHandle;
|
|
|
|
FVehicleState VehicleState;
|
|
|
|
// #todo: this isn't very configurable
|
|
TUniquePtr<Chaos::FSimpleWheeledVehicle> PVehicle;
|
|
|
|
FDeferredForces DeferredForces;
|
|
|
|
/** Current control inputs that is being used on the PT */
|
|
FControlInputs VehicleInputs;
|
|
|
|
FVehicleInputRateConfig ThrottleInputRate;
|
|
FVehicleInputRateConfig SteeringInputRate;
|
|
FVehicleInputRateConfig BrakeInputRate;
|
|
FVehicleInputRateConfig HandbrakeInputRate;
|
|
FVehicleInputRateConfig RollInputRate;
|
|
FVehicleInputRateConfig PitchInputRate;
|
|
FVehicleInputRateConfig YawInputRate;
|
|
};
|
|
|
|
|
|
/**
|
|
* Base component to handle the vehicle simulation for an actor.
|
|
*/
|
|
UCLASS(Abstract, hidecategories = (PlanarMovement, "Components|Movement|Planar", Activation, "Components|Activation"))
|
|
class CHAOSVEHICLES_API UChaosVehicleMovementComponent : public UPawnMovementComponent
|
|
{
|
|
friend struct FChaosVehicleAsyncInput;
|
|
friend struct FChaosVehicleAsyncOutput;
|
|
|
|
friend struct FNetworkVehicleInputs;
|
|
friend struct FNetworkVehicleStates;
|
|
|
|
friend class FChaosVehicleManager;
|
|
friend class FChaosVehicleManagerAsyncCallback;
|
|
|
|
GENERATED_UCLASS_BODY()
|
|
|
|
//#todo: these 2 oddities seem out of place
|
|
|
|
/** If true, the brake and reverse controls will behave in a more arcade fashion where holding reverse also functions as brake. For a more realistic approach turn this off*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup)
|
|
uint8 bReverseAsBrake : 1;
|
|
|
|
/** If true, when reversing the throttle will behave like a brake while the vehicle moving in a backwards direction - requires bReverseAsBrake to be enabled for operation */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (EditCondition = "bReverseAsBrake"))
|
|
uint8 bThrottleAsBrake : 1;
|
|
|
|
public:
|
|
/** Mass to set the vehicle chassis to. It's much easier to tweak vehicle settings when
|
|
* the mass doesn't change due to tweaks with the physics asset. [kg] */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (ClampMin = "0.01", UIMin = "0.01"))
|
|
float Mass;
|
|
|
|
/**
|
|
* Enable to override the calculated COM position with your own fixed value - this prevents the vehicle handling changing when the asset changes
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup)
|
|
bool bEnableCenterOfMassOverride;
|
|
|
|
/**
|
|
* The center of mass override value, this value overrides the calculated COM and the COM offset value in the mesh is also ignored.
|
|
*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (EditCondition = "bEnableCenterOfMassOverride"))
|
|
FVector CenterOfMassOverride;
|
|
|
|
/** Chassis width used for drag force computation (cm)*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (ClampMin = "0.01", UIMin = "0.01"))
|
|
float ChassisWidth;
|
|
|
|
/** Chassis height used for drag force computation (cm)*/
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (ClampMin = "0.01", UIMin = "0.01"))
|
|
float ChassisHeight;
|
|
|
|
/** DragCoefficient of the vehicle chassis - force resisting forward motion at speed */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup)
|
|
float DragCoefficient;
|
|
|
|
/** DownforceCoefficient of the vehicle chassis - force pressing vehicle into ground at speed */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup)
|
|
float DownforceCoefficient;
|
|
|
|
// Drag area in Meters^2
|
|
UPROPERTY(transient)
|
|
float DragArea;
|
|
|
|
// Debug drag magnitude last applied
|
|
UPROPERTY(transient)
|
|
float DebugDragMagnitude;
|
|
|
|
/** Scales the vehicle's inertia in each direction (forward, right, up) */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, AdvancedDisplay)
|
|
FVector InertiaTensorScale;
|
|
|
|
/** Option to apply some aggressive sleep logic, larger number is more agressive, 0 disables */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup)
|
|
float SleepThreshold;
|
|
|
|
/** Option to apply some aggressive sleep logic if slopes up Z is less than this value, i.e value = Cos(SlopeAngle) so 0.866 will sleep up to 30 degree slopes */
|
|
UPROPERTY(EditAnywhere, Category = VehicleSetup, meta = (ClampMin = "0.01", UIMin = "0.01", ClampMax = "1.0", UIMax = "1.0"))
|
|
float SleepSlopeLimit;
|
|
|
|
/** Optional aerofoil setup - can be used for car spoilers or aircraft wings/elevator/rudder */
|
|
UPROPERTY(EditAnywhere, Category = AerofoilSetup)
|
|
TArray<FVehicleAerofoilConfig> Aerofoils;
|
|
|
|
/** Optional thruster setup, use one or more as your main engine or as supplementary booster */
|
|
UPROPERTY(EditAnywhere, Category = ThrusterSetup)
|
|
TArray<FVehicleThrustConfig> Thrusters;
|
|
|
|
/** Arcade style direct control of vehicle rotation via torque force */
|
|
UPROPERTY(EditAnywhere, Category = ArcadeControl)
|
|
FVehicleTorqueControlConfig TorqueControl;
|
|
|
|
/** Arcade style direct control of vehicle rotation via torque force */
|
|
UPROPERTY(EditAnywhere, Category = ArcadeControl)
|
|
FVehicleTargetRotationControlConfig TargetRotationControl;
|
|
|
|
/** Arcade style control of vehicle */
|
|
UPROPERTY(EditAnywhere, Category = ArcadeControl)
|
|
FVehicleStabilizeControlConfig StabilizeControl;
|
|
|
|
// Used to recreate the physics if the blueprint changes.
|
|
uint32 VehicleSetupTag;
|
|
|
|
protected:
|
|
// True if the player is holding the handbrake
|
|
UPROPERTY(Transient)
|
|
uint8 bRawHandbrakeInput : 1;
|
|
|
|
// True if the player is holding gear up
|
|
UPROPERTY(Transient)
|
|
uint8 bRawGearUpInput : 1;
|
|
|
|
// True if the player is holding gear down
|
|
UPROPERTY(Transient)
|
|
uint8 bRawGearDownInput : 1;
|
|
|
|
/** Was avoidance updated in this frame? */
|
|
UPROPERTY(Transient)
|
|
uint32 bWasAvoidanceUpdated : 1;
|
|
|
|
UPROPERTY(Transient)
|
|
uint8 bParkEnabled : 1;
|
|
|
|
Chaos::ETransmissionType TransmissionType;
|
|
|
|
UPROPERTY()
|
|
TObjectPtr<UNetworkPhysicsComponent> NetworkPhysicsComponent = nullptr;
|
|
|
|
public:
|
|
|
|
/** UObject interface */
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
/** End UObject interface*/
|
|
|
|
#if WITH_EDITOR
|
|
/** Respond to a property change in editor */
|
|
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
|
#endif //WITH_EDITOR
|
|
|
|
/** Overridden to allow registration with components NOT owned by a Pawn. */
|
|
virtual void SetUpdatedComponent(USceneComponent* NewUpdatedComponent) override;
|
|
|
|
/** Allow the player controller of a different pawn to control this vehicle */
|
|
virtual void SetOverrideController(AController* OverrideController);
|
|
|
|
|
|
/** Return true if it's suitable to create a physics representation of the vehicle at this time */
|
|
virtual bool ShouldCreatePhysicsState() const override;
|
|
|
|
/** Returns true if the physics state exists */
|
|
virtual bool HasValidPhysicsState() const override;
|
|
|
|
/** Return true if we are ready to create a vehicle, false if the setup has missing references */
|
|
virtual bool CanCreateVehicle() const;
|
|
|
|
/** Used to create any physics engine information for this component */
|
|
virtual void OnCreatePhysicsState() override;
|
|
|
|
/** Used to shut down and physics engine structure for this component */
|
|
virtual void OnDestroyPhysicsState() override;
|
|
|
|
/** Updates the vehicle tuning and other state such as user input. */
|
|
virtual void PreTickGT(float DeltaTime);
|
|
|
|
/** Stops movement immediately (zeroes velocity, usually zeros acceleration for components with acceleration). */
|
|
virtual void StopMovementImmediately() override;
|
|
|
|
/** Set the user input for the vehicle throttle [range 0 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetThrottleInput(float Throttle);
|
|
|
|
/** Increase the vehicle throttle position [throttle range normalized 0 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void IncreaseThrottleInput(float ThrottleDelta);
|
|
|
|
/** Decrease the vehicle throttle position [throttle range normalized 0 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void DecreaseThrottleInput(float ThrottleDelta);
|
|
|
|
/** Set the user input for the vehicle Brake [range 0 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetBrakeInput(float Brake);
|
|
|
|
/** Set the user input for the vehicle steering [range -1 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetSteeringInput(float Steering);
|
|
|
|
/** Set the user input for the vehicle pitch [range -1 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetPitchInput(float Pitch);
|
|
|
|
/** Set the user input for the vehicle roll [range -1 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetRollInput(float Roll);
|
|
|
|
/** Set the user input for the vehicle yaw [range -1 to 1] */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetYawInput(float Yaw);
|
|
|
|
/** Set the user input for handbrake */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetHandbrakeInput(bool bNewHandbrake);
|
|
|
|
/** Set the vehicle in park mode */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetParked(bool bParked);
|
|
|
|
/** Set the vehicle sleeping (bEnableSleep=true) or wake it up (bEnableSleep=false) */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetSleeping(bool bEnableSleep);
|
|
|
|
/** Set the user input for gear up */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetChangeUpInput(bool bNewGearUp);
|
|
|
|
/** Set the user input for gear down */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetChangeDownInput(bool bNewGearDown);
|
|
|
|
/** Set the user input for gear (-1 reverse, 0 neutral, 1+ forward)*/
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetTargetGear(int32 GearNum, bool bImmediate);
|
|
|
|
/** Set the flag that will be used to select auto-gears */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetUseAutomaticGears(bool bUseAuto);
|
|
|
|
/** Set the flag that determines whether a controller is required to set control inputs */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void SetRequiresControllerForInputs(bool bRequiresController);
|
|
|
|
/** Get current gear */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
int32 GetCurrentGear() const;
|
|
|
|
/** Get target gear */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
int32 GetTargetGear() const;
|
|
|
|
/** Are gears being changed automatically? */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
bool GetUseAutoGears() const;
|
|
|
|
/** How fast the vehicle is moving forward */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
float GetForwardSpeed() const;
|
|
|
|
/** How fast the vehicle is moving forward */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
float GetForwardSpeedMPH() const;
|
|
|
|
/** Get the user input for the vehicle throttle - can use this to feed control to a connected trailer */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
float GetThrottleInput() { return RawThrottleInput; }
|
|
|
|
/** Get the user input for the vehicle brake - can use this to feed control to a connected trailer */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
float GetBrakeInput() { return RawBrakeInput; }
|
|
|
|
/** Get the user input for the vehicle handbrake - can use this to feed control to a connected trailer */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
bool GetHandbrakeInput() const { return bRawHandbrakeInput; }
|
|
|
|
/** Get the user input for the vehicle steering - can use this to feed control to a connected trailer */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
float GetSteeringInput() { return RawSteeringInput; }
|
|
|
|
|
|
/** Is the vehicle in park mode */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
bool IsParked() const;
|
|
|
|
/** Reset some vehicle state - call this if you are say creating pool of vehicles that get reused and you don't want to carry over the previous state */
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void ResetVehicle() { ResetVehicleState(); }
|
|
|
|
/** Grab a snapshot of the vehicle instance dynamic state */
|
|
void GetBaseSnapshot(FBaseSnapshotData& SnapshotOut) const;
|
|
|
|
/** Set snapshot of vehicle instance dynamic state */
|
|
void SetBaseSnapshot(const FBaseSnapshotData& SnapshotIn);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "Game|Components|ChaosVehicleMovement")
|
|
void EnableSelfRighting(bool InState)
|
|
{
|
|
TargetRotationControl.Enabled = InState;
|
|
TorqueControl.Enabled = InState;
|
|
StabilizeControl.Enabled = InState;
|
|
}
|
|
|
|
/** location local coordinates of named bone in skeleton, apply additional offset or just use offset if no bone located */
|
|
FVector LocateBoneOffset(const FName InBoneName, const FVector& InExtraOffset) const;
|
|
|
|
TUniquePtr<FPhysicsVehicleOutput>& PhysicsVehicleOutput()
|
|
{
|
|
return PVehicleOutput;
|
|
}
|
|
|
|
virtual float GetSuspensionOffset(int WheelIndex) { return 0.f; }
|
|
|
|
//----ASYNC----
|
|
TUniquePtr<FChaosVehicleAsyncInput> SetCurrentAsyncInputOutput(int32 InputIdx, FChaosVehicleManagerAsyncOutput* CurOutput, FChaosVehicleManagerAsyncOutput* NextOutput, float Alpha, int32 VehicleManagerTimestamp);
|
|
|
|
void SetCurrentAsyncInputOutputInternal(FChaosVehicleAsyncInput* CurInput, int32 InputIdx, FChaosVehicleManagerAsyncOutput* CurOutput, int32 VehicleManagerTimestamp);
|
|
void SetCurrentAsyncInputOutputInternal(FChaosVehicleAsyncInput* CurInput, int32 InputIdx, FChaosVehicleManagerAsyncOutput* CurOutput, FChaosVehicleManagerAsyncOutput* NextOutput, float Alpha, int32 VehicleManagerTimestamp);
|
|
|
|
virtual void Update(float DeltaTime);
|
|
|
|
virtual void ResetVehicleState();
|
|
|
|
// Get output data from Physics Thread
|
|
virtual void ParallelUpdate(float DeltaSeconds);
|
|
|
|
void FinalizeSimCallbackData(FChaosVehicleManagerAsyncInput& Input);
|
|
|
|
EChaosAsyncVehicleDataType CurAsyncType;
|
|
FChaosVehicleAsyncInput* CurAsyncInput;
|
|
struct FChaosVehicleAsyncOutput* CurAsyncOutput;
|
|
struct FChaosVehicleAsyncOutput* NextAsyncOutput;
|
|
float OutputInterpAlpha;
|
|
|
|
struct FAsyncOutputWrapper
|
|
{
|
|
int32 Idx;
|
|
int32 Timestamp;
|
|
|
|
FAsyncOutputWrapper()
|
|
: Idx(INDEX_NONE)
|
|
, Timestamp(INDEX_NONE)
|
|
{
|
|
}
|
|
};
|
|
TArray<FAsyncOutputWrapper> OutputsWaitingOn;
|
|
|
|
protected:
|
|
|
|
// replicated state of vehicle
|
|
UPROPERTY(Transient, Replicated)
|
|
FVehicleReplicatedState ReplicatedState;
|
|
|
|
// accumulator for RB replication errors
|
|
float AngErrorAccumulator;
|
|
|
|
// What the player has the steering set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawSteeringInput;
|
|
|
|
// What the player has the accelerator set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawThrottleInput;
|
|
|
|
// What the player has the brake set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawBrakeInput;
|
|
|
|
// What the player has the pitch set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawPitchInput;
|
|
|
|
// What the player has the roll set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawRollInput;
|
|
|
|
// What the player has the yaw set to. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RawYawInput;
|
|
|
|
// Steering output to physics system. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float SteeringInput;
|
|
|
|
// Accelerator output to physics system. Range 0...1
|
|
UPROPERTY(Transient)
|
|
float ThrottleInput;
|
|
|
|
// Brake output to physics system. Range 0...1
|
|
UPROPERTY(Transient)
|
|
float BrakeInput;
|
|
|
|
// Body Pitch output to physics system. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float PitchInput;
|
|
|
|
// Body Roll output to physics system. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float RollInput;
|
|
|
|
// Body Yaw output to physics system. Range -1...1
|
|
UPROPERTY(Transient)
|
|
float YawInput;
|
|
|
|
// Handbrake output to physics system. Range 0...1
|
|
UPROPERTY(Transient)
|
|
float HandbrakeInput;
|
|
|
|
// Bypass the need for a controller in order for the controls to be processed.
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput)
|
|
bool bRequiresControllerForInputs;
|
|
|
|
// How much to press the brake when the player has release throttle
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput)
|
|
float IdleBrakeInput;
|
|
|
|
// Auto-brake when absolute vehicle forward speed is less than this (cm/s)
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput)
|
|
float StopThreshold;
|
|
|
|
// Auto-brake when vehicle forward speed is opposite of player input by at least this much (cm/s)
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput)
|
|
float WrongDirectionThreshold;
|
|
|
|
public:
|
|
// Rate at which input throttle can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig ThrottleInputRate;
|
|
|
|
// Rate at which input brake can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig BrakeInputRate;
|
|
|
|
// Rate at which input steering can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig SteeringInputRate;
|
|
|
|
// Rate at which input handbrake can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig HandbrakeInputRate;
|
|
|
|
// Rate at which input pitch can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig PitchInputRate;
|
|
|
|
// Rate at which input roll can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig RollInputRate;
|
|
|
|
// Rate at which input yaw can rise and fall
|
|
UPROPERTY(EditAnywhere, Category = VehicleInput, AdvancedDisplay)
|
|
FVehicleInputRateConfig YawInputRate;
|
|
|
|
protected:
|
|
|
|
// input related
|
|
|
|
/** Compute steering input */
|
|
float CalcSteeringInput();
|
|
|
|
/** Compute throttle & brake input */
|
|
void CalcThrottleBrakeInput(float& ThrottleOut, float& BrakeOut);
|
|
|
|
/** Compute handbrake input */
|
|
float CalcHandbrakeInput();
|
|
|
|
/** Compute pitch input */
|
|
float CalcPitchInput();
|
|
|
|
/** Compute roll input */
|
|
float CalcRollInput();
|
|
|
|
/** Compute yaw input */
|
|
float CalcYawInput();
|
|
|
|
/** Compute throttle inputs */
|
|
float CalcThrottleUpInput();
|
|
float CalcThrottleDownInput();
|
|
|
|
/**
|
|
* Clear all interpolated inputs to default values.
|
|
* Raw input won't be cleared, the vehicle may resume input based movement next frame.
|
|
*/
|
|
virtual void ClearInput();
|
|
|
|
/**
|
|
* Clear all raw inputs to default values.
|
|
* Interpolated input won't be cleared, the vehicle will begin interpolating to no input.
|
|
*/
|
|
virtual void ClearRawInput();
|
|
|
|
void ClearAllInput()
|
|
{
|
|
ClearRawInput();
|
|
ClearInput();
|
|
}
|
|
|
|
// Update
|
|
|
|
/** Read current state for simulation */
|
|
virtual void UpdateState(float DeltaTime);
|
|
|
|
/** Option to aggressively sleep the vehicle */
|
|
virtual void ProcessSleeping(const FControlInputs& ControlInputs);
|
|
|
|
/** Pass current state to server */
|
|
UFUNCTION(reliable, server, WithValidation)
|
|
void ServerUpdateState(float InSteeringInput, float InThrottleInput, float InBrakeInput
|
|
, float InHandbrakeInput, int32 InCurrentGear, float InRollInput, float InPitchInput, float InYawInput);
|
|
|
|
// Setup
|
|
|
|
/** Get our controller */
|
|
virtual AController* GetController() const override;
|
|
|
|
/** Retrieve the player controller of the vehicle component */
|
|
APlayerController* GetPlayerController() const;
|
|
|
|
/** Get the mesh this vehicle is tied to */
|
|
class UMeshComponent* GetMesh() const;
|
|
|
|
/** Get Mesh cast as USkeletalMeshComponent, may return null if cast fails */
|
|
USkeletalMeshComponent* GetSkeletalMesh();
|
|
|
|
/** Get Mesh cast as UStaticMeshComponent, may return null if cast fails */
|
|
UStaticMeshComponent* GetStaticMesh();
|
|
|
|
/** Create and setup the Chaos vehicle */
|
|
virtual void CreateVehicle();
|
|
|
|
virtual TUniquePtr<Chaos::FSimpleWheeledVehicle> CreatePhysicsVehicle();
|
|
|
|
/** Skeletal mesh needs some special handling in the vehicle case */
|
|
virtual void FixupSkeletalMesh() {}
|
|
|
|
/** Allocate and setup the Chaos vehicle */
|
|
virtual void SetupVehicle(TUniquePtr<Chaos::FSimpleWheeledVehicle>& PVehicle);
|
|
|
|
/** Do some final setup after the Chaos vehicle gets created */
|
|
virtual void PostSetupVehicle();
|
|
|
|
/** Adjust the Chaos Physics mass */
|
|
virtual void SetupVehicleMass();
|
|
|
|
void UpdateMassProperties(FBodyInstance* BI);
|
|
|
|
/** When vehicle is created we want to compute some helper data like drag area, etc.... Derived classes should use this to properly compute things like engine RPM */
|
|
virtual void ComputeConstants();
|
|
|
|
// Debug
|
|
|
|
void ShowDebugInfo(class AHUD* HUD, class UCanvas* Canvas, const class FDebugDisplayInfo& DisplayInfo, float& YL, float& YPos);
|
|
|
|
/** Draw debug text for the wheels and suspension */
|
|
virtual void DrawDebug(UCanvas* Canvas, float& YL, float& YPos);
|
|
|
|
// draw 2D debug line to UI canvas
|
|
void DrawLine2D(UCanvas* Canvas, const FVector2D& StartPos, const FVector2D& EndPos, FColor Color, float Thickness = 1.f);
|
|
|
|
float GetForwardAcceleration()
|
|
{
|
|
return VehicleState.ForwardsAcceleration;
|
|
}
|
|
|
|
FBodyInstance* GetBodyInstance();
|
|
const FBodyInstance* GetBodyInstance() const;
|
|
FVehicleState VehicleState; /* Useful vehicle state captured at start of frame */
|
|
TUniquePtr<FPhysicsVehicleOutput> PVehicleOutput; /* physics simulation data output from the async physics thread */
|
|
|
|
/** Handle for delegate registered on mesh component */
|
|
FDelegateHandle MeshOnPhysicsStateChangeHandle;
|
|
|
|
protected:
|
|
|
|
TUniquePtr<UChaosVehicleSimulation> VehicleSimulationPT; /* simulation code running on the physics thread async callback */
|
|
|
|
UPROPERTY(transient, Replicated)
|
|
TObjectPtr<AController> OverrideController;
|
|
|
|
const Chaos::FSimpleAerodynamicsConfig& GetAerodynamicsConfig()
|
|
{
|
|
FillAerodynamicsSetup();
|
|
return PAerodynamicsSetup;
|
|
}
|
|
|
|
void FillAerodynamicsSetup()
|
|
{
|
|
PAerodynamicsSetup.DragCoefficient = this->DragCoefficient;
|
|
PAerodynamicsSetup.DownforceCoefficient = this->DownforceCoefficient;
|
|
PAerodynamicsSetup.AreaMetresSquared = Chaos::Cm2ToM2(this->DragArea);
|
|
}
|
|
|
|
void WakeAllEnabledRigidBodies();
|
|
void PutAllEnabledRigidBodiesToSleep();
|
|
|
|
|
|
Chaos::FSimpleAerodynamicsConfig PAerodynamicsSetup;
|
|
int32 TargetGear;
|
|
|
|
float PrevSteeringInput;
|
|
float PrevReplicatedSteeringInput;
|
|
bool bUsingNetworkPhysicsPrediction;
|
|
};
|