Expose vehicle relationship between speed and steer to driver
This commit is contained in:
@@ -55,6 +55,48 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
|
|||||||
|
|
||||||
void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
|
void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
|
||||||
{
|
{
|
||||||
|
// Don't let have an invalid steer vs speed list.
|
||||||
|
if (&value.SteerVsSpeed == nullptr)
|
||||||
|
value.SteerVsSpeed = Array<WheeledVehicle::SteerControl>();
|
||||||
|
|
||||||
|
if (value.SteerVsSpeed.Count() < 1)
|
||||||
|
value.SteerVsSpeed.Add(WheeledVehicle::SteerControl());
|
||||||
|
else // physx backend requires the max of 4 values only
|
||||||
|
while (value.SteerVsSpeed.Count() > 4)
|
||||||
|
value.SteerVsSpeed.RemoveLast();
|
||||||
|
|
||||||
|
// Maintain all values clamped to have a ordened speed list
|
||||||
|
int steerVsSpeedCount = value.SteerVsSpeed.Count();
|
||||||
|
for (int i = 0; i < steerVsSpeedCount; i++)
|
||||||
|
{
|
||||||
|
// Apply only on changed value
|
||||||
|
if (_driveControl.SteerVsSpeed[i].Speed != value.SteerVsSpeed[i].Speed || _driveControl.SteerVsSpeed[i].Steer != value.SteerVsSpeed[i].Steer)
|
||||||
|
{
|
||||||
|
WheeledVehicle::SteerControl &steerVsSpeed = value.SteerVsSpeed[i];
|
||||||
|
steerVsSpeed.Steer = Math::Saturate(steerVsSpeed.Steer);
|
||||||
|
steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, 10.0f);
|
||||||
|
|
||||||
|
// Clamp speeds to have an ordened list.
|
||||||
|
if (i >= 1)
|
||||||
|
{
|
||||||
|
WheeledVehicle::SteerControl &lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
|
||||||
|
WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
|
||||||
|
float minSpeed = lastSteerVsSpeed.Speed;
|
||||||
|
float maxSpeed = nextSteerVsSpeed.Speed;
|
||||||
|
|
||||||
|
if (i + 1 < steerVsSpeedCount - 1)
|
||||||
|
steerVsSpeed.Speed = Math::Clamp(steerVsSpeed.Speed, minSpeed, maxSpeed);
|
||||||
|
else
|
||||||
|
steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, minSpeed);
|
||||||
|
}
|
||||||
|
else if (steerVsSpeedCount > 1)
|
||||||
|
{
|
||||||
|
WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
|
||||||
|
steerVsSpeed.Speed = Math::Min(steerVsSpeed.Speed, nextSteerVsSpeed.Speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_driveControl = value;
|
_driveControl = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +434,6 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
|
|||||||
SERIALIZE_MEMBER(Engine, _engine);
|
SERIALIZE_MEMBER(Engine, _engine);
|
||||||
SERIALIZE_MEMBER(Differential, _differential);
|
SERIALIZE_MEMBER(Differential, _differential);
|
||||||
SERIALIZE_MEMBER(Gearbox, _gearbox);
|
SERIALIZE_MEMBER(Gearbox, _gearbox);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
|
void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
|
||||||
|
|||||||
@@ -40,6 +40,45 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
|
|||||||
Special
|
Special
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Storage the relationship between speed and steer.
|
||||||
|
/// </summary>
|
||||||
|
API_STRUCT() struct SteerControl : ISerializable
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(SteerControl);
|
||||||
|
API_AUTO_SERIALIZATION();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The vehicle speed.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "Limit(0)") float Speed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target max steer of the speed.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "Limit(0, 1)") float Steer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a Steer/Speed relationship structure.
|
||||||
|
/// </summary>
|
||||||
|
SteerControl()
|
||||||
|
{
|
||||||
|
Speed = 1000;
|
||||||
|
Steer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a Steer/Speed relationship structure.
|
||||||
|
/// <param name="speed">The vehicle speed.</param>
|
||||||
|
/// <param name="steer">The target max steer of the speed.</param>
|
||||||
|
/// </summary>
|
||||||
|
SteerControl(float speed, float steer)
|
||||||
|
{
|
||||||
|
Speed = speed;
|
||||||
|
Steer = steer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vehicle engine settings.
|
/// Vehicle engine settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -94,42 +133,54 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Acceleration input sensitive.
|
/// Acceleration input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deceleration input sensitive.
|
/// Deceleration input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(11)") float FallRateAcceleration = 10.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(11)") float FallRateAcceleration = 10.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Brake input sensitive.
|
/// Brake input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(12)") float RiseRateBrake = 6.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(12)") float RiseRateBrake = 6.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Release brake sensitive.
|
/// Release brake sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(13)") float FallRateBrake = 10.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(13)") float FallRateBrake = 10.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Brake input sensitive.
|
/// Brake input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Release handbrake sensitive.
|
/// Release handbrake sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(15)") float FallRateHandBrake = 12.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(15)") float FallRateHandBrake = 12.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Steer input sensitive.
|
/// Steer input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(16)") float RiseRateSteer = 2.5f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(16)") float RiseRateSteer = 2.5f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Release steer input sensitive.
|
/// Release steer input sensitive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(17)") float FallRateSteer = 5.0f;
|
API_FIELD(Attributes="Limit(0), EditorOrder(17)") float FallRateSteer = 5.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vehicle control relationship between speed and steer. The higher is the speed,
|
||||||
|
/// decrease steer to make vehicle more maneuverable (limited only 4 relationships).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() Array<WheeledVehicle::SteerControl> SteerVsSpeed = Array<WheeledVehicle::SteerControl>
|
||||||
|
{
|
||||||
|
SteerControl(800, 1.0f),
|
||||||
|
SteerControl(1500, 0.7f),
|
||||||
|
SteerControl(2500, 0.5f),
|
||||||
|
SteerControl(5000, 0.2f),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1554,9 +1554,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
|
|||||||
leftBrake = 1.0f;
|
leftBrake = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @formatter:off
|
// Smooth input controls
|
||||||
// Reference: PhysX SDK docs
|
|
||||||
// TODO: expose input control smoothing data
|
|
||||||
PxVehiclePadSmoothingData padSmoothing =
|
PxVehiclePadSmoothingData padSmoothing =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -1591,20 +1589,31 @@ void PhysicsBackend::EndSimulateScene(void* scene)
|
|||||||
wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
|
wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Reference: PhysX SDK docs
|
|
||||||
// TODO: expose steer vs forward curve into per-vehicle (up to 8 points, values clamped into 0/1 range)
|
// Reduce steer by speed to make vehicle more easier to maneuver
|
||||||
static constexpr PxF32 steerVsForwardSpeedData[] =
|
|
||||||
|
constexpr int steerVsSpeedN = 8;
|
||||||
|
PxF32 steerVsForwardSpeedData[steerVsSpeedN];
|
||||||
|
const int lastSteerVsSpeedIndex = wheelVehicle->_driveControl.SteerVsSpeed.Count() - 1;
|
||||||
|
int steerVsSpeedIndex = 0;
|
||||||
|
|
||||||
|
// Steer vs speed data structure example:
|
||||||
|
// array:
|
||||||
|
// speed, steer
|
||||||
|
// 1000, 1.0,
|
||||||
|
// 2000, 0.7,
|
||||||
|
// 5000, 0.5,
|
||||||
|
// ..
|
||||||
|
|
||||||
|
// fill the steerVsForwardSpeedData with the speed and steer
|
||||||
|
for (int i = 0; i < 8; i += 2)
|
||||||
{
|
{
|
||||||
0.0f, 1.0f,
|
steerVsForwardSpeedData[i] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Speed;
|
||||||
20.0f, 0.9f,
|
steerVsForwardSpeedData[i + 1] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Steer;
|
||||||
65.0f, 0.8f,
|
steerVsSpeedIndex = Math::Min(steerVsSpeedIndex + 1, lastSteerVsSpeedIndex);
|
||||||
120.0f, 0.7f,
|
}
|
||||||
PX_MAX_F32, PX_MAX_F32,
|
const PxFixedSizeLookupTable<steerVsSpeedN> steerVsForwardSpeed(steerVsForwardSpeedData, 4);
|
||||||
PX_MAX_F32, PX_MAX_F32,
|
|
||||||
PX_MAX_F32, PX_MAX_F32,
|
|
||||||
PX_MAX_F32, PX_MAX_F32,
|
|
||||||
};
|
|
||||||
const PxFixedSizeLookupTable<8> steerVsForwardSpeed(steerVsForwardSpeedData, 4);
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
if (wheelVehicle->UseAnalogSteering)
|
if (wheelVehicle->UseAnalogSteering)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user