Fix invalid Rigidbody bounds if it has no shapes attached

This commit is contained in:
Wojciech Figat
2022-03-28 19:28:25 +02:00
parent 8e79529e4e
commit 0ca6e70b66
7 changed files with 72 additions and 123 deletions

View File

@@ -1396,7 +1396,7 @@ bool Actor::HasActorInChildren(Actor* a) const
bool Actor::IntersectsItself(const Ray& ray, float& distance, Vector3& normal) bool Actor::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
{ {
return GetBox().Intersects(ray, distance, normal); return _box.Intersects(ray, distance, normal);
} }
Actor* Actor::Intersects(const Ray& ray, float& distance, Vector3& normal) Actor* Actor::Intersects(const Ray& ray, float& distance, Vector3& normal)

View File

@@ -1,54 +0,0 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "PhysicsActor.h"
#include "../PhysicsBackend.h"
PhysicsActor::PhysicsActor(const SpawnParams& params)
: Actor(params)
, _cachedScale(1.0f)
, _isUpdatingTransform(false)
{
}
void PhysicsActor::OnActiveTransformChanged()
{
// Change actor transform (but with locking)
ASSERT(!_isUpdatingTransform);
_isUpdatingTransform = true;
Transform transform;
PhysicsBackend::GetRigidActorPose(GetPhysicsActor(), transform.Translation, transform.Orientation);
transform.Scale = _transform.Scale;
if (_parent)
{
_parent->GetTransform().WorldToLocal(transform, _localTransform);
}
else
{
_localTransform = transform;
}
OnTransformChanged();
_isUpdatingTransform = false;
}
void PhysicsActor::OnTransformChanged()
{
// Base
Actor::OnTransformChanged();
UpdateBounds();
}
void PhysicsActor::UpdateBounds()
{
void* actor = GetPhysicsActor();
if (actor)
PhysicsBackend::GetActorBounds(actor, _box);
else
_box = BoundingBox(_transform.Translation);
BoundingSphere::FromBox(_box, _sphere);
}
bool PhysicsActor::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
{
return _box.Intersects(ray, distance, normal);
}

View File

@@ -1,40 +0,0 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Level/Actor.h"
#include "Engine/Physics/Types.h"
#include "IPhysicsActor.h"
/// <summary>
/// A base class for all physical actors.
/// </summary>
/// <seealso cref="Actor" />
API_CLASS(Abstract) class FLAXENGINE_API PhysicsActor : public Actor, public IPhysicsActor
{
DECLARE_SCENE_OBJECT_ABSTRACT(PhysicsActor);
protected:
Vector3 _cachedScale;
bool _isUpdatingTransform;
public:
/// <summary>
/// Updates the bounding box.
/// </summary>
void UpdateBounds();
public:
// [Actor]
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
// [IPhysicsActor]
void OnActiveTransformChanged() override;
protected:
// [Actor]
void OnTransformChanged() override;
};

View File

@@ -8,8 +8,9 @@
#include "Engine/Serialization/Serialization.h" #include "Engine/Serialization/Serialization.h"
RigidBody::RigidBody(const SpawnParams& params) RigidBody::RigidBody(const SpawnParams& params)
: PhysicsActor(params) : Actor(params)
, _actor(nullptr) , _actor(nullptr)
, _cachedScale(1.0f)
, _mass(1.0f) , _mass(1.0f)
, _linearDamping(0.01f) , _linearDamping(0.01f)
, _angularDamping(0.05f) , _angularDamping(0.05f)
@@ -24,6 +25,7 @@ RigidBody::RigidBody(const SpawnParams& params)
, _startAwake(true) , _startAwake(true)
, _updateMassWhenScaleChanges(false) , _updateMassWhenScaleChanges(false)
, _overrideMass(false) , _overrideMass(false)
, _isUpdatingTransform(false)
{ {
} }
@@ -224,13 +226,13 @@ bool RigidBody::IsSleeping() const
void RigidBody::Sleep() const void RigidBody::Sleep() const
{ {
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy()) if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
PhysicsBackend::GetRigidActorSleep(_actor); PhysicsBackend::RigidDynamicActorSleep(_actor);
} }
void RigidBody::WakeUp() const void RigidBody::WakeUp() const
{ {
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy()) if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
PhysicsBackend::GetRigidDynamicActorWakeUp(_actor); PhysicsBackend::RigidDynamicActorWakeUp(_actor);
} }
void RigidBody::UpdateMass() void RigidBody::UpdateMass()
@@ -323,6 +325,16 @@ void RigidBody::OnColliderChanged(Collider* c)
// WakeUp(); // WakeUp();
} }
void RigidBody::UpdateBounds()
{
void* actor = GetPhysicsActor();
if (actor && PhysicsBackend::GetRigidActorShapesCount(actor) != 0)
PhysicsBackend::GetActorBounds(actor, _box);
else
_box = BoundingBox(_transform.Translation);
BoundingSphere::FromBox(_box, _sphere);
}
void RigidBody::UpdateScale() void RigidBody::UpdateScale()
{ {
const Vector3 scale = GetScale(); const Vector3 scale = GetScale();
@@ -339,7 +351,7 @@ void RigidBody::UpdateScale()
void RigidBody::Serialize(SerializeStream& stream, const void* otherObj) void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
{ {
// Base // Base
PhysicsActor::Serialize(stream, otherObj); Actor::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(RigidBody); SERIALIZE_GET_OTHER_OBJ(RigidBody);
@@ -364,7 +376,7 @@ void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
void RigidBody::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) void RigidBody::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{ {
// Base // Base
PhysicsActor::Deserialize(stream, modifier); Actor::Deserialize(stream, modifier);
DESERIALIZE_BIT_MEMBER(OverrideMass, _overrideMass); DESERIALIZE_BIT_MEMBER(OverrideMass, _overrideMass);
DESERIALIZE_MEMBER(Mass, _mass); DESERIALIZE_MEMBER(Mass, _mass);
@@ -389,6 +401,26 @@ void* RigidBody::GetPhysicsActor() const
return _actor; return _actor;
} }
void RigidBody::OnActiveTransformChanged()
{
// Change actor transform (but with locking)
ASSERT(!_isUpdatingTransform);
_isUpdatingTransform = true;
Transform transform;
PhysicsBackend::GetRigidActorPose(GetPhysicsActor(), transform.Translation, transform.Orientation);
transform.Scale = _transform.Scale;
if (_parent)
{
_parent->GetTransform().WorldToLocal(transform, _localTransform);
}
else
{
_localTransform = transform;
}
OnTransformChanged();
_isUpdatingTransform = false;
}
void RigidBody::BeginPlay(SceneBeginData* data) void RigidBody::BeginPlay(SceneBeginData* data)
{ {
// Create rigid body // Create rigid body
@@ -441,13 +473,13 @@ void RigidBody::BeginPlay(SceneBeginData* data)
UpdateBounds(); UpdateBounds();
// Base // Base
PhysicsActor::BeginPlay(data); Actor::BeginPlay(data);
} }
void RigidBody::EndPlay() void RigidBody::EndPlay()
{ {
// Base // Base
PhysicsActor::EndPlay(); Actor::EndPlay();
if (_actor) if (_actor)
{ {
@@ -462,7 +494,7 @@ void RigidBody::EndPlay()
void RigidBody::OnActiveInTreeChanged() void RigidBody::OnActiveInTreeChanged()
{ {
// Base // Base
PhysicsActor::OnActiveInTreeChanged(); Actor::OnActiveInTreeChanged();
if (_actor) if (_actor)
{ {
@@ -480,23 +512,18 @@ void RigidBody::OnActiveInTreeChanged()
void RigidBody::OnTransformChanged() void RigidBody::OnTransformChanged()
{ {
// Base
Actor::OnTransformChanged();
// Update physics is not during physics state synchronization // Update physics is not during physics state synchronization
if (!_isUpdatingTransform && _actor) if (!_isUpdatingTransform && _actor)
{ {
// Base (skip PhysicsActor call to optimize)
Actor::OnTransformChanged();
const bool kinematic = GetIsKinematic() && GetEnableSimulation(); const bool kinematic = GetIsKinematic() && GetEnableSimulation();
PhysicsBackend::SetRigidActorPose(_actor, _transform.Translation, _transform.Orientation, kinematic, true); PhysicsBackend::SetRigidActorPose(_actor, _transform.Translation, _transform.Orientation, kinematic, true);
UpdateScale(); UpdateScale();
UpdateBounds();
}
else
{
// Base
PhysicsActor::OnTransformChanged();
} }
UpdateBounds();
} }
void RigidBody::OnPhysicsSceneChanged(PhysicsScene* previous) void RigidBody::OnPhysicsSceneChanged(PhysicsScene* previous)

View File

@@ -2,7 +2,9 @@
#pragma once #pragma once
#include "PhysicsActor.h" #include "Engine/Level/Actor.h"
#include "Engine/Physics/Types.h"
#include "Engine/Physics/Actors/IPhysicsActor.h"
#include "Engine/Physics/Collisions.h" #include "Engine/Physics/Collisions.h"
class PhysicsColliderActor; class PhysicsColliderActor;
@@ -11,8 +13,8 @@ class Collider;
/// <summary> /// <summary>
/// Physics simulation driven object. /// Physics simulation driven object.
/// </summary> /// </summary>
/// <seealso cref="PhysicsActor" /> /// <seealso cref="Actor" />
API_CLASS() class FLAXENGINE_API RigidBody : public PhysicsActor API_CLASS() class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor
{ {
DECLARE_SCENE_OBJECT(RigidBody); DECLARE_SCENE_OBJECT(RigidBody);
protected: protected:
@@ -35,6 +37,7 @@ protected:
int32 _startAwake : 1; int32 _startAwake : 1;
int32 _updateMassWhenScaleChanges : 1; int32 _updateMassWhenScaleChanges : 1;
int32 _overrideMass : 1; int32 _overrideMass : 1;
int32 _isUpdatingTransform : 1;
public: public:
@@ -537,7 +540,10 @@ public:
// Called when collider gets detached from this rigidbody or activated/deactivated. Used to update rigidbody mass. // Called when collider gets detached from this rigidbody or activated/deactivated. Used to update rigidbody mass.
virtual void OnColliderChanged(Collider* c); virtual void OnColliderChanged(Collider* c);
protected: /// <summary>
/// Updates the bounding box.
/// </summary>
void UpdateBounds();
/// <summary> /// <summary>
/// Updates the rigidbody scale dependent properties like mass (may be modified when actor transformation changes). /// Updates the rigidbody scale dependent properties like mass (may be modified when actor transformation changes).
@@ -546,14 +552,17 @@ protected:
public: public:
// [PhysicsActor] // [Actor]
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;
// [IPhysicsActor]
void* GetPhysicsActor() const override; void* GetPhysicsActor() const override;
void OnActiveTransformChanged() override;
protected: protected:
// [PhysicsActor] // [Actor]
void BeginPlay(SceneBeginData* data) override; void BeginPlay(SceneBeginData* data) override;
void EndPlay() override; void EndPlay() override;
void OnActiveInTreeChanged() override; void OnActiveInTreeChanged() override;

View File

@@ -1607,6 +1607,12 @@ void PhysicsBackend::GetActorBounds(void* actor, BoundingBox& bounds)
bounds = P2C(actorPhysX->getWorldBounds(boundsScale)); bounds = P2C(actorPhysX->getWorldBounds(boundsScale));
} }
int32 PhysicsBackend::GetRigidActorShapesCount(void* actor)
{
auto actorPhysX = (PxRigidActor*)actor;
return actorPhysX->getNbShapes();
}
void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation) void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation)
{ {
const PxTransform trans(C2P(position), C2P(orientation)); const PxTransform trans(C2P(position), C2P(orientation));
@@ -1749,13 +1755,13 @@ bool PhysicsBackend::GetRigidDynamicActorIsSleeping(void* actor)
return actorPhysX->isSleeping(); return actorPhysX->isSleeping();
} }
void PhysicsBackend::GetRigidActorSleep(void* actor) void PhysicsBackend::RigidDynamicActorSleep(void* actor)
{ {
auto actorPhysX = (PxRigidDynamic*)actor; auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->putToSleep(); actorPhysX->putToSleep();
} }
void PhysicsBackend::GetRigidDynamicActorWakeUp(void* actor) void PhysicsBackend::RigidDynamicActorWakeUp(void* actor)
{ {
auto actorPhysX = (PxRigidDynamic*)actor; auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->wakeUp(); actorPhysX->wakeUp();

View File

@@ -131,6 +131,7 @@ public:
static ActorFlags GetActorFlags(void* actor); static ActorFlags GetActorFlags(void* actor);
static void SetActorFlags(void* actor, ActorFlags value); static void SetActorFlags(void* actor, ActorFlags value);
static void GetActorBounds(void* actor, BoundingBox& bounds); static void GetActorBounds(void* actor, BoundingBox& bounds);
static int32 GetRigidActorShapesCount(void* actor);
static void* CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation); static void* CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static void* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation); static void* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static RigidDynamicFlags GetRigidDynamicActorFlags(void* actor); static RigidDynamicFlags GetRigidDynamicActorFlags(void* actor);
@@ -148,8 +149,8 @@ public:
static Vector3 GetRigidDynamicActorCenterOfMass(void* actor); static Vector3 GetRigidDynamicActorCenterOfMass(void* actor);
static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Vector3& value); static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Vector3& value);
static bool GetRigidDynamicActorIsSleeping(void* actor); static bool GetRigidDynamicActorIsSleeping(void* actor);
static void GetRigidActorSleep(void* actor); static void RigidDynamicActorSleep(void* actor);
static void GetRigidDynamicActorWakeUp(void* actor); static void RigidDynamicActorWakeUp(void* actor);
static float GetRigidDynamicActorSleepThreshold(void* actor); static float GetRigidDynamicActorSleepThreshold(void* actor);
static void SetRigidDynamicActorSleepThreshold(void* actor, float value); static void SetRigidDynamicActorSleepThreshold(void* actor, float value);
static float GetRigidDynamicActorMaxDepenetrationVelocity(void* actor); static float GetRigidDynamicActorMaxDepenetrationVelocity(void* actor);