Add proper vehicle setup after editing wheel colliders

This commit is contained in:
Wojtek Figat
2021-03-26 17:11:26 +01:00
parent 2ce14b5e9c
commit e21c9d24de
6 changed files with 60 additions and 46 deletions

View File

@@ -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);

View File

@@ -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>

View File

@@ -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);

View File

@@ -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:

View File

@@ -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());

View File

@@ -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>