Add proper vehicle setup after editing wheel colliders
This commit is contained in:
@@ -383,6 +383,15 @@ void RigidBody::OnTriggerExit(PhysicsColliderActor* c)
|
|||||||
TriggerExit(c);
|
TriggerExit(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RigidBody::OnColliderChanged(Collider* c)
|
||||||
|
{
|
||||||
|
UpdateMass();
|
||||||
|
|
||||||
|
// TODO: maybe wake up only if one ore more shapes attached is active?
|
||||||
|
//if (GetStartAwake())
|
||||||
|
// WakeUp();
|
||||||
|
}
|
||||||
|
|
||||||
void RigidBody::CreateActor()
|
void RigidBody::CreateActor()
|
||||||
{
|
{
|
||||||
ASSERT(_actor == nullptr);
|
ASSERT(_actor == nullptr);
|
||||||
|
|||||||
@@ -551,6 +551,9 @@ public:
|
|||||||
void OnTriggerEnter(PhysicsColliderActor* c);
|
void OnTriggerEnter(PhysicsColliderActor* c);
|
||||||
void OnTriggerExit(PhysicsColliderActor* c);
|
void OnTriggerExit(PhysicsColliderActor* c);
|
||||||
|
|
||||||
|
// Called when collider gets detached from this rigidbody or activated/deactivated. Used to update rigidbody mass.
|
||||||
|
virtual void OnColliderChanged(Collider* c);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -182,6 +182,14 @@ void WheeledVehicle::Setup()
|
|||||||
return;
|
return;
|
||||||
auto& drive = (PxVehicleDrive4W*&)_drive;
|
auto& drive = (PxVehicleDrive4W*&)_drive;
|
||||||
|
|
||||||
|
// Release previous
|
||||||
|
if (drive)
|
||||||
|
{
|
||||||
|
WheelVehicles.Remove(this);
|
||||||
|
drive->free();
|
||||||
|
drive = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Get wheels
|
// Get wheels
|
||||||
Array<Wheel*, FixedAllocation<PX_MAX_NB_WHEELS>> wheels;
|
Array<Wheel*, FixedAllocation<PX_MAX_NB_WHEELS>> wheels;
|
||||||
_wheelsData.Clear();
|
_wheelsData.Clear();
|
||||||
@@ -202,18 +210,15 @@ void WheeledVehicle::Setup()
|
|||||||
LOG(Warning, "Invalid wheel collider {1} in vehicle {0} cannot be a trigger", ToString(), wheel.Collider->ToString());
|
LOG(Warning, "Invalid wheel collider {1} in vehicle {0} cannot be a trigger", ToString(), wheel.Collider->ToString());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (wheel.Collider->IsDuringPlay())
|
||||||
|
{
|
||||||
wheels.Add(&wheel);
|
wheels.Add(&wheel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (wheels.IsEmpty())
|
if (wheels.IsEmpty())
|
||||||
{
|
{
|
||||||
// No wheel, no car
|
// No wheel, no car
|
||||||
// No woman, no cry
|
// No woman, no cry
|
||||||
if (drive)
|
|
||||||
{
|
|
||||||
WheelVehicles.Remove(this);
|
|
||||||
drive->free();
|
|
||||||
drive = nullptr;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_wheelsData.Resize(wheels.Count());
|
_wheelsData.Resize(wheels.Count());
|
||||||
@@ -294,6 +299,8 @@ void WheeledVehicle::Setup()
|
|||||||
wheelsSimData->setTireForceAppPointOffset(i, forceAppPointOffset);
|
wheelsSimData->setTireForceAppPointOffset(i, forceAppPointOffset);
|
||||||
|
|
||||||
PxShape* wheelShape = wheel.Collider->GetPxShape();
|
PxShape* wheelShape = wheel.Collider->GetPxShape();
|
||||||
|
if (wheel.Collider->IsActiveInHierarchy())
|
||||||
|
{
|
||||||
wheelsSimData->setWheelShapeMapping(i, shapes.Find(wheelShape));
|
wheelsSimData->setWheelShapeMapping(i, shapes.Find(wheelShape));
|
||||||
|
|
||||||
// Setup Vehicle ID inside word3 for suspension raycasts to ignore self
|
// Setup Vehicle ID inside word3 for suspension raycasts to ignore self
|
||||||
@@ -303,6 +310,12 @@ void WheeledVehicle::Setup()
|
|||||||
wheelShape->setSimulationFilterData(filter);
|
wheelShape->setSimulationFilterData(filter);
|
||||||
wheelsSimData->setSceneQueryFilterData(i, filter);
|
wheelsSimData->setSceneQueryFilterData(i, filter);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wheelsSimData->setWheelShapeMapping(i, -1);
|
||||||
|
wheelsSimData->disableWheel(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (auto child : Children)
|
for (auto child : Children)
|
||||||
{
|
{
|
||||||
auto collider = Cast<Collider>(child);
|
auto collider = Cast<Collider>(child);
|
||||||
@@ -375,7 +388,7 @@ void WheeledVehicle::Setup()
|
|||||||
// Create vehicle drive
|
// Create vehicle drive
|
||||||
drive = PxVehicleDrive4W::allocate(wheels.Count());
|
drive = PxVehicleDrive4W::allocate(wheels.Count());
|
||||||
_actor->setSolverIterationCounts(12, 4);
|
_actor->setSolverIterationCounts(12, 4);
|
||||||
drive->setup(CPhysX, _actor, *wheelsSimData, driveSimData, wheels.Count() - 4);
|
drive->setup(CPhysX, _actor, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
|
||||||
WheelVehicles.Add(this);
|
WheelVehicles.Add(this);
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
@@ -442,6 +455,14 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier*
|
|||||||
DESERIALIZE_MEMBER(Gearbox, _gearbox);
|
DESERIALIZE_MEMBER(Gearbox, _gearbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WheeledVehicle::OnColliderChanged(Collider* c)
|
||||||
|
{
|
||||||
|
RigidBody::OnColliderChanged(c);
|
||||||
|
|
||||||
|
// Rebuild vehicle when someone adds/removed wheels
|
||||||
|
Setup();
|
||||||
|
}
|
||||||
|
|
||||||
void WheeledVehicle::BeginPlay(SceneBeginData* data)
|
void WheeledVehicle::BeginPlay(SceneBeginData* data)
|
||||||
{
|
{
|
||||||
RigidBody::BeginPlay(data);
|
RigidBody::BeginPlay(data);
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||||
|
void OnColliderChanged(Collider* c) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -170,19 +170,7 @@ bool Collider::ComputePenetration(const Collider* colliderA, const Collider* col
|
|||||||
const PxTransform poseA(C2P(colliderA->GetPosition()), C2P(colliderA->GetOrientation()));
|
const PxTransform poseA(C2P(colliderA->GetPosition()), C2P(colliderA->GetOrientation()));
|
||||||
const PxTransform poseB(C2P(colliderB->GetPosition()), C2P(colliderB->GetOrientation()));
|
const PxTransform poseB(C2P(colliderB->GetPosition()), C2P(colliderB->GetOrientation()));
|
||||||
|
|
||||||
return PxGeometryQuery::computePenetration(
|
return PxGeometryQuery::computePenetration(C2P(direction), distance, shapeA->getGeometry().any(), poseA, shapeB->getGeometry().any(), poseB);
|
||||||
C2P(direction),
|
|
||||||
distance,
|
|
||||||
shapeA->getGeometry().any(),
|
|
||||||
poseA,
|
|
||||||
shapeB->getGeometry().any(),
|
|
||||||
poseB
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Collider::IsAttached() const
|
|
||||||
{
|
|
||||||
return _shape && _shape->getActor() != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Collider::CanAttach(RigidBody* rigidBody) const
|
bool Collider::CanAttach(RigidBody* rigidBody) const
|
||||||
@@ -442,15 +430,18 @@ void Collider::BeginPlay(SceneBeginData* data)
|
|||||||
|
|
||||||
void Collider::EndPlay()
|
void Collider::EndPlay()
|
||||||
{
|
{
|
||||||
|
// Base
|
||||||
|
PhysicsColliderActor::EndPlay();
|
||||||
|
|
||||||
if (_shape)
|
if (_shape)
|
||||||
{
|
{
|
||||||
// Detach from the actor
|
// Detach from the actor
|
||||||
auto actor = _shape->getActor();
|
auto actor = _shape->getActor();
|
||||||
if (actor)
|
if (actor)
|
||||||
actor->detachShape(*_shape);
|
actor->detachShape(*_shape);
|
||||||
|
if (actor && actor->is<PxRigidDynamic>())
|
||||||
// Check if was using a static actor and cleanup it
|
static_cast<RigidBody*>(actor->userData)->OnColliderChanged(this);
|
||||||
if (_staticActor)
|
else if (_staticActor)
|
||||||
{
|
{
|
||||||
RemoveStaticActor();
|
RemoveStaticActor();
|
||||||
}
|
}
|
||||||
@@ -460,9 +451,6 @@ void Collider::EndPlay()
|
|||||||
_shape->release();
|
_shape->release();
|
||||||
_shape = nullptr;
|
_shape = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base
|
|
||||||
PhysicsColliderActor::EndPlay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Collider::OnActiveInTreeChanged()
|
void Collider::OnActiveInTreeChanged()
|
||||||
@@ -479,11 +467,7 @@ void Collider::OnActiveInTreeChanged()
|
|||||||
auto rigidBody = GetAttachedRigidBody();
|
auto rigidBody = GetAttachedRigidBody();
|
||||||
if (rigidBody)
|
if (rigidBody)
|
||||||
{
|
{
|
||||||
rigidBody->UpdateMass();
|
rigidBody->OnColliderChanged(this);
|
||||||
|
|
||||||
// TODO: maybe wake up only if one ore more shapes attached is active?
|
|
||||||
//if (rigidBody->GetStartAwake())
|
|
||||||
// rigidBody->WakeUp();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,6 +484,8 @@ void Collider::OnParentChanged()
|
|||||||
auto actor = _shape->getActor();
|
auto actor = _shape->getActor();
|
||||||
if (actor)
|
if (actor)
|
||||||
actor->detachShape(*_shape);
|
actor->detachShape(*_shape);
|
||||||
|
if (actor && actor->is<PxRigidDynamic>())
|
||||||
|
static_cast<RigidBody*>(actor->userData)->OnColliderChanged(this);
|
||||||
|
|
||||||
// Check if the new parent is a rigidbody
|
// Check if the new parent is a rigidbody
|
||||||
const auto rigidBody = dynamic_cast<RigidBody*>(GetParent());
|
const auto rigidBody = dynamic_cast<RigidBody*>(GetParent());
|
||||||
|
|||||||
@@ -149,12 +149,6 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether this collider is attached to the body.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns><c>true</c> if this instance is attached; otherwise, <c>false</c>.</returns>
|
|
||||||
API_PROPERTY() bool IsAttached() const;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether this collider can be attached the specified rigid body.
|
/// Determines whether this collider can be attached the specified rigid body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user