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);
}
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()
{
ASSERT(_actor == nullptr);
@@ -394,7 +403,7 @@ void RigidBody::CreateActor()
// Setup flags
#if WITH_PVD
PxActorFlags actorFlags = PxActorFlag::eVISUALIZATION;
PxActorFlags actorFlags = PxActorFlag::eVISUALIZATION;
#else
PxActorFlags actorFlags = static_cast<PxActorFlags>(0);
#endif

View File

@@ -551,6 +551,9 @@ public:
void OnTriggerEnter(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:
/// <summary>

View File

@@ -182,6 +182,14 @@ void WheeledVehicle::Setup()
return;
auto& drive = (PxVehicleDrive4W*&)_drive;
// Release previous
if (drive)
{
WheelVehicles.Remove(this);
drive->free();
drive = nullptr;
}
// Get wheels
Array<Wheel*, FixedAllocation<PX_MAX_NB_WHEELS>> wheels;
_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());
continue;
}
wheels.Add(&wheel);
if (wheel.Collider->IsDuringPlay())
{
wheels.Add(&wheel);
}
}
if (wheels.IsEmpty())
{
// No wheel, no car
// No woman, no cry
if (drive)
{
WheelVehicles.Remove(this);
drive->free();
drive = nullptr;
}
return;
}
_wheelsData.Resize(wheels.Count());
@@ -294,14 +299,22 @@ void WheeledVehicle::Setup()
wheelsSimData->setTireForceAppPointOffset(i, forceAppPointOffset);
PxShape* wheelShape = wheel.Collider->GetPxShape();
wheelsSimData->setWheelShapeMapping(i, shapes.Find(wheelShape));
if (wheel.Collider->IsActiveInHierarchy())
{
wheelsSimData->setWheelShapeMapping(i, shapes.Find(wheelShape));
// Setup Vehicle ID inside word3 for suspension raycasts to ignore self
PxFilterData filter = wheelShape->getQueryFilterData();
filter.word3 = _id.D + 1;
wheelShape->setQueryFilterData(filter);
wheelShape->setSimulationFilterData(filter);
wheelsSimData->setSceneQueryFilterData(i, filter);
// Setup Vehicle ID inside word3 for suspension raycasts to ignore self
PxFilterData filter = wheelShape->getQueryFilterData();
filter.word3 = _id.D + 1;
wheelShape->setQueryFilterData(filter);
wheelShape->setSimulationFilterData(filter);
wheelsSimData->setSceneQueryFilterData(i, filter);
}
else
{
wheelsSimData->setWheelShapeMapping(i, -1);
wheelsSimData->disableWheel(i);
}
}
for (auto child : Children)
{
@@ -375,7 +388,7 @@ void WheeledVehicle::Setup()
// Create vehicle drive
drive = PxVehicleDrive4W::allocate(wheels.Count());
_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);
// Initialize
@@ -442,6 +455,14 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier*
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)
{
RigidBody::BeginPlay(data);

View File

@@ -254,6 +254,7 @@ public:
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
void OnColliderChanged(Collider* c) override;
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 poseB(C2P(colliderB->GetPosition()), C2P(colliderB->GetOrientation()));
return PxGeometryQuery::computePenetration(
C2P(direction),
distance,
shapeA->getGeometry().any(),
poseA,
shapeB->getGeometry().any(),
poseB
);
}
bool Collider::IsAttached() const
{
return _shape && _shape->getActor() != nullptr;
return PxGeometryQuery::computePenetration(C2P(direction), distance, shapeA->getGeometry().any(), poseA, shapeB->getGeometry().any(), poseB);
}
bool Collider::CanAttach(RigidBody* rigidBody) const
@@ -442,15 +430,18 @@ void Collider::BeginPlay(SceneBeginData* data)
void Collider::EndPlay()
{
// Base
PhysicsColliderActor::EndPlay();
if (_shape)
{
// Detach from the actor
auto actor = _shape->getActor();
if (actor)
actor->detachShape(*_shape);
// Check if was using a static actor and cleanup it
if (_staticActor)
if (actor && actor->is<PxRigidDynamic>())
static_cast<RigidBody*>(actor->userData)->OnColliderChanged(this);
else if (_staticActor)
{
RemoveStaticActor();
}
@@ -460,9 +451,6 @@ void Collider::EndPlay()
_shape->release();
_shape = nullptr;
}
// Base
PhysicsColliderActor::EndPlay();
}
void Collider::OnActiveInTreeChanged()
@@ -479,11 +467,7 @@ void Collider::OnActiveInTreeChanged()
auto rigidBody = GetAttachedRigidBody();
if (rigidBody)
{
rigidBody->UpdateMass();
// TODO: maybe wake up only if one ore more shapes attached is active?
//if (rigidBody->GetStartAwake())
// rigidBody->WakeUp();
rigidBody->OnColliderChanged(this);
}
}
}
@@ -500,6 +484,8 @@ void Collider::OnParentChanged()
auto actor = _shape->getActor();
if (actor)
actor->detachShape(*_shape);
if (actor && actor->is<PxRigidDynamic>())
static_cast<RigidBody*>(actor->userData)->OnColliderChanged(this);
// Check if the new parent is a rigidbody
const auto rigidBody = dynamic_cast<RigidBody*>(GetParent());

View File

@@ -149,12 +149,6 @@ 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>
/// Determines whether this collider can be attached the specified rigid body.
/// </summary>