Add proper vehicle setup after editing wheel colliders
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user