Merge branch 'master' into 1.2

This commit is contained in:
Wojtek Figat
2021-04-13 09:52:03 +02:00
39 changed files with 531 additions and 132 deletions

View File

@@ -22,6 +22,7 @@ CharacterController::CharacterController(const SpawnParams& params)
, _radius(50.0f)
, _height(150.0f)
, _minMoveDistance(0.0f)
, _upDirection(Vector3::Up)
, _isUpdatingTransform(false)
, _nonWalkableMode(CharacterController::NonWalkableModes::PreventClimbing)
, _lastFlags(CollisionFlags::None)
@@ -82,6 +83,18 @@ void CharacterController::SetStepOffset(float value)
_controller->setStepOffset(value);
}
void CharacterController::SetUpDirection(const Vector3& up)
{
if (_controller)
_controller->setUpDirection(C2P(up));
_upDirection = up;
}
Vector3 CharacterController::GetUpDirection() const
{
return _controller ? P2C(_controller->getUpDirection()) : _upDirection;
}
void CharacterController::SetMinMoveDistance(float value)
{
_minMoveDistance = Math::Max(value, 0.0f);
@@ -180,6 +193,7 @@ void CharacterController::CreateActor()
// Create controller
_controller = (PxCapsuleController*)Physics::GetControllerManager()->createController(desc);
ASSERT(_controller);
_controller->setUpDirection(C2P(_upDirection));
const auto actor = _controller->getActor();
ASSERT(actor && actor->getNbShapes() == 1);
actor->getShapes(&_shape, 1);
@@ -363,6 +377,7 @@ void CharacterController::Serialize(SerializeStream& stream, const void* otherOb
SERIALIZE_MEMBER(Radius, _radius);
SERIALIZE_MEMBER(Height, _height);
SERIALIZE_MEMBER(MinMoveDistance, _minMoveDistance);
SERIALIZE_MEMBER(UpDirection, _upDirection);
}
void CharacterController::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
@@ -376,4 +391,5 @@ void CharacterController::Deserialize(DeserializeStream& stream, ISerializeModif
DESERIALIZE_MEMBER(Radius, _radius);
DESERIALIZE_MEMBER(Height, _height);
DESERIALIZE_MEMBER(MinMoveDistance, _minMoveDistance);
DESERIALIZE_MEMBER(UpDirection, _upDirection);
}

View File

@@ -65,6 +65,7 @@ private:
float _height;
float _minMoveDistance;
bool _isUpdatingTransform;
Vector3 _upDirection;
NonWalkableModes _nonWalkableMode;
CollisionFlags _lastFlags;
uint32 _filterData[4];
@@ -141,6 +142,17 @@ public:
/// </summary>
API_PROPERTY() void SetStepOffset(float value);
/// <summary>
/// Gets the character up vector.
/// </summary>
API_PROPERTY(Attributes="EditorOrder(240), DefaultValue(true), EditorDisplay(\"Character Controller\")")
Vector3 GetUpDirection() const;
/// <summary>
/// Sets the character up vector.
/// </summary>
API_PROPERTY() void SetUpDirection(const Vector3& up);
/// <summary>
/// Gets the minimum move distance of the character controller. The minimum traveled distance to consider. If traveled distance is smaller, the character doesn't move. This is used to stop the recursive motion algorithm when remaining distance to travel is small.
/// </summary>

View File

@@ -358,6 +358,51 @@ bool Physics::SphereCastAll(const Vector3& center, const float radius, const Vec
return true;
}
bool Physics::CapsuleCast(const Vector3& center, const float radius, const float height, const Vector3& direction, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
return GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback());
}
bool Physics::CapsuleCast(const Vector3& center, const float radius, const float height, const Vector3& direction, RayCastHit& hitInfo, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
if (!GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_SINGLE();
return true;
}
bool Physics::CapsuleCastAll(const Vector3& center, const float radius, const float height, const Vector3& direction, Array<RayCastHit>& results, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
if (!GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_ALL();
return true;
}
bool Physics::CheckBox(const Vector3& center, const Vector3& halfExtents, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
@@ -380,6 +425,17 @@ bool Physics::CheckSphere(const Vector3& center, const float radius, uint32 laye
return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback());
}
bool Physics::CheckCapsule(const Vector3& center, const float radius, const float height, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback());
}
bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<Collider*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
@@ -414,6 +470,23 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array<Col
return true;
}
bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array<Collider*>& results, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
if (!GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_OVERLAP_COLLIDER();
return true;
}
bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<PhysicsColliderActor*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
@@ -447,3 +520,20 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array<Phy
return true;
}
bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array<PhysicsColliderActor*>& results, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
if (!GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_OVERLAP();
return true;
}

View File

@@ -268,6 +268,50 @@ public:
/// <returns>True if sphere hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="hitInfo">The result hit information. Valid only when method returns true.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="results">The result hits. Valid only when method returns true.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCastAll(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Checks whether the given box overlaps with other colliders or not.
/// </summary>
@@ -289,6 +333,17 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool CheckSphere(const Vector3& center, float radius, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Checks whether the given capsule overlaps with other colliders or not.
/// </summary>
/// <param name="center">The capsule center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool CheckCapsule(const Vector3& center, float radius, float height, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given box.
/// </summary>
@@ -312,6 +367,18 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given sphere.
/// </summary>
/// <param name="center">The sphere center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="results">The result colliders that overlap with the given sphere. Valid only when method returns true.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given box.
/// </summary>
@@ -335,6 +402,18 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given sphere.
/// </summary>
/// <param name="center">The capsule center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="results">The result colliders that overlap with the given sphere. Valid only when method returns true.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
public:
/// <summary>