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)
{
return GetBox().Intersects(ray, distance, normal);
return _box.Intersects(ray, distance, 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"
RigidBody::RigidBody(const SpawnParams& params)
: PhysicsActor(params)
: Actor(params)
, _actor(nullptr)
, _cachedScale(1.0f)
, _mass(1.0f)
, _linearDamping(0.01f)
, _angularDamping(0.05f)
@@ -24,6 +25,7 @@ RigidBody::RigidBody(const SpawnParams& params)
, _startAwake(true)
, _updateMassWhenScaleChanges(false)
, _overrideMass(false)
, _isUpdatingTransform(false)
{
}
@@ -224,13 +226,13 @@ bool RigidBody::IsSleeping() const
void RigidBody::Sleep() const
{
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
PhysicsBackend::GetRigidActorSleep(_actor);
PhysicsBackend::RigidDynamicActorSleep(_actor);
}
void RigidBody::WakeUp() const
{
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
PhysicsBackend::GetRigidDynamicActorWakeUp(_actor);
PhysicsBackend::RigidDynamicActorWakeUp(_actor);
}
void RigidBody::UpdateMass()
@@ -323,6 +325,16 @@ void RigidBody::OnColliderChanged(Collider* c)
// 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()
{
const Vector3 scale = GetScale();
@@ -339,7 +351,7 @@ void RigidBody::UpdateScale()
void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
PhysicsActor::Serialize(stream, otherObj);
Actor::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(RigidBody);
@@ -364,7 +376,7 @@ void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
void RigidBody::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
// Base
PhysicsActor::Deserialize(stream, modifier);
Actor::Deserialize(stream, modifier);
DESERIALIZE_BIT_MEMBER(OverrideMass, _overrideMass);
DESERIALIZE_MEMBER(Mass, _mass);
@@ -389,6 +401,26 @@ void* RigidBody::GetPhysicsActor() const
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)
{
// Create rigid body
@@ -441,13 +473,13 @@ void RigidBody::BeginPlay(SceneBeginData* data)
UpdateBounds();
// Base
PhysicsActor::BeginPlay(data);
Actor::BeginPlay(data);
}
void RigidBody::EndPlay()
{
// Base
PhysicsActor::EndPlay();
Actor::EndPlay();
if (_actor)
{
@@ -462,7 +494,7 @@ void RigidBody::EndPlay()
void RigidBody::OnActiveInTreeChanged()
{
// Base
PhysicsActor::OnActiveInTreeChanged();
Actor::OnActiveInTreeChanged();
if (_actor)
{
@@ -480,23 +512,18 @@ void RigidBody::OnActiveInTreeChanged()
void RigidBody::OnTransformChanged()
{
// Base
Actor::OnTransformChanged();
// Update physics is not during physics state synchronization
if (!_isUpdatingTransform && _actor)
{
// Base (skip PhysicsActor call to optimize)
Actor::OnTransformChanged();
const bool kinematic = GetIsKinematic() && GetEnableSimulation();
PhysicsBackend::SetRigidActorPose(_actor, _transform.Translation, _transform.Orientation, kinematic, true);
UpdateScale();
UpdateBounds();
}
else
{
// Base
PhysicsActor::OnTransformChanged();
}
UpdateBounds();
}
void RigidBody::OnPhysicsSceneChanged(PhysicsScene* previous)

View File

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

View File

@@ -1607,6 +1607,12 @@ void PhysicsBackend::GetActorBounds(void* actor, BoundingBox& bounds)
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)
{
const PxTransform trans(C2P(position), C2P(orientation));
@@ -1749,13 +1755,13 @@ bool PhysicsBackend::GetRigidDynamicActorIsSleeping(void* actor)
return actorPhysX->isSleeping();
}
void PhysicsBackend::GetRigidActorSleep(void* actor)
void PhysicsBackend::RigidDynamicActorSleep(void* actor)
{
auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->putToSleep();
}
void PhysicsBackend::GetRigidDynamicActorWakeUp(void* actor)
void PhysicsBackend::RigidDynamicActorWakeUp(void* actor)
{
auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->wakeUp();

View File

@@ -131,6 +131,7 @@ public:
static ActorFlags GetActorFlags(void* actor);
static void SetActorFlags(void* actor, ActorFlags value);
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* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static RigidDynamicFlags GetRigidDynamicActorFlags(void* actor);
@@ -148,8 +149,8 @@ public:
static Vector3 GetRigidDynamicActorCenterOfMass(void* actor);
static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Vector3& value);
static bool GetRigidDynamicActorIsSleeping(void* actor);
static void GetRigidActorSleep(void* actor);
static void GetRigidDynamicActorWakeUp(void* actor);
static void RigidDynamicActorSleep(void* actor);
static void RigidDynamicActorWakeUp(void* actor);
static float GetRigidDynamicActorSleepThreshold(void* actor);
static void SetRigidDynamicActorSleepThreshold(void* actor, float value);
static float GetRigidDynamicActorMaxDepenetrationVelocity(void* actor);