Merge branch 'development' of https://github.com/aws-lumberyard/o3de into mp_systemcomp_cleanup
This commit is contained in:
+38
-8
@@ -56,6 +56,7 @@ def C18243584_Joints_HingeSoftLimitsConstrained():
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import math
|
||||
|
||||
import ImportPathHelper as imports
|
||||
|
||||
@@ -93,22 +94,51 @@ def C18243584_Joints_HingeSoftLimitsConstrained():
|
||||
Report.info_vector3(lead.position, "lead initial position:")
|
||||
Report.info_vector3(follower.position, "follower initial position:")
|
||||
leadInitialPosition = lead.position
|
||||
followerInitialPosition = follower.position
|
||||
|
||||
# 4) Wait for the follower to move above the lead or Timeout
|
||||
normalizedStartPos = JointsHelper.getRelativeVector(lead.position, follower.position)
|
||||
normalizedStartPos = normalizedStartPos.GetNormalizedSafe()
|
||||
|
||||
# 4) Wait for several seconds
|
||||
general.idle_wait(4.0) # wait for lead and follower to move
|
||||
class WaitCondition:
|
||||
TARGET_ANGLE = math.radians(45)
|
||||
TARGET_MAX_ANGLE = math.radians(180)
|
||||
|
||||
angleAchieved = 0.0
|
||||
followerMovedAbove45Deg = False #this is expected to be true to pass the test
|
||||
followerMovedAbove180Deg = True #this is expected to be false to pass the test
|
||||
|
||||
def checkConditionMet(self):
|
||||
#calculate the current follower-lead vector
|
||||
normalVec = JointsHelper.getRelativeVector(lead.position, follower.position)
|
||||
normalVec = normalVec.GetNormalizedSafe()
|
||||
#dot product + acos to get the angle
|
||||
currentAngle = math.acos(normalizedStartPos.Dot(normalVec))
|
||||
#if the angle is now less then last time, it is no longer rising, so end the test.
|
||||
if currentAngle < self.angleAchieved:
|
||||
return True
|
||||
|
||||
self.angleAchieved = currentAngle
|
||||
self.followerMovedAbove45Deg = currentAngle > self.TARGET_ANGLE
|
||||
self.followerMovedAbove180Deg = currentAngle > self.TARGET_MAX_ANGLE
|
||||
return False
|
||||
|
||||
def isFollowerPositionCorrect(self):
|
||||
return self.followerMovedAbove45Deg and not self.followerMovedAbove180Deg
|
||||
|
||||
waitCondition = WaitCondition()
|
||||
|
||||
MAX_WAIT_TIME = 5.0 #seconds
|
||||
conditionMet = helper.wait_for_condition(lambda: waitCondition.checkConditionMet(), MAX_WAIT_TIME)
|
||||
|
||||
# 5) Check to see if lead and follower behaved as expected
|
||||
Report.info_vector3(lead.position, "lead position after 1 second:")
|
||||
Report.info_vector3(follower.position, "follower position after 1 second:")
|
||||
Report.info_vector3(lead.position, "lead position after test:")
|
||||
Report.info_vector3(follower.position, "follower position after test:")
|
||||
|
||||
leadPositionDelta = lead.position.Subtract(leadInitialPosition)
|
||||
leadRemainedStill = JointsHelper.vector3SmallerThanScalar(leadPositionDelta, FLOAT_EPSILON)
|
||||
Report.critical_result(Tests.check_lead_position, leadRemainedStill)
|
||||
|
||||
followerMovedInXOnly = ((follower.position.x > leadInitialPosition.x) > FLOAT_EPSILON and
|
||||
(follower.position.z - leadInitialPosition.z) > FLOAT_EPSILON)
|
||||
Report.critical_result(Tests.check_follower_position, followerMovedInXOnly)
|
||||
Report.critical_result(Tests.check_follower_position, conditionMet and waitCondition.isFollowerPositionCorrect())
|
||||
|
||||
# 6) Exit Game Mode
|
||||
helper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:16f592487e8973abcf6b696aee6e430924c22daac0d6bb781c9e76153cd932f7
|
||||
size 8885
|
||||
oid sha256:352a64f523b3246000393309fa7f14955fe554e0b792a4177349f0f2db8a2b62
|
||||
size 5901
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4d5c38cf9b97ae28c391916e6637aebf767d5ac009df61e730396fe8b116f3e5
|
||||
size 6913
|
||||
oid sha256:31bd1feb92c3bb8a5c5df4638927a9a80e879329965732c4c32f673c236a8b0a
|
||||
size 6021
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a6f26f1c1c037fa0b848ac9b3d9a76e476b4853d770f1a77c01714286733b567
|
||||
size 6921
|
||||
oid sha256:063779c1e80ce22319cb82ff0d7635d3dcbb043b789c3830cc405ffa36d3c0ef
|
||||
size 5876
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4ffd3c4ee04fa8a414995c39c7ca79246e3d9b0ceee1ad1b85d61a5298f71495
|
||||
size 6940
|
||||
oid sha256:5bd3a952841aa924a4869c74fad7ed397667a87948270f0ce35f314e6cf2e14a
|
||||
size 5927
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(Joint, AZ::SystemAllocator, 0);
|
||||
|
||||
void Joint::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AzPhysics::Joint>()
|
||||
->Version(1)
|
||||
->Field("SceneOwner", &Joint::m_sceneOwner)
|
||||
->Field("JointHandle", &Joint::m_jointHandle)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct JointConfiguration;
|
||||
|
||||
//! Base class for all Joints in Physics.
|
||||
struct Joint
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::Joint, "{1EEC9382-3434-4866-9B18-E93F151A6F59}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
virtual ~Joint() = default;
|
||||
|
||||
//! The current Scene the joint is contained.
|
||||
SceneHandle m_sceneOwner = AzPhysics::InvalidSceneHandle;
|
||||
|
||||
//! The handle to this joint.
|
||||
JointHandle m_jointHandle = AzPhysics::InvalidJointHandle;
|
||||
|
||||
//! Helper functions for setting user data.
|
||||
//! @param userData Can be a pointer to any type as internally will be cast to a void*. Object lifetime not managed by the Joint.
|
||||
template<typename T>
|
||||
void SetUserData(T* userData)
|
||||
{
|
||||
m_customUserData = static_cast<void*>(userData);
|
||||
}
|
||||
//! Helper functions for getting the set user data.
|
||||
//! @return Will return a void* to the user data set.
|
||||
void* GetUserData()
|
||||
{
|
||||
return m_customUserData;
|
||||
}
|
||||
|
||||
virtual AZ::Crc32 GetNativeType() const = 0;
|
||||
virtual void* GetNativePointer() const = 0;
|
||||
|
||||
virtual AzPhysics::SimulatedBodyHandle GetParentBodyHandle() const = 0;
|
||||
virtual AzPhysics::SimulatedBodyHandle GetChildBodyHandle() const = 0;
|
||||
|
||||
virtual void SetParentBody(AzPhysics::SimulatedBodyHandle parentBody) = 0;
|
||||
virtual void SetChildBody(AzPhysics::SimulatedBodyHandle childBody) = 0;
|
||||
|
||||
virtual void GenerateJointLimitVisualizationData(
|
||||
[[ maybe_unused ]] float scale,
|
||||
[[ maybe_unused ]] AZ::u32 angularSubdivisions,
|
||||
[[ maybe_unused ]] AZ::u32 radialSubdivisions,
|
||||
[[ maybe_unused ]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
[[ maybe_unused ]] AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
[[ maybe_unused ]] AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
[[ maybe_unused ]] AZStd::vector<bool>& lineValidityBufferOut) { }
|
||||
|
||||
private:
|
||||
void* m_customUserData = nullptr;
|
||||
};
|
||||
|
||||
//! Alias for a list of non owning weak pointers to Joint objects.
|
||||
using JointList = AZStd::vector<Joint*>;
|
||||
|
||||
//! Interface to access Joint utilities and helper functions
|
||||
class JointHelpersInterface
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AzPhysics::JointHelpersInterface, "{A511C64D-C8A5-4E8F-9C69-8DC5EFAD0C4C}");
|
||||
|
||||
JointHelpersInterface() = default;
|
||||
virtual ~JointHelpersInterface() = default;
|
||||
AZ_DISABLE_COPY_MOVE(JointHelpersInterface);
|
||||
|
||||
//! Returns a list of supported Joint types
|
||||
virtual const AZStd::vector<AZ::TypeId> GetSupportedJointTypeIds() const = 0;
|
||||
|
||||
//! Returns a TypeID if the request joint type is supported.
|
||||
//! If the Physics backend supports this joint type JointHelpersInterface::GetSupportedJointTypeId will return a AZ::TypeId.
|
||||
virtual AZStd::optional<const AZ::TypeId> GetSupportedJointTypeId(JointType typeEnum) const = 0;
|
||||
|
||||
//! Computes parameters such as joint limit local rotations to give the desired initial joint limit orientation.
|
||||
//! @param jointLimitTypeId The type ID used to identify the particular kind of joint limit configuration to be created.
|
||||
//! @param parentWorldRotation The rotation in world space of the parent world body associated with the joint.
|
||||
//! @param childWorldRotation The rotation in world space of the child world body associated with the joint.
|
||||
//! @param axis Axis used to define the centre for limiting angular degrees of freedom.
|
||||
//! @param exampleLocalRotations A vector (which may be empty) containing example valid rotations in the local space
|
||||
//! of the child world body relative to the parent world body, which may optionally be used to help estimate the extents
|
||||
//! of the joint limit.
|
||||
virtual AZStd::unique_ptr<JointConfiguration> ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) = 0;
|
||||
|
||||
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
|
||||
/// @param configuration The joint configuration to generate visualization data for.
|
||||
/// @param parentRotation The rotation of the joint's parent body (in the same frame as childRotation).
|
||||
/// @param childRotation The rotation of the joint's child body (in the same frame as parentRotation).
|
||||
/// @param scale Scale factor for the output display data.
|
||||
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
|
||||
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
|
||||
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] lineBufferOut Used to define lines to be displayed.
|
||||
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
|
||||
virtual void GenerateJointLimitVisualizationData(
|
||||
const JointConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) = 0;
|
||||
};
|
||||
}
|
||||
@@ -51,8 +51,10 @@ namespace AzPhysics
|
||||
|
||||
using SceneIndex = AZ::s8;
|
||||
using SimulatedBodyIndex = AZ::s32;
|
||||
using JointIndex = AZ::s32;
|
||||
static_assert(std::is_signed<SceneIndex>::value
|
||||
&& std::is_signed<SimulatedBodyIndex>::value, "SceneIndex and SimulatedBodyIndex must be signed integers.");
|
||||
&& std::is_signed<SimulatedBodyIndex>::value
|
||||
&& std::is_signed<JointIndex>::value, "SceneIndex, SimulatedBodyIndex and JointIndex must be signed integers.");
|
||||
|
||||
|
||||
//! A handle to a Scene within the physics simulation.
|
||||
@@ -69,12 +71,27 @@ namespace AzPhysics
|
||||
static constexpr SimulatedBodyHandle InvalidSimulatedBodyHandle = { AZ::Crc32(), -1 };
|
||||
using SimulatedBodyHandleList = AZStd::vector<SimulatedBodyHandle>;
|
||||
|
||||
//! A handle to a Joint within a physics scene.
|
||||
//! A JointHandle is a tuple of a Crc of the scene's name and the index in the Joint list.
|
||||
using JointHandle = AZStd::tuple<AZ::Crc32, JointIndex>;
|
||||
static constexpr JointHandle InvalidJointHandle = { AZ::Crc32(), -1 };
|
||||
|
||||
//! Helper used for pairing the ShapeConfiguration and ColliderConfiguration together which is used when creating a Simulated Body.
|
||||
using ShapeColliderPair = AZStd::pair<
|
||||
AZStd::shared_ptr<Physics::ColliderConfiguration>,
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration>>;
|
||||
using ShapeColliderPairList = AZStd::vector<ShapeColliderPair>;
|
||||
|
||||
//! Joint types are used to request for AZ::TypeId with the JointHelpersInterface::GetSupportedJointTypeId.
|
||||
//! If the Physics backend supports this joint type JointHelpersInterface::GetSupportedJointTypeId will return a AZ::TypeId.
|
||||
enum class JointType
|
||||
{
|
||||
D6Joint,
|
||||
FixedJoint,
|
||||
BallJoint,
|
||||
HingeJoint
|
||||
};
|
||||
|
||||
//! Flags used to specifying which properties of a body to compute.
|
||||
enum class MassComputeFlags : AZ::u8
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JointConfiguration, AZ::SystemAllocator, 0);
|
||||
|
||||
void JointConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Name", &JointConfiguration::m_debugName)
|
||||
->Field("ParentLocalRotation", &JointConfiguration::m_parentLocalRotation)
|
||||
->Field("ParentLocalPosition", &JointConfiguration::m_parentLocalPosition)
|
||||
->Field("ChildLocalRotation", &JointConfiguration::m_childLocalRotation)
|
||||
->Field("ChildLocalPosition", &JointConfiguration::m_childLocalPosition)
|
||||
->Field("StartSimulationEnabled", &JointConfiguration::m_startSimulationEnabled)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
//! Base Class of all Physics Joints that will be simulated.
|
||||
struct JointConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(AzPhysics::JointConfiguration, "{DF91D39A-4901-48C4-9159-93FD2ACA5252}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointConfiguration() = default;
|
||||
virtual ~JointConfiguration() = default;
|
||||
|
||||
// Entity/object association.
|
||||
void* m_customUserData = nullptr;
|
||||
|
||||
// Basic initial settings.
|
||||
AZ::Quaternion m_parentLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Parent joint frame relative to parent body.
|
||||
AZ::Vector3 m_parentLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to parent body.
|
||||
AZ::Quaternion m_childLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Child joint frame relative to child body.
|
||||
AZ::Vector3 m_childLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to child body.
|
||||
bool m_startSimulationEnabled = true;
|
||||
|
||||
// For debugging/tracking purposes only.
|
||||
AZStd::string m_debugName;
|
||||
};
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
const char* JointLimitConfiguration::GetTypeName()
|
||||
{
|
||||
return "Base Joint";
|
||||
}
|
||||
|
||||
void JointLimitConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointLimitConfiguration>()
|
||||
->Version(1)
|
||||
->Field("ParentLocalRotation", &JointLimitConfiguration::m_parentLocalRotation)
|
||||
->Field("ParentLocalPosition", &JointLimitConfiguration::m_parentLocalPosition)
|
||||
->Field("ChildLocalRotation", &JointLimitConfiguration::m_childLocalRotation)
|
||||
->Field("ChildLocalPosition", &JointLimitConfiguration::m_childLocalPosition)
|
||||
;
|
||||
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<JointLimitConfiguration>(
|
||||
"Joint Configuration", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_parentLocalRotation,
|
||||
"Parent local rotation", "The rotation of the parent joint frame relative to the parent body")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_parentLocalPosition,
|
||||
"Parent local position", "The position of the joint in the frame of the parent body")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_childLocalRotation,
|
||||
"Child local rotation", "The rotation of the child joint frame relative to the child body")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_childLocalPosition,
|
||||
"Child local position", "The position of the joint in the frame of the child body")
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Physics
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class JointLimitConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(JointLimitConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(JointLimitConfiguration, "{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointLimitConfiguration() = default;
|
||||
JointLimitConfiguration(const JointLimitConfiguration&) = default;
|
||||
virtual ~JointLimitConfiguration() = default;
|
||||
|
||||
virtual const char* GetTypeName();
|
||||
|
||||
AZ::Quaternion m_parentLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Parent joint frame relative to parent body.
|
||||
AZ::Vector3 m_parentLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to parent body.
|
||||
AZ::Quaternion m_childLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Child joint frame relative to child body.
|
||||
AZ::Vector3 m_childLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to child body.
|
||||
};
|
||||
|
||||
class Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Joint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Joint, "{405F517C-E986-4ACB-9606-D5D080DDE987}");
|
||||
|
||||
virtual AzPhysics::SimulatedBody* GetParentBody() const = 0;
|
||||
virtual AzPhysics::SimulatedBody* GetChildBody() const = 0;
|
||||
virtual void SetParentBody(AzPhysics::SimulatedBody* parentBody) = 0;
|
||||
virtual void SetChildBody(AzPhysics::SimulatedBody* childBody) = 0;
|
||||
virtual const AZStd::string& GetName() const = 0;
|
||||
virtual void SetName(const AZStd::string& name) = 0;
|
||||
virtual const AZ::Crc32 GetNativeType() const = 0;
|
||||
virtual void* GetNativePointer() = 0;
|
||||
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
|
||||
/// @param scale Scale factor for the output display data.
|
||||
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
|
||||
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
|
||||
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] lineBufferOut Used to define lines to be displayed.
|
||||
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
|
||||
virtual void GenerateJointLimitVisualizationData(
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) = 0;
|
||||
};
|
||||
} // namespace Physics
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
|
||||
namespace AzPhysics
|
||||
@@ -103,6 +105,26 @@ namespace AzPhysics
|
||||
virtual void EnableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
virtual void DisableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Add a joint to the Scene.
|
||||
//! @param sceneHandle A handle to the scene to add / remove the joint.
|
||||
//! @param jointConfig The config of the joint.
|
||||
//! @param parentBody The parent body of the joint.
|
||||
//! @param childBody The child body of the joint
|
||||
//! @return Returns a handle to the created joint. Will return AzPhyiscs::InvalidJointHandle if it fails.
|
||||
virtual JointHandle AddJoint(SceneHandle sceneHandle, const JointConfiguration* jointConfig,
|
||||
SimulatedBodyHandle parentBody, SimulatedBodyHandle childBody) = 0;
|
||||
|
||||
//! Get the Raw pointer to the requested joint.
|
||||
//! @param sceneHandle A handle to the scene to get the simulated bodies from.
|
||||
//! @param jointHandle A handle to the joint to retrieve the raw pointer.
|
||||
//! @return A raw pointer to the Joint body. If the either handle is invalid this will return null.
|
||||
virtual Joint* GetJointFromHandle(SceneHandle sceneHandle, JointHandle jointHandle) = 0;
|
||||
|
||||
//! Remove a joint from the Scene.
|
||||
//! @param sceneHandle A handle to the scene to add / remove the joint.
|
||||
//! @param jointHandle A handle to the joint being removed.
|
||||
virtual void RemoveJoint(SceneHandle sceneHandle, JointHandle jointHandle) = 0;
|
||||
|
||||
//! Make a blocking query into the scene.
|
||||
//! @param sceneHandle A handle to the scene to make the scene query with.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
@@ -299,6 +321,23 @@ namespace AzPhysics
|
||||
virtual void EnableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
|
||||
virtual void DisableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
|
||||
|
||||
//! Add a joint to the Scene.
|
||||
//! @param jointConfig The config of the joint.
|
||||
//! @param parentBody The parent body of the joint.
|
||||
//! @param childBody The child body of the joint
|
||||
//! @return Returns a handle to the created joint. Will return AzPhyiscs::InvalidJointHandle if it fails.
|
||||
virtual JointHandle AddJoint(const JointConfiguration* jointConfig,
|
||||
SimulatedBodyHandle parentBody, SimulatedBodyHandle childBody) = 0;
|
||||
|
||||
//! Get the Raw pointer to the requested joint.
|
||||
//! @param jointHandle A handle to the joint to retrieve the raw pointer.
|
||||
//! @return A raw pointer to the Joint body. If the either handle is invalid this will return null.
|
||||
virtual Joint* GetJointFromHandle(JointHandle jointHandle) = 0;
|
||||
|
||||
//! Remove a joint from the Scene.
|
||||
//! @param jointHandle A handle to the joint being removed.
|
||||
virtual void RemoveJoint(JointHandle jointHandle) = 0;
|
||||
|
||||
//! Make a blocking query into the scene.
|
||||
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
|
||||
//! @return Returns a structure that contains a list of Hits. Depending on flags set in the request, this may only contain 1 result.
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Physics
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<RagdollNodeConfiguration, RigidBodyConfiguration>()
|
||||
->Version(4, &ClassConverters::RagdollNodeConfigConverter)
|
||||
->Field("JointLimit", &RagdollNodeConfiguration::m_jointLimit)
|
||||
->Version(5, &ClassConverters::RagdollNodeConfigConverter)
|
||||
->Field("JointConfig", &RagdollNodeConfiguration::m_jointConfig)
|
||||
;
|
||||
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/RagdollPhysicsBus.h>
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
@@ -37,7 +38,7 @@ namespace Physics
|
||||
RagdollNodeConfiguration();
|
||||
RagdollNodeConfiguration(const RagdollNodeConfiguration& settings) = default;
|
||||
|
||||
AZStd::shared_ptr<JointLimitConfiguration> m_jointLimit;
|
||||
AZStd::shared_ptr<AzPhysics::JointConfiguration> m_jointConfig;
|
||||
};
|
||||
|
||||
class RagdollConfiguration
|
||||
@@ -73,7 +74,7 @@ namespace Physics
|
||||
virtual AzPhysics::RigidBody& GetRigidBody() = 0;
|
||||
virtual ~RagdollNode() = default;
|
||||
|
||||
virtual const AZStd::shared_ptr<Physics::Joint>& GetJoint() const = 0;
|
||||
virtual AzPhysics::Joint* GetJoint() = 0;
|
||||
virtual bool IsSimulating() const = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,23 +26,15 @@ namespace AZ
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
struct RigidBodyConfiguration;
|
||||
struct RigidBody;
|
||||
}
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
class WorldBody;
|
||||
class Shape;
|
||||
class Material;
|
||||
class MaterialSelection;
|
||||
class MaterialConfiguration;
|
||||
class ColliderConfiguration;
|
||||
class ShapeConfiguration;
|
||||
class JointLimitConfiguration;
|
||||
class Joint;
|
||||
class CharacterConfiguration;
|
||||
class Character;
|
||||
|
||||
/// Represents a debug vertex (position & color).
|
||||
struct DebugDrawVertex
|
||||
@@ -148,51 +140,6 @@ namespace Physics
|
||||
/// @param nativeMeshObject Pointer to the mesh object.
|
||||
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// Joints
|
||||
|
||||
virtual AZStd::vector<AZ::TypeId> GetSupportedJointTypes() = 0;
|
||||
virtual AZStd::shared_ptr<JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType) = 0;
|
||||
virtual AZStd::shared_ptr<Joint> CreateJoint(const AZStd::shared_ptr<JointLimitConfiguration>& configuration,
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody) = 0;
|
||||
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
|
||||
/// @param configuration The joint configuration to generate visualization data for.
|
||||
/// @param parentRotation The rotation of the joint's parent body (in the same frame as childRotation).
|
||||
/// @param childRotation The rotation of the joint's child body (in the same frame as parentRotation).
|
||||
/// @param scale Scale factor for the output display data.
|
||||
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
|
||||
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
|
||||
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
|
||||
/// @param[out] lineBufferOut Used to define lines to be displayed.
|
||||
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
|
||||
virtual void GenerateJointLimitVisualizationData(
|
||||
const JointLimitConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) = 0;
|
||||
|
||||
/// Computes parameters such as joint limit local rotations to give the desired initial joint limit orientation.
|
||||
/// @param jointLimitTypeId The type ID used to identify the particular kind of joint limit configuration to be created.
|
||||
/// @param parentWorldRotation The rotation in world space of the parent world body associated with the joint.
|
||||
/// @param childWorldRotation The rotation in world space of the child world body associated with the joint.
|
||||
/// @param axis Axis used to define the centre for limiting angular degrees of freedom.
|
||||
/// @param exampleLocalRotations A vector (which may be empty) containing example valid rotations in the local space
|
||||
/// of the child world body relative to the parent world body, which may optionally be used to help estimate the extents
|
||||
/// of the joint limit.
|
||||
virtual AZStd::unique_ptr<JointLimitConfiguration> ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// Cooking
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
@@ -121,9 +122,9 @@ namespace Physics
|
||||
DefaultMaterialConfiguration::Reflect(context);
|
||||
MaterialLibraryAsset::Reflect(context);
|
||||
MaterialInfoReflectionWrapper::Reflect(context);
|
||||
JointLimitConfiguration::Reflect(context);
|
||||
AzPhysics::SimulatedBodyConfiguration::Reflect(context);
|
||||
AzPhysics::RigidBodyConfiguration::Reflect(context);
|
||||
AzPhysics::JointConfiguration::Reflect(context);
|
||||
RagdollNodeConfiguration::Reflect(context);
|
||||
RagdollConfiguration::Reflect(context);
|
||||
CharacterColliderNodeConfiguration::Reflect(context);
|
||||
@@ -131,6 +132,7 @@ namespace Physics
|
||||
AnimationConfiguration::Reflect(context);
|
||||
CharacterConfiguration::Reflect(context);
|
||||
AzPhysics::SimulatedBody::Reflect(context);
|
||||
AzPhysics::Joint::Reflect(context);
|
||||
ReflectSimulatedBodyComponentRequestsBus(context);
|
||||
CollisionFilteringRequests::Reflect(context);
|
||||
AzPhysics::SceneQuery::ReflectSceneQueryObjects(context);
|
||||
|
||||
@@ -204,6 +204,8 @@ set(FILES
|
||||
Physics/Collision/CollisionLayers.cpp
|
||||
Physics/Collision/CollisionGroups.h
|
||||
Physics/Collision/CollisionGroups.cpp
|
||||
Physics/Common/PhysicsJoint.h
|
||||
Physics/Common/PhysicsJoint.cpp
|
||||
Physics/Common/PhysicsSceneQueries.h
|
||||
Physics/Common/PhysicsSceneQueries.cpp
|
||||
Physics/Common/PhysicsEvents.h
|
||||
@@ -215,6 +217,8 @@ set(FILES
|
||||
Physics/Common/PhysicsSimulatedBodyEvents.cpp
|
||||
Physics/Common/PhysicsTypes.h
|
||||
Physics/Components/SimulatedBodyComponentBus.h
|
||||
Physics/Configuration/JointConfiguration.h
|
||||
Physics/Configuration/JointConfiguration.cpp
|
||||
Physics/Configuration/CollisionConfiguration.h
|
||||
Physics/Configuration/CollisionConfiguration.cpp
|
||||
Physics/Configuration/RigidBodyConfiguration.h
|
||||
@@ -259,8 +263,6 @@ set(FILES
|
||||
Physics/Ragdoll.h
|
||||
Physics/Utils.h
|
||||
Physics/Utils.cpp
|
||||
Physics/Joint.h
|
||||
Physics/Joint.cpp
|
||||
Physics/ClassConverters.cpp
|
||||
Physics/ClassConverters.h
|
||||
Physics/MaterialBus.h
|
||||
|
||||
@@ -493,6 +493,29 @@ namespace AzQtComponents
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CE_MenuItem:
|
||||
{
|
||||
const QMenu* menu = qobject_cast<const QMenu*>(widget);
|
||||
QAction* action = menu->activeAction();
|
||||
if (action)
|
||||
{
|
||||
QMenu* subMenu = action->menu();
|
||||
if (subMenu)
|
||||
{
|
||||
QVariant noHover = subMenu->property("noHover");
|
||||
if (noHover.isValid() && noHover.toBool())
|
||||
{
|
||||
// First draw as standard to get the correct hover background for the complete control.
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
// Now draw the icon as non-hovered so control behaves as designed.
|
||||
QStyleOptionMenuItem myOpt = *qstyleoption_cast<const QStyleOptionMenuItem*>(option);
|
||||
myOpt.state &= ~QStyle::State_Selected;
|
||||
return QProxyStyle::drawControl(element, &myOpt, painter, widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return QProxyStyle::drawControl(element, option, painter, widget);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.0708 0.87087L11.0708 0.87074C10.4286 0.371024 9.61107 0.13517 8.79265 0.213464C7.97422 0.291757 7.21961 0.678004 6.6897 1.28985L5.76756 2.36366C5.63378 2.51944 5.56909 2.72055 5.58771 2.92273C5.60634 3.12492 5.70675 3.31163 5.86686 3.44178C6.02698 3.57194 6.23368 3.63488 6.44149 3.61676C6.6493 3.59864 6.8412 3.50094 6.97498 3.34516L7.89716 2.27122C8.03184 2.11488 8.19736 1.98639 8.38395 1.89334C8.57053 1.8003 8.7744 1.74459 8.98349 1.7295C9.19258 1.71442 9.40266 1.74027 9.60131 1.80552C9.79996 1.87078 9.98315 1.97411 10.1401 2.10942C10.4422 2.38256 10.6244 2.75851 10.6488 3.15904C10.6732 3.55957 10.5379 3.95383 10.2711 4.25978L8.35381 6.49309L8.33616 6.51209C8.23375 6.62767 8.11374 6.72729 7.98031 6.80749C7.67189 6.99364 7.30661 7.06983 6.94686 7.02305C6.58711 6.97626 6.25522 6.8094 6.00789 6.55097C5.86556 6.40288 5.66865 6.31578 5.46039 6.30879C5.25213 6.30179 5.04952 6.37546 4.89703 6.51365C4.74453 6.65183 4.65462 6.84323 4.64701 7.04584C4.6394 7.24845 4.71472 7.44572 4.85645 7.59436C5.21222 7.96578 5.65746 8.24515 6.15198 8.40726C6.6465 8.56937 7.17473 8.60911 7.68898 8.52289C7.84983 8.49539 8.00828 8.45599 8.16298 8.40505C8.70939 8.22568 9.19408 7.90261 9.56335 7.47165L11.4758 5.24457C11.7478 4.92529 11.9523 4.55683 12.0773 4.16038C12.2024 3.76394 12.2457 3.34735 12.2046 2.93457C12.1671 2.53429 12.0475 2.1454 11.8527 1.79092C11.658 1.43644 11.3921 1.12358 11.0708 0.87087Z" fill="white"/>
|
||||
<path d="M5.40958 9.14055L4.58546 10.1003C4.32342 10.4101 3.94867 10.6097 3.53919 10.6576C3.12972 10.7054 2.71706 10.5977 2.3871 10.357C2.22234 10.2309 2.08525 10.0738 1.98392 9.89526C1.8826 9.71668 1.81911 9.52014 1.79719 9.31727C1.77528 9.1144 1.79539 8.90932 1.85634 8.71414C1.91729 8.51896 2.01784 8.33765 2.15204 8.18093L4.10231 5.90975L4.11666 5.89415C4.21908 5.77861 4.3391 5.67903 4.47254 5.59887C4.75216 5.42921 5.07976 5.34988 5.4085 5.37222C5.73725 5.39457 6.05033 5.51745 6.30299 5.72329C6.3635 5.77246 6.42015 5.82595 6.47246 5.88333C6.54738 5.9658 6.63971 6.03156 6.74316 6.07611C6.84661 6.12066 6.95872 6.14295 7.07184 6.14146C7.18361 6.13992 7.29372 6.11492 7.39465 6.06817C7.49558 6.02143 7.58495 5.95403 7.65666 5.8706L7.66607 5.85958C7.78641 5.72083 7.85132 5.54454 7.8489 5.36301C7.84647 5.18148 7.77687 5.00689 7.65286 4.87124C7.35341 4.54132 6.98422 4.27825 6.57057 4.10003C6.15692 3.92182 5.70858 3.83266 5.25623 3.83866C4.80388 3.84467 4.35821 3.94569 3.94971 4.13482C3.54122 4.32395 3.17954 4.59672 2.88945 4.93446L0.944626 7.19943C0.420065 7.81564 0.163643 8.60683 0.230025 9.40433C0.296406 10.2018 0.68034 10.9426 1.29998 11.4686C1.61272 11.7312 1.97644 11.9301 2.3696 12.0535C2.76277 12.1769 3.17738 12.2223 3.5889 12.187C3.687 12.1793 3.78434 12.1672 3.88093 12.1507C4.62877 12.0232 5.30663 11.6437 5.79562 11.0786L6.617 10.1221C6.75077 9.96628 6.81547 9.76517 6.79684 9.56299C6.77822 9.3608 6.6778 9.17409 6.51769 9.04394C6.35758 8.91378 6.15088 8.85084 5.94306 8.86896C5.73525 8.88708 5.54335 8.98477 5.40957 9.14055H5.40958Z" fill="white"/>
|
||||
<path d="M11.0708 0.87087L11.0708 0.87074C10.4286 0.371024 9.61107 0.13517 8.79265 0.213464C7.97422 0.291757 7.21961 0.678004 6.6897 1.28985L5.76756 2.36366C5.63378 2.51944 5.56909 2.72055 5.58771 2.92273C5.60634 3.12492 5.70675 3.31163 5.86686 3.44178C6.02698 3.57194 6.23368 3.63488 6.44149 3.61676C6.6493 3.59864 6.8412 3.50094 6.97498 3.34516L7.89716 2.27122C8.03184 2.11488 8.19736 1.98639 8.38395 1.89334C8.57053 1.8003 8.7744 1.74459 8.98349 1.7295C9.19258 1.71442 9.40266 1.74027 9.60131 1.80552C9.79996 1.87078 9.98315 1.97411 10.1401 2.10942C10.4422 2.38256 10.6244 2.75851 10.6488 3.15904C10.6732 3.55957 10.5379 3.95383 10.2711 4.25978L8.35381 6.49309L8.33616 6.51209C8.23375 6.62767 8.11374 6.72729 7.98031 6.80749C7.67189 6.99364 7.30661 7.06983 6.94686 7.02305C6.58711 6.97626 6.25522 6.8094 6.00789 6.55097C5.86556 6.40288 5.66865 6.31578 5.46039 6.30879C5.25213 6.30179 5.04952 6.37546 4.89703 6.51365C4.74453 6.65183 4.65462 6.84323 4.64701 7.04584C4.6394 7.24845 4.71472 7.44572 4.85645 7.59436C5.21222 7.96578 5.65746 8.24515 6.15198 8.40726C6.6465 8.56937 7.17473 8.60911 7.68898 8.52289C7.84983 8.49539 8.00828 8.45599 8.16298 8.40505C8.70939 8.22568 9.19408 7.90261 9.56335 7.47165L11.4758 5.24457C11.7478 4.92529 11.9523 4.55683 12.0773 4.16038C12.2024 3.76394 12.2457 3.34735 12.2046 2.93457C12.1671 2.53429 12.0475 2.1454 11.8527 1.79092C11.658 1.43644 11.3921 1.12358 11.0708 0.87087Z" fill="#3F3F3F"/>
|
||||
<path d="M5.40958 9.14055L4.58546 10.1003C4.32342 10.4101 3.94867 10.6097 3.53919 10.6576C3.12972 10.7054 2.71706 10.5977 2.3871 10.357C2.22234 10.2309 2.08525 10.0738 1.98392 9.89526C1.8826 9.71668 1.81911 9.52014 1.79719 9.31727C1.77528 9.1144 1.79539 8.90932 1.85634 8.71414C1.91729 8.51896 2.01784 8.33765 2.15204 8.18093L4.10231 5.90975L4.11666 5.89415C4.21908 5.77861 4.3391 5.67903 4.47254 5.59887C4.75216 5.42921 5.07976 5.34988 5.4085 5.37222C5.73725 5.39457 6.05033 5.51745 6.30299 5.72329C6.3635 5.77246 6.42015 5.82595 6.47246 5.88333C6.54738 5.9658 6.63971 6.03156 6.74316 6.07611C6.84661 6.12066 6.95872 6.14295 7.07184 6.14146C7.18361 6.13992 7.29372 6.11492 7.39465 6.06817C7.49558 6.02143 7.58495 5.95403 7.65666 5.8706L7.66607 5.85958C7.78641 5.72083 7.85132 5.54454 7.8489 5.36301C7.84647 5.18148 7.77687 5.00689 7.65286 4.87124C7.35341 4.54132 6.98422 4.27825 6.57057 4.10003C6.15692 3.92182 5.70858 3.83266 5.25623 3.83866C4.80388 3.84467 4.35821 3.94569 3.94971 4.13482C3.54122 4.32395 3.17954 4.59672 2.88945 4.93446L0.944626 7.19943C0.420065 7.81564 0.163643 8.60683 0.230025 9.40433C0.296406 10.2018 0.68034 10.9426 1.29998 11.4686C1.61272 11.7312 1.97644 11.9301 2.3696 12.0535C2.76277 12.1769 3.17738 12.2223 3.5889 12.187C3.687 12.1793 3.78434 12.1672 3.88093 12.1507C4.62877 12.0232 5.30663 11.6437 5.79562 11.0786L6.617 10.1221C6.75077 9.96628 6.81547 9.76517 6.79684 9.56299C6.77822 9.3608 6.6778 9.17409 6.51769 9.04394C6.35758 8.91378 6.15088 8.85084 5.94306 8.86896C5.73525 8.88708 5.54335 8.98477 5.40957 9.14055H5.40958Z" fill="#3F3F3F"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
@@ -210,6 +210,15 @@ namespace AzToolsFramework
|
||||
//! Type to inherit to implement ViewportInteractionRequests.
|
||||
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! An interface to notify when changes to viewport settings have happened.
|
||||
class ViewportSettingNotifications
|
||||
{
|
||||
public:
|
||||
virtual void OnGridSnappingChanged(bool enabled) = 0;
|
||||
};
|
||||
|
||||
using ViewportSettingsNotificationBus = AZ::EBus<ViewportSettingNotifications, ViewportEBusTraits>;
|
||||
|
||||
//! Requests to freeze the Viewport Input
|
||||
//! Added to prevent a bug with the legacy CryEngine Viewport code that would
|
||||
//! keep doing raycast tests even when no level is loaded, causing a crash.
|
||||
|
||||
+18
-1
@@ -489,6 +489,16 @@ namespace AzToolsFramework
|
||||
return buttonId;
|
||||
}
|
||||
|
||||
void SnappingCluster::TrySetVisible(const bool visible)
|
||||
{
|
||||
bool snapping = false;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
|
||||
|
||||
// show snapping viewport ui only if there are entities selected and snapping is enabled
|
||||
SetViewportUiClusterVisible(m_clusterId, visible && snapping);
|
||||
}
|
||||
|
||||
// return either center or entity pivot
|
||||
static AZ::Vector3 CalculatePivotTranslation(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
|
||||
{
|
||||
@@ -1035,6 +1045,7 @@ namespace AzToolsFramework
|
||||
EditorEntityLockComponentNotificationBus::Router::BusRouterConnect();
|
||||
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId);
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusConnect(ViewportUi::DefaultViewportId);
|
||||
|
||||
CreateTransformModeSelectionCluster();
|
||||
CreateSpaceSelectionCluster();
|
||||
@@ -1058,6 +1069,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_pivotOverrideFrame.Reset();
|
||||
|
||||
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect();
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusDisconnect();
|
||||
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
|
||||
@@ -3253,7 +3265,7 @@ namespace AzToolsFramework
|
||||
m_didSetSelectedEntities = false;
|
||||
}
|
||||
|
||||
SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, m_viewportUiVisible && !m_selectedEntityIds.empty());
|
||||
m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty());
|
||||
|
||||
RegenerateManipulators();
|
||||
}
|
||||
@@ -3717,6 +3729,11 @@ namespace AzToolsFramework
|
||||
SetAllViewportUiVisible(true);
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelection::OnGridSnappingChanged([[maybe_unused]] const bool enabled)
|
||||
{
|
||||
m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty());
|
||||
}
|
||||
|
||||
namespace ETCS
|
||||
{
|
||||
// little raii wrapper to switch a value from true to false and back
|
||||
|
||||
+7
@@ -131,6 +131,9 @@ namespace AzToolsFramework
|
||||
SnappingCluster(const SnappingCluster&) = delete;
|
||||
SnappingCluster& operator=(const SnappingCluster&) = delete;
|
||||
|
||||
//! Attempt to show the snapping cluster (will only succeed if snapping is enabled).
|
||||
void TrySetVisible(bool visible);
|
||||
|
||||
ViewportUi::ClusterId m_clusterId; //!< The cluster id for all snapping buttons.
|
||||
ViewportUi::ButtonId m_snapToWorldButtonId; //!< The button id for snapping all axes to the world.
|
||||
AZ::Event<ViewportUi::ButtonId>::Handler m_snappingHandler; //!< Callback for when a snapping cluster button is pressed.
|
||||
@@ -151,6 +154,7 @@ namespace AzToolsFramework
|
||||
, private EditorEntityLockComponentNotificationBus::Router
|
||||
, private EditorManipulatorCommandUndoRedoRequestBus::Handler
|
||||
, private AZ::TransformNotificationBus::MultiHandler
|
||||
, private ViewportInteraction::ViewportSettingsNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
@@ -289,6 +293,9 @@ namespace AzToolsFramework
|
||||
void OnStartPlayInEditor() override;
|
||||
void OnStopPlayInEditor() override;
|
||||
|
||||
// ViewportSettingsNotificationBus overrides ...
|
||||
void OnGridSnappingChanged(bool enabled) override;
|
||||
|
||||
// Helpers to safely interact with the TransformBus (requests).
|
||||
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation);
|
||||
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
|
||||
namespace SandboxEditor
|
||||
@@ -56,6 +57,39 @@ namespace SandboxEditor
|
||||
return value;
|
||||
}
|
||||
|
||||
struct EditorViewportSettingsCallbacksImpl : public EditorViewportSettingsCallbacks
|
||||
{
|
||||
EditorViewportSettingsCallbacksImpl()
|
||||
{
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
using AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual;
|
||||
|
||||
m_notifyEventHandler = registry->RegisterNotifier(
|
||||
[this](const AZStd::string_view path, [[maybe_unused]] const AZ::SettingsRegistryInterface::Type type)
|
||||
{
|
||||
if (IsPathAncestorDescendantOrEqual(GridSnappingSetting, path))
|
||||
{
|
||||
m_gridSnappingChanged.Signal(GridSnappingEnabled());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) override
|
||||
{
|
||||
handler.Connect(m_gridSnappingChanged);
|
||||
}
|
||||
|
||||
GridSnappingChangedEvent m_gridSnappingChanged;
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyEventHandler;
|
||||
};
|
||||
|
||||
AZStd::unique_ptr<EditorViewportSettingsCallbacks> CreateEditorViewportSettingsCallbacks()
|
||||
{
|
||||
return AZStd::make_unique<EditorViewportSettingsCallbacksImpl>();
|
||||
}
|
||||
|
||||
bool GridSnappingEnabled()
|
||||
{
|
||||
return GetRegistry(GridSnappingSetting, false);
|
||||
|
||||
@@ -14,8 +14,27 @@
|
||||
|
||||
#include <SandboxAPI.h>
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace SandboxEditor
|
||||
{
|
||||
using GridSnappingChangedEvent = AZ::Event<bool>;
|
||||
|
||||
//! Set callbacks to listen for editor settings change events.
|
||||
class EditorViewportSettingsCallbacks
|
||||
{
|
||||
public:
|
||||
virtual ~EditorViewportSettingsCallbacks() = default;
|
||||
|
||||
virtual void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) = 0;
|
||||
};
|
||||
|
||||
//! Create an instance of EditorViewportSettingsCallbacks
|
||||
//! Note: EditorViewportSettingsCallbacks is implemented in EditorViewportSettings.cpp - a change
|
||||
//! event will fire when a value in the settings registry (editorpreferences.setreg) is modified.
|
||||
SANDBOX_API AZStd::unique_ptr<EditorViewportSettingsCallbacks> CreateEditorViewportSettingsCallbacks();
|
||||
|
||||
SANDBOX_API bool GridSnappingEnabled();
|
||||
SANDBOX_API void SetGridSnapping(bool enabled);
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@
|
||||
#include "EditorPreferencesPageGeneral.h"
|
||||
#include "ViewportManipulatorController.h"
|
||||
#include "LegacyViewportCameraController.h"
|
||||
#include "EditorViewportSettings.h"
|
||||
|
||||
#include "ViewPane.h"
|
||||
#include "CustomResolutionDlg.h"
|
||||
@@ -1450,6 +1449,17 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
{
|
||||
SetAsActiveViewport();
|
||||
}
|
||||
|
||||
m_editorViewportSettingsCallbacks = SandboxEditor::CreateEditorViewportSettingsCallbacks();
|
||||
|
||||
m_gridSnappingHandler = SandboxEditor::GridSnappingChangedEvent::Handler(
|
||||
[id](const bool snapping)
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Event(
|
||||
id, &AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Events::OnGridSnappingChanged, snapping);
|
||||
});
|
||||
|
||||
m_editorViewportSettingsCallbacks->SetGridSnappingChangedEvent(m_gridSnappingHandler);
|
||||
}
|
||||
|
||||
void EditorViewportWidget::ConnectViewportInteractionRequestBus()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "Objects/DisplayContext.h"
|
||||
#include "Undo/Undo.h"
|
||||
#include "Util/PredefinedAspectRatios.h"
|
||||
#include "EditorViewportSettings.h"
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
@@ -571,6 +572,9 @@ private:
|
||||
|
||||
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
|
||||
|
||||
SandboxEditor::GridSnappingChangedEvent::Handler m_gridSnappingHandler;
|
||||
AZStd::unique_ptr<SandboxEditor::EditorViewportSettingsCallbacks> m_editorViewportSettingsCallbacks;
|
||||
|
||||
QSet<int> m_keyDown;
|
||||
|
||||
bool m_freezeViewportInput = false;
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace AWSCore
|
||||
void InitializeAWSDocActions();
|
||||
void InitializeAWSGlobalDocsSubMenu();
|
||||
void InitializeAWSFeatureGemActions();
|
||||
void AddSpaceForIcon(QMenu* menu);
|
||||
|
||||
// AWSCoreEditorRequestBus interface implementation
|
||||
void SetAWSClientAuthEnabled() override;
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
|
||||
static constexpr int IconSize = 16;
|
||||
|
||||
AWSCoreEditorMenu::AWSCoreEditorMenu(const QString& text)
|
||||
: QMenu(text)
|
||||
, m_resourceMappingToolWatcher(nullptr)
|
||||
@@ -43,6 +46,7 @@ namespace AWSCore
|
||||
InitializeResourceMappingToolAction();
|
||||
this->addSeparator();
|
||||
InitializeAWSFeatureGemActions();
|
||||
AddSpaceForIcon(this);
|
||||
|
||||
AWSCoreEditorRequestBus::Handler::BusConnect();
|
||||
}
|
||||
@@ -136,6 +140,8 @@ namespace AWSCore
|
||||
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndScriptCanvasActionText, AWSAndScriptCanvasUrl, ":/Notifications/link.svg"));
|
||||
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndComponentsActionText, AWSAndComponentsUrl, ":/Notifications/link.svg"));
|
||||
globalDocsMenu->addAction(AddExternalLinkAction(CallAWSResourcesActionText, CallAWSResourcesUrl, ":/Notifications/link.svg"));
|
||||
|
||||
AddSpaceForIcon(globalDocsMenu);
|
||||
}
|
||||
|
||||
void AWSCoreEditorMenu::InitializeAWSFeatureGemActions()
|
||||
@@ -170,6 +176,8 @@ namespace AWSCore
|
||||
AWSClientAuthPlatformSpecificActionText, AWSClientAuthPlatformSpecificUrl, ":/Notifications/link.svg"));
|
||||
subMenu->addAction(AddExternalLinkAction(
|
||||
AWSClientAuthAPIReferenceActionText, AWSClientAuthAPIReferenceUrl, ":/Notifications/link.svg"));
|
||||
|
||||
AddSpaceForIcon(subMenu);
|
||||
}
|
||||
|
||||
void AWSCoreEditorMenu::SetAWSMetricsEnabled()
|
||||
@@ -197,7 +205,9 @@ namespace AWSCore
|
||||
[configFilePath](){
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(configFilePath.c_str()));
|
||||
});
|
||||
|
||||
subMenu->addAction(settingsAction);
|
||||
AddSpaceForIcon(subMenu);
|
||||
}
|
||||
|
||||
QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText)
|
||||
@@ -209,6 +219,7 @@ namespace AWSCore
|
||||
{
|
||||
QMenu* subMenu = new QMenu(QObject::tr(menuText.c_str()));
|
||||
subMenu->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
|
||||
subMenu->setProperty("noHover", true);
|
||||
this->insertMenu(*itr, subMenu);
|
||||
this->removeAction(*itr);
|
||||
return subMenu;
|
||||
@@ -216,4 +227,11 @@ namespace AWSCore
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AWSCoreEditorMenu::AddSpaceForIcon(QMenu *menu)
|
||||
{
|
||||
QSize size = menu->sizeHint();
|
||||
size.setWidth(size.width() + IconSize);
|
||||
menu->setFixedSize(size);
|
||||
}
|
||||
} // namespace AWSCore
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
from genericpath import isdir
|
||||
from argparse import ArgumentParser
|
||||
import json
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
# this allows us to add additional data if necessary, e.g. frame_test_timestamps.json
|
||||
is_timestamp_file = lambda file: file.name.startswith('frame') and file.name.endswith('_timestamps.json')
|
||||
ns_to_ms = lambda time: time / 1e6
|
||||
|
||||
def main(logs_dir):
|
||||
count = 0
|
||||
total = 0
|
||||
maximum = 0
|
||||
|
||||
print(f'Analyzing frame timestamp logs in {logs_dir}')
|
||||
|
||||
# go through files in alphabetical order (remove sorted() if not necessary)
|
||||
for file in sorted(logs_dir.iterdir(), key=lambda file: len(file.name)):
|
||||
if file.is_dir() or not is_timestamp_file(file):
|
||||
continue
|
||||
|
||||
data = json.loads(file.read_text())
|
||||
entries = data['ClassData']['timestampEntries']
|
||||
timestamps = [entry['timestampResultInNanoseconds'] for entry in entries]
|
||||
|
||||
frame_time = sum(timestamps)
|
||||
frame_name = file.name.split('_')[0]
|
||||
print(f'- Total time for frame {frame_name}: {ns_to_ms(frame_time)}ms')
|
||||
|
||||
maximum = max(maximum, frame_time)
|
||||
total += frame_time
|
||||
count += 1
|
||||
|
||||
if count < 1:
|
||||
print(f'No logs were found in {base_dir}')
|
||||
exit(1)
|
||||
|
||||
print(f'Avg. time across {count} frames: {ns_to_ms(total / count)}ms')
|
||||
print(f'Max frame time: {ns_to_ms(maximum)}ms')
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = ArgumentParser(description='Gathers statistics from a group of pass timestamp logs')
|
||||
parser.add_argument('path', help='Path to the directory containing the pass timestamp logs')
|
||||
args = parser.parse_args()
|
||||
|
||||
base_dir = Path(args.path)
|
||||
if not base_dir.exists():
|
||||
raise FileNotFoundError('Invalid path provided')
|
||||
main(base_dir)
|
||||
+7
@@ -96,6 +96,13 @@ namespace AZ
|
||||
|
||||
RPI::AttachmentReadback::CallbackFunction readbackCallback = [&](const RPI::AttachmentReadback::ReadbackResult& result)
|
||||
{
|
||||
if (!result.m_dataBuffer)
|
||||
{
|
||||
AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event(
|
||||
m_context->GetData()->m_thumbnailKeyRendered,
|
||||
&AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender);
|
||||
return;
|
||||
}
|
||||
uchar* data = result.m_dataBuffer.get()->data();
|
||||
QImage image(
|
||||
data, result.m_imageDescriptor.m_size.m_width, result.m_imageDescriptor.m_size.m_height, QImage::Format_RGBA8888);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Physics/RigidBodyBus.h>
|
||||
#include <AzFramework/Physics/Shape.h>
|
||||
#include <AzFramework/Physics/SystemBus.h>
|
||||
@@ -221,23 +220,6 @@ namespace Blast
|
||||
AZStd::vector<AZStd::shared_ptr<Physics::Material>>(const Physics::MaterialSelection&));
|
||||
MOCK_METHOD2(
|
||||
UpdateMaterialSelection, bool(const Physics::ShapeConfiguration&, Physics::ColliderConfiguration&));
|
||||
MOCK_METHOD0(GetSupportedJointTypes, AZStd::vector<AZ::TypeId>());
|
||||
MOCK_METHOD1(CreateJointLimitConfiguration, AZStd::shared_ptr<Physics::JointLimitConfiguration>(AZ::TypeId));
|
||||
MOCK_METHOD3(
|
||||
CreateJoint,
|
||||
AZStd::shared_ptr<Physics::Joint>(
|
||||
const AZStd::shared_ptr<Physics::JointLimitConfiguration>&, AzPhysics::SimulatedBody*, AzPhysics::SimulatedBody*));
|
||||
MOCK_METHOD10(
|
||||
GenerateJointLimitVisualizationData,
|
||||
void(
|
||||
const Physics::JointLimitConfiguration&, const AZ::Quaternion&, const AZ::Quaternion&, float, AZ::u32,
|
||||
AZ::u32, AZStd::vector<AZ::Vector3>&, AZStd::vector<AZ::u32>&, AZStd::vector<AZ::Vector3>&,
|
||||
AZStd::vector<bool>&));
|
||||
MOCK_METHOD5(
|
||||
ComputeInitialJointLimitConfiguration,
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration>(
|
||||
const AZ::TypeId&, const AZ::Quaternion&, const AZ::Quaternion&, const AZ::Vector3&,
|
||||
const AZStd::vector<AZ::Quaternion>&));
|
||||
MOCK_METHOD3(CookConvexMeshToFile, bool(const AZStd::string&, const AZ::Vector3*, AZ::u32));
|
||||
MOCK_METHOD3(CookConvexMeshToMemory, bool(const AZ::Vector3*, AZ::u32, AZStd::vector<AZ::u8>&));
|
||||
MOCK_METHOD5(
|
||||
|
||||
@@ -71,12 +71,7 @@ namespace EMotionFX
|
||||
newNodeConfig.m_debugName = jointName;
|
||||
|
||||
// Create joint limit on default.
|
||||
AZStd::vector<AZ::TypeId> supportedJointLimitTypes;
|
||||
Physics::SystemRequestBus::BroadcastResult(supportedJointLimitTypes, &Physics::SystemRequests::GetSupportedJointTypes);
|
||||
if (!supportedJointLimitTypes.empty())
|
||||
{
|
||||
newNodeConfig.m_jointLimit = CommandRagdollHelpers::CreateJointLimitByType(supportedJointLimitTypes[0], skeleton, joint);
|
||||
}
|
||||
newNodeConfig.m_jointConfig = CommandRagdollHelpers::CreateJointLimitByType(AzPhysics::JointType::D6Joint, skeleton, joint);
|
||||
|
||||
if (index)
|
||||
{
|
||||
@@ -91,8 +86,8 @@ namespace EMotionFX
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration> CommandRagdollHelpers::CreateJointLimitByType(
|
||||
const AZ::TypeId& typeId, const Skeleton* skeleton, const Node* node)
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration> CommandRagdollHelpers::CreateJointLimitByType(
|
||||
AzPhysics::JointType jointType, const Skeleton* skeleton, const Node* node)
|
||||
{
|
||||
const Pose* bindPose = skeleton->GetBindPose();
|
||||
const Transform& nodeBindTransform = bindPose->GetModelSpaceTransform(node->GetNodeIndex());
|
||||
@@ -105,12 +100,20 @@ namespace EMotionFX
|
||||
AZ::Vector3 boneDirection = GetBoneDirection(skeleton, node);
|
||||
AZStd::vector<AZ::Quaternion> exampleRotationsLocal;
|
||||
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration> jointLimitConfig =
|
||||
AZ::Interface<Physics::System>::Get()->ComputeInitialJointLimitConfiguration(
|
||||
typeId, parentBindRotationWorld, nodeBindRotationWorld, boneDirection, exampleRotationsLocal);
|
||||
if (auto* jointHelpers = AZ::Interface<AzPhysics::JointHelpersInterface>::Get())
|
||||
{
|
||||
if (AZStd::optional<const AZ::TypeId> jointTypeId = jointHelpers->GetSupportedJointTypeId(jointType);
|
||||
jointTypeId.has_value())
|
||||
{
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration> jointLimitConfig = jointHelpers->ComputeInitialJointLimitConfiguration(
|
||||
*jointTypeId, parentBindRotationWorld, nodeBindRotationWorld, boneDirection, exampleRotationsLocal);
|
||||
|
||||
AZ_Assert(jointLimitConfig, "Could not create joint limit configuration with type '%s'.", typeId.ToString<AZStd::string>().c_str());
|
||||
return jointLimitConfig;
|
||||
AZ_Assert(jointLimitConfig, "Could not create joint limit configuration.");
|
||||
return jointLimitConfig;
|
||||
}
|
||||
}
|
||||
AZ_Assert(false, "Could not create joint limit configuration.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CommandRagdollHelpers::AddJointsToRagdoll(AZ::u32 actorId, const AZStd::vector<AZStd::string>& jointNames,
|
||||
@@ -532,7 +535,7 @@ namespace EMotionFX
|
||||
if (m_serializedJointLimits)
|
||||
{
|
||||
AZ::Outcome<AZStd::string> oldSerializedJointLimits = SerializeJointLimits(nodeConfig);
|
||||
success |= MCore::ReflectionSerializer::DeserializeMembers(nodeConfig->m_jointLimit.get(), m_serializedJointLimits.value());
|
||||
success |= MCore::ReflectionSerializer::DeserializeMembers(nodeConfig->m_jointConfig.get(), m_serializedJointLimits.value());
|
||||
if (success && oldSerializedJointLimits.IsSuccess())
|
||||
{
|
||||
m_oldSerializedJointLimits = oldSerializedJointLimits.GetValue();
|
||||
@@ -565,7 +568,7 @@ namespace EMotionFX
|
||||
AZ::Outcome<AZStd::string> CommandAdjustRagdollJoint::SerializeJointLimits(const Physics::RagdollNodeConfiguration* ragdollNodeConfig)
|
||||
{
|
||||
return MCore::ReflectionSerializer::SerializeMembersExcept(
|
||||
ragdollNodeConfig->m_jointLimit.get(),
|
||||
ragdollNodeConfig->m_jointConfig.get(),
|
||||
{"ParentLocalRotation", "ParentLocalPosition", "ChildLocalRotation", "ChildLocalPosition", }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ namespace EMotionFX
|
||||
Physics::RagdollConfiguration& ragdollConfig, const AZStd::optional<size_t>& index,
|
||||
AZStd::string& outResult);
|
||||
|
||||
static AZStd::unique_ptr<Physics::JointLimitConfiguration> CreateJointLimitByType(const AZ::TypeId& typeId,
|
||||
const Skeleton* skeleton, const Node* node);
|
||||
static AZStd::unique_ptr<AzPhysics::JointConfiguration> CreateJointLimitByType(
|
||||
AzPhysics::JointType jointType, const Skeleton* skeleton, const Node* node);
|
||||
|
||||
static void AddJointsToRagdoll(AZ::u32 actorId, const AZStd::vector<AZStd::string>& jointNames,
|
||||
MCore::CommandGroup* commandGroup = nullptr, bool executeInsideCommand = false, bool addDefaultCollider = true);
|
||||
|
||||
@@ -90,12 +90,15 @@ namespace EMotionFX
|
||||
|
||||
if (serializeContext)
|
||||
{
|
||||
AZStd::vector<AZ::TypeId> supportedJointLimitTypes;
|
||||
Physics::SystemRequestBus::BroadcastResult(supportedJointLimitTypes, &Physics::SystemRequests::GetSupportedJointTypes);
|
||||
for (const AZ::TypeId& jointLimitType : supportedJointLimitTypes)
|
||||
//D6 joint is the only currently supported joint for ragdoll
|
||||
if (auto* jointHelpers = AZ::Interface<AzPhysics::JointHelpersInterface>::Get())
|
||||
{
|
||||
const char* jointLimitName = serializeContext->FindClassData(jointLimitType)->m_editData->m_name;
|
||||
m_typeComboBox->addItem(jointLimitName, jointLimitType.ToString<AZStd::string>().c_str());
|
||||
if (AZStd::optional<const AZ::TypeId> d6jointTypeId = jointHelpers->GetSupportedJointTypeId(AzPhysics::JointType::D6Joint);
|
||||
d6jointTypeId.has_value())
|
||||
{
|
||||
const char* jointLimitName = serializeContext->FindClassData(*d6jointTypeId)->m_editData->m_name;
|
||||
m_typeComboBox->addItem(jointLimitName, (*d6jointTypeId).ToString<AZStd::string>().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Reflected property editor for joint limit
|
||||
@@ -134,7 +137,7 @@ namespace EMotionFX
|
||||
Physics::RagdollNodeConfiguration* ragdollNodeConfig = GetRagdollNodeConfig();
|
||||
if (ragdollNodeConfig)
|
||||
{
|
||||
Physics::JointLimitConfiguration* jointLimitConfig = ragdollNodeConfig->m_jointLimit.get();
|
||||
AzPhysics::JointConfiguration* jointLimitConfig = ragdollNodeConfig->m_jointConfig.get();
|
||||
if (jointLimitConfig)
|
||||
{
|
||||
const AZ::TypeId& jointTypeId = jointLimitConfig->RTTI_GetType();
|
||||
@@ -262,13 +265,14 @@ namespace EMotionFX
|
||||
{
|
||||
if (type.IsNull())
|
||||
{
|
||||
ragdollNodeConfig->m_jointLimit = nullptr;
|
||||
ragdollNodeConfig->m_jointConfig = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Node* node = m_nodeIndex.data(SkeletonModel::ROLE_POINTER).value<Node*>();
|
||||
const Skeleton* skeleton = m_nodeIndex.data(SkeletonModel::ROLE_ACTOR_POINTER).value<Actor*>()->GetSkeleton();
|
||||
ragdollNodeConfig->m_jointLimit = CommandRagdollHelpers::CreateJointLimitByType(type, skeleton, node);
|
||||
ragdollNodeConfig->m_jointConfig =
|
||||
CommandRagdollHelpers::CreateJointLimitByType(AzPhysics::JointType::D6Joint, skeleton, node);
|
||||
}
|
||||
|
||||
Update();
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Physics/Ragdoll.h>
|
||||
#include <AzQtComponents/Components/Widgets/Card.h>
|
||||
#include <QModelIndex>
|
||||
|
||||
@@ -514,7 +514,7 @@ namespace EMotionFX
|
||||
|
||||
if (renderJointLimits && jointSelected)
|
||||
{
|
||||
const AZStd::shared_ptr<Physics::JointLimitConfiguration>& jointLimitConfig = ragdollNode.m_jointLimit;
|
||||
const AZStd::shared_ptr<AzPhysics::JointConfiguration>& jointLimitConfig = ragdollNode.m_jointConfig;
|
||||
if (jointLimitConfig)
|
||||
{
|
||||
const Node* ragdollParentNode = physicsSetup->FindRagdollParentNode(joint);
|
||||
@@ -528,7 +528,8 @@ namespace EMotionFX
|
||||
}
|
||||
}
|
||||
|
||||
void RagdollNodeInspectorPlugin::RenderJointLimit(const Physics::JointLimitConfiguration& configuration,
|
||||
void RagdollNodeInspectorPlugin::RenderJointLimit(
|
||||
const AzPhysics::JointConfiguration& configuration,
|
||||
const ActorInstance* actorInstance,
|
||||
const Node* node,
|
||||
const Node* parentNode,
|
||||
@@ -549,9 +550,12 @@ namespace EMotionFX
|
||||
m_indexBuffer.clear();
|
||||
m_lineBuffer.clear();
|
||||
m_lineValidityBuffer.clear();
|
||||
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::GenerateJointLimitVisualizationData,
|
||||
configuration, parentOrientation, childOrientation, s_scale, s_angularSubdivisions, s_radialSubdivisions,
|
||||
m_vertexBuffer, m_indexBuffer, m_lineBuffer, m_lineValidityBuffer);
|
||||
if(auto* jointHelpers = AZ::Interface<AzPhysics::JointHelpersInterface>::Get())
|
||||
{
|
||||
jointHelpers->GenerateJointLimitVisualizationData(
|
||||
configuration, parentOrientation, childOrientation, s_scale, s_angularSubdivisions, s_radialSubdivisions, m_vertexBuffer,
|
||||
m_indexBuffer, m_lineBuffer, m_lineValidityBuffer);
|
||||
}
|
||||
|
||||
Transform jointModelSpaceTransform = currentPose->GetModelSpaceTransform(parentNodeIndex);
|
||||
jointModelSpaceTransform.mPosition = currentPose->GetModelSpaceTransform(nodeIndex).mPosition;
|
||||
@@ -572,7 +576,8 @@ namespace EMotionFX
|
||||
}
|
||||
}
|
||||
|
||||
void RagdollNodeInspectorPlugin::RenderJointFrame(const Physics::JointLimitConfiguration& configuration,
|
||||
void RagdollNodeInspectorPlugin::RenderJointFrame(
|
||||
const AzPhysics::JointConfiguration& configuration,
|
||||
const ActorInstance* actorInstance,
|
||||
const Node* node,
|
||||
const Node* parentNode,
|
||||
|
||||
@@ -60,14 +60,16 @@ namespace EMotionFX
|
||||
|
||||
void Render(EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo) override;
|
||||
void RenderRagdoll(ActorInstance* actorInstance, bool renderColliders, bool renderJointLimits, EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo);
|
||||
void RenderJointLimit(const Physics::JointLimitConfiguration& jointConfiguration,
|
||||
void RenderJointLimit(
|
||||
const AzPhysics::JointConfiguration& jointConfiguration,
|
||||
const ActorInstance* actorInstance,
|
||||
const Node* node,
|
||||
const Node* parentNode,
|
||||
EMStudio::RenderPlugin* renderPlugin,
|
||||
EMStudio::EMStudioPlugin::RenderInfo* renderInfo,
|
||||
const MCore::RGBAColor& color);
|
||||
void RenderJointFrame(const Physics::JointLimitConfiguration& jointConfiguration,
|
||||
void RenderJointFrame(
|
||||
const AzPhysics::JointConfiguration& jointConfiguration,
|
||||
const ActorInstance* actorInstance,
|
||||
const Node* node,
|
||||
const Node* parentNode,
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace EMotionFX
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<D6JointLimitConfiguration, Physics::JointLimitConfiguration>()
|
||||
serializeContext->Class<D6JointLimitConfiguration, AzPhysics::JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("SwingLimitY", &D6JointLimitConfiguration::m_swingLimitY)
|
||||
->Field("SwingLimitZ", &D6JointLimitConfiguration::m_swingLimitZ)
|
||||
|
||||
@@ -12,23 +12,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
// Add so that RagdollNodeInspectorPlugin::PhysXCharactersGemAvailable() will return the correct value
|
||||
// We duplicated the D6JointLimitConfiguration because it doesn't exist in the test environment.
|
||||
class D6JointLimitConfiguration
|
||||
: public Physics::JointLimitConfiguration
|
||||
: public AzPhysics::JointConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(D6JointLimitConfiguration, AZ::SystemAllocator, 0);
|
||||
// This uses the same uuid as the production D6JointLimitConfiguration.
|
||||
// The Ragdoll UI uses this UUID to see if physx is available.
|
||||
AZ_RTTI(D6JointLimitConfiguration, "{90C5C23D-16C0-4F23-AD50-A190E402388E}", Physics::JointLimitConfiguration);
|
||||
AZ_RTTI(D6JointLimitConfiguration, "{90C5C23D-16C0-4F23-AD50-A190E402388E}", AzPhysics::JointConfiguration);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
const char* GetTypeName() override { return "D6 Joint"; }
|
||||
|
||||
float m_swingLimitY = 45.0f; ///< Maximum angle in degrees from the Y axis of the joint frame.
|
||||
float m_swingLimitZ = 45.0f; ///< Maximum angle in degrees from the Z axis of the joint frame.
|
||||
|
||||
@@ -35,11 +35,6 @@ namespace Physics
|
||||
MOCK_METHOD2(CreateShape, AZStd::shared_ptr<Physics::Shape>(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration));
|
||||
MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject));
|
||||
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration& materialConfiguration));
|
||||
MOCK_METHOD0(GetSupportedJointTypes, AZStd::vector<AZ::TypeId>());
|
||||
MOCK_METHOD1(CreateJointLimitConfiguration, AZStd::shared_ptr<Physics::JointLimitConfiguration>(AZ::TypeId jointType));
|
||||
MOCK_METHOD3(CreateJoint, AZStd::shared_ptr<Physics::Joint>(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration, AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody));
|
||||
MOCK_METHOD10(GenerateJointLimitVisualizationData, void(const Physics::JointLimitConfiguration& configuration, const AZ::Quaternion& parentRotation, const AZ::Quaternion& childRotation, float scale, AZ::u32 angularSubdivisions, AZ::u32 radialSubdivisions, AZStd::vector<AZ::Vector3>& vertexBufferOut, AZStd::vector<AZ::u32>& indexBufferOut, AZStd::vector<AZ::Vector3>& lineBufferOut, AZStd::vector<bool>& lineValidityBufferOut));
|
||||
MOCK_METHOD5(ComputeInitialJointLimitConfiguration, AZStd::unique_ptr<Physics::JointLimitConfiguration>(const AZ::TypeId& jointLimitTypeId, const AZ::Quaternion& parentWorldRotation, const AZ::Quaternion& childWorldRotation, const AZ::Vector3& axis, const AZStd::vector<AZ::Quaternion>& exampleLocalRotations));
|
||||
MOCK_METHOD3(CookConvexMeshToFile, bool(const AZStd::string& filePath, const AZ::Vector3* vertices, AZ::u32 vertexCount));
|
||||
MOCK_METHOD3(CookConvexMeshToMemory, bool(const AZ::Vector3* vertices, AZ::u32 vertexCount, AZStd::vector<AZ::u8>& result));
|
||||
MOCK_METHOD5(CookTriangleMeshToFile, bool(const AZStd::string& filePath, const AZ::Vector3* vertices, AZ::u32 vertexCount, const AZ::u32* indices, AZ::u32 indexCount));
|
||||
@@ -72,6 +67,36 @@ namespace Physics
|
||||
MOCK_CONST_METHOD0(GetDefaultSceneConfiguration, const AzPhysics::SceneConfiguration& ());
|
||||
};
|
||||
|
||||
class MockJointHelpersInterface : AZ::Interface<AzPhysics::JointHelpersInterface>::Registrar
|
||||
{
|
||||
public:
|
||||
MOCK_CONST_METHOD0(GetSupportedJointTypeIds, const AZStd::vector<AZ::TypeId>());
|
||||
MOCK_CONST_METHOD1(GetSupportedJointTypeId, AZStd::optional<const AZ::TypeId>(AzPhysics::JointType typeEnum));
|
||||
|
||||
MOCK_METHOD5(
|
||||
ComputeInitialJointLimitConfiguration,
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration>(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations));
|
||||
|
||||
MOCK_METHOD10(
|
||||
GenerateJointLimitVisualizationData,
|
||||
void(
|
||||
const AzPhysics::JointConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut));
|
||||
};
|
||||
|
||||
//Mocked of the AzPhysics Scene Interface. To keep things simple just mocked functions that have a return value OR required for a test.
|
||||
class MockPhysicsSceneInterface
|
||||
: AZ::Interface<AzPhysics::SceneInterface>::Registrar
|
||||
@@ -97,6 +122,9 @@ namespace Physics
|
||||
void DisableSimulationOfBody(
|
||||
[[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
|
||||
[[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle) override {}
|
||||
void RemoveJoint(
|
||||
[[maybe_unused]]AzPhysics::SceneHandle sceneHandle,
|
||||
[[maybe_unused]] AzPhysics::JointHandle jointHandle) override {}
|
||||
void SuppressCollisionEvents(
|
||||
[[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
|
||||
[[maybe_unused]] const AzPhysics::SimulatedBodyHandle& bodyHandleA,
|
||||
@@ -145,6 +173,9 @@ namespace Physics
|
||||
MOCK_METHOD2(AddSimulatedBodies, AzPhysics::SimulatedBodyHandleList(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SimulatedBodyConfigurationList& simulatedBodyConfigs));
|
||||
MOCK_METHOD2(GetSimulatedBodyFromHandle, AzPhysics::SimulatedBody* (AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle));
|
||||
MOCK_METHOD2(GetSimulatedBodiesFromHandle, AzPhysics::SimulatedBodyList(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SimulatedBodyHandleList& bodyHandles));
|
||||
MOCK_METHOD4(AddJoint, AzPhysics::JointHandle(AzPhysics::SceneHandle sceneHandle, const AzPhysics::JointConfiguration* jointConfig,
|
||||
AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody));
|
||||
MOCK_METHOD2(GetJointFromHandle, AzPhysics::Joint* (AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle bodyHandle));
|
||||
MOCK_CONST_METHOD1(GetGravity, AZ::Vector3(AzPhysics::SceneHandle sceneHandle));
|
||||
MOCK_METHOD2(RegisterSceneSimulationFinishHandler, void(AzPhysics::SceneHandle sceneHandle, AzPhysics::SceneEvents::OnSceneSimulationFinishHandler& handler));
|
||||
MOCK_CONST_METHOD2(GetLegacyBody, AzPhysics::SimulatedBody* (AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle handle));
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzFramework/Physics/Character.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
|
||||
#include <EMotionFX/CommandSystem/Source/ColliderCommands.h>
|
||||
#include <EMotionFX/CommandSystem/Source/RagdollCommands.h>
|
||||
@@ -44,10 +45,21 @@ namespace EMotionFX
|
||||
|
||||
D6JointLimitConfiguration::Reflect(GetSerializeContext());
|
||||
|
||||
const AZ::TypeId& jointLimitTypeId = azrtti_typeid<D6JointLimitConfiguration>();
|
||||
EXPECT_CALL(m_physicsSystem, GetSupportedJointTypes)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{jointLimitTypeId}));
|
||||
EXPECT_CALL(m_physicsSystem, ComputeInitialJointLimitConfiguration(jointLimitTypeId, _, _, _, _))
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeIds)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{ azrtti_typeid<D6JointLimitConfiguration>() }));
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeId(_))
|
||||
.WillRepeatedly(
|
||||
[](AzPhysics::JointType jointType) -> AZStd::optional<const AZ::TypeId>
|
||||
{
|
||||
if (jointType == AzPhysics::JointType::D6Joint)
|
||||
{
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
});
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, ComputeInitialJointLimitConfiguration(_, _, _, _, _))
|
||||
.WillRepeatedly([]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId,
|
||||
[[maybe_unused]] const AZ::Quaternion& parentWorldRotation,
|
||||
[[maybe_unused]] const AZ::Quaternion& childWorldRotation,
|
||||
@@ -59,6 +71,7 @@ namespace EMotionFX
|
||||
private:
|
||||
Physics::MockPhysicsSystem m_physicsSystem;
|
||||
Physics::MockPhysicsInterface m_physicsInterface;
|
||||
Physics::MockJointHelpersInterface m_jointHelpers;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS
|
||||
|
||||
@@ -55,10 +55,27 @@ namespace EMotionFX
|
||||
|
||||
Physics::MockPhysicsSystem physicsSystem;
|
||||
Physics::MockPhysicsInterface physicsInterface;
|
||||
EXPECT_CALL(physicsSystem, GetSupportedJointTypes)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{azrtti_typeid<D6JointLimitConfiguration>()}));
|
||||
EXPECT_CALL(physicsSystem, ComputeInitialJointLimitConfiguration(azrtti_typeid<D6JointLimitConfiguration>(), _, _, _, _))
|
||||
.WillRepeatedly([]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId, [[maybe_unused]] const AZ::Quaternion& parentWorldRotation, [[maybe_unused]] const AZ::Quaternion& childWorldRotation, [[maybe_unused]] const AZ::Vector3& axis, [[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) { return AZStd::make_unique<D6JointLimitConfiguration>(); });
|
||||
Physics::MockJointHelpersInterface jointHelpers;
|
||||
EXPECT_CALL(jointHelpers, GetSupportedJointTypeIds)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{ azrtti_typeid<D6JointLimitConfiguration>() }));
|
||||
EXPECT_CALL(jointHelpers, GetSupportedJointTypeId(_))
|
||||
.WillRepeatedly(
|
||||
[](AzPhysics::JointType jointType) -> AZStd::optional<const AZ::TypeId>
|
||||
{
|
||||
if (jointType == AzPhysics::JointType::D6Joint)
|
||||
{
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
});
|
||||
EXPECT_CALL(jointHelpers, ComputeInitialJointLimitConfiguration(_, _, _, _, _))
|
||||
.WillRepeatedly(
|
||||
[]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId,
|
||||
[[maybe_unused]] const AZ::Quaternion& parentWorldRotation, [[maybe_unused]] const AZ::Quaternion& childWorldRotation,
|
||||
[[maybe_unused]] const AZ::Vector3& axis, [[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
return AZStd::make_unique<D6JointLimitConfiguration>();
|
||||
});
|
||||
|
||||
AutoRegisteredActor actor {ActorFactory::CreateAndInit<SimpleJointChainActor>(4)};
|
||||
|
||||
@@ -70,7 +87,7 @@ namespace EMotionFX
|
||||
CommandRagdollHelpers::AddJointsToRagdoll(actor->GetID(), {"rootJoint", "joint1", "joint2", "joint3"});
|
||||
const Physics::RagdollConfiguration& ragdollConfig = actor->GetPhysicsSetup()->GetRagdollConfig();
|
||||
ASSERT_EQ(ragdollConfig.m_nodes.size(), 4);
|
||||
AZStd::shared_ptr<D6JointLimitConfiguration> rootJointLimit = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("rootJoint")->m_jointLimit);
|
||||
AZStd::shared_ptr<D6JointLimitConfiguration> rootJointLimit = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("rootJoint")->m_jointConfig);
|
||||
ASSERT_TRUE(rootJointLimit);
|
||||
// Set the initial joint limits on the rootJoint to be something different
|
||||
rootJointLimit->m_swingLimitY = 1.0f;
|
||||
@@ -119,7 +136,8 @@ namespace EMotionFX
|
||||
selectionModel.select(joint1Index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
|
||||
// Verify initial state of joint1's limits
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint1Limit = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint1")->m_jointLimit);
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint1Limit =
|
||||
AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint1")->m_jointConfig);
|
||||
EXPECT_EQ(joint1Limit->m_swingLimitY, 45.0f);
|
||||
EXPECT_EQ(joint1Limit->m_swingLimitZ, 45.0f);
|
||||
|
||||
@@ -141,10 +159,12 @@ namespace EMotionFX
|
||||
selectionModel.select(joint2Index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
selectionModel.select(joint3Index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint2Limit = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint2")->m_jointLimit);
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint2Limit =
|
||||
AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint2")->m_jointConfig);
|
||||
EXPECT_EQ(joint2Limit->m_swingLimitY, 45.0f);
|
||||
EXPECT_EQ(joint2Limit->m_swingLimitZ, 45.0f);
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint3Limit = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint3")->m_jointLimit);
|
||||
const AZStd::shared_ptr<D6JointLimitConfiguration> joint3Limit =
|
||||
AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(ragdollConfig.FindNodeConfigByName("joint3")->m_jointConfig);
|
||||
EXPECT_EQ(joint3Limit->m_swingLimitY, 45.0f);
|
||||
EXPECT_EQ(joint3Limit->m_swingLimitZ, 45.0f);
|
||||
|
||||
|
||||
@@ -18,11 +18,47 @@
|
||||
#include <EMotionFX/CommandSystem/Source/CommandManager.h>
|
||||
#include <EMotionFX/CommandSystem/Source/RagdollCommands.h>
|
||||
#include <EMotionFX/CommandSystem/Source/ColliderCommands.h>
|
||||
|
||||
#include <Tests/D6JointLimitConfiguration.h>
|
||||
#include <Tests/Mocks/PhysicsSystem.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
using RagdollCommandTests = ActorFixture;
|
||||
class RagdollCommandTests : public ActorFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
ActorFixture::SetUp();
|
||||
|
||||
D6JointLimitConfiguration::Reflect(GetSerializeContext());
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeIds)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{ azrtti_typeid<D6JointLimitConfiguration>() }));
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeId(_))
|
||||
.WillRepeatedly(
|
||||
[](AzPhysics::JointType jointType) -> AZStd::optional<const AZ::TypeId>
|
||||
{
|
||||
if (jointType == AzPhysics::JointType::D6Joint)
|
||||
{
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
});
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, ComputeInitialJointLimitConfiguration(_, _, _, _, _))
|
||||
.WillRepeatedly([]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId,
|
||||
[[maybe_unused]] const AZ::Quaternion& parentWorldRotation,
|
||||
[[maybe_unused]] const AZ::Quaternion& childWorldRotation,
|
||||
[[maybe_unused]] const AZ::Vector3& axis,
|
||||
[[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{ return AZStd::make_unique<D6JointLimitConfiguration>(); });
|
||||
}
|
||||
protected:
|
||||
Physics::MockJointHelpersInterface m_jointHelpers;
|
||||
};
|
||||
|
||||
AZStd::vector<AZStd::string> GetRagdollJointNames(const Actor* actor)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QPushButton>
|
||||
@@ -29,6 +30,7 @@
|
||||
#include <Tests/UI/ModalPopupHandler.h>
|
||||
#include <Tests/UI/UIFixture.h>
|
||||
#include <Tests/D6JointLimitConfiguration.h>
|
||||
#include <Tests/Mocks/PhysicsSystem.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -140,6 +142,31 @@ namespace EMotionFX
|
||||
|
||||
TEST_F(CanAddToSimulatedObjectFixture, CanAddCollidersfromRagdoll)
|
||||
{
|
||||
using ::testing::_;
|
||||
Physics::MockJointHelpersInterface jointHelpers;
|
||||
EXPECT_CALL(jointHelpers, GetSupportedJointTypeIds)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{ azrtti_typeid<D6JointLimitConfiguration>() }));
|
||||
|
||||
EXPECT_CALL(jointHelpers, GetSupportedJointTypeId(_))
|
||||
.WillRepeatedly(
|
||||
[](AzPhysics::JointType jointType) -> AZStd::optional<const AZ::TypeId>
|
||||
{
|
||||
if (jointType == AzPhysics::JointType::D6Joint)
|
||||
{
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
});
|
||||
|
||||
EXPECT_CALL(jointHelpers, ComputeInitialJointLimitConfiguration(_, _, _, _, _))
|
||||
.WillRepeatedly(
|
||||
[]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId, [[maybe_unused]] const AZ::Quaternion& parentWorldRotation,
|
||||
[[maybe_unused]] const AZ::Quaternion& childWorldRotation, [[maybe_unused]] const AZ::Vector3& axis,
|
||||
[[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
return AZStd::make_unique<D6JointLimitConfiguration>();
|
||||
});
|
||||
|
||||
RecordProperty("test_case_id", "C13291807");
|
||||
AutoRegisteredActor actor = ActorFactory::CreateAndInit<SimpleJointChainActor>(7, "CanAddToSimulatedObjectActor");
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <QtTest>
|
||||
@@ -27,6 +28,7 @@
|
||||
|
||||
#include <Editor/ReselectingTreeView.h>
|
||||
#include <Tests/D6JointLimitConfiguration.h>
|
||||
#include <Tests/Mocks/PhysicsSystem.h>
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
@@ -35,6 +37,8 @@ namespace EMotionFX
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
using ::testing::_;
|
||||
|
||||
SetupQtAndFixtureBase();
|
||||
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
@@ -42,6 +46,29 @@ namespace EMotionFX
|
||||
|
||||
D6JointLimitConfiguration::Reflect(serializeContext);
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeIds)
|
||||
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{ azrtti_typeid<D6JointLimitConfiguration>() }));
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, GetSupportedJointTypeId(_))
|
||||
.WillRepeatedly(
|
||||
[](AzPhysics::JointType jointType) -> AZStd::optional<const AZ::TypeId>
|
||||
{
|
||||
if (jointType == AzPhysics::JointType::D6Joint)
|
||||
{
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
});
|
||||
|
||||
EXPECT_CALL(m_jointHelpers, ComputeInitialJointLimitConfiguration(_, _, _, _, _))
|
||||
.WillRepeatedly(
|
||||
[]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId, [[maybe_unused]] const AZ::Quaternion& parentWorldRotation,
|
||||
[[maybe_unused]] const AZ::Quaternion& childWorldRotation, [[maybe_unused]] const AZ::Vector3& axis,
|
||||
[[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
return AZStd::make_unique<D6JointLimitConfiguration>();
|
||||
});
|
||||
|
||||
SetupPluginWindows();
|
||||
}
|
||||
|
||||
@@ -73,6 +100,7 @@ namespace EMotionFX
|
||||
QModelIndexList m_indexList;
|
||||
ReselectingTreeView* m_treeView;
|
||||
EMotionFX::SkeletonOutlinerPlugin* m_skeletonOutliner;
|
||||
Physics::MockJointHelpersInterface m_jointHelpers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -63,8 +63,6 @@ set(FILES
|
||||
Tests/Integration/CanDeleteJackEntity.cpp
|
||||
Tests/Bugs/CanDeleteMotionWhenMotionIsBeingBlended.cpp
|
||||
Tests/Bugs/CanUndoParameterDeletionAndRestoreBlendTreeConnections.cpp
|
||||
Tests/D6JointLimitConfiguration.cpp
|
||||
Tests/D6JointLimitConfiguration.h
|
||||
Tests/Editor/FileManagerTests.cpp
|
||||
Tests/Editor/ParametersGroupDefaultValues.cpp
|
||||
Tests/Editor/MotionSetLoadEscalation.cpp
|
||||
|
||||
@@ -21,4 +21,6 @@ set(FILES
|
||||
Tests/TestAssetCode/AnimGraphAssetFactory.h
|
||||
Tests/TestAssetCode/ActorAssetFactory.h
|
||||
Tests/TestAssetCode/MotionSetAssetFactory.h
|
||||
Tests/D6JointLimitConfiguration.cpp
|
||||
Tests/D6JointLimitConfiguration.h
|
||||
)
|
||||
|
||||
@@ -156,6 +156,8 @@ endif()
|
||||
################################################################################
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
|
||||
|
||||
ly_add_target(
|
||||
NAME PhysX.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
|
||||
NAMESPACE Gem
|
||||
@@ -174,6 +176,15 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
RUNTIME_DEPENDENCIES
|
||||
Gem::LmbrCentral
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_JOINTS_TYPED_TEST_CASE)
|
||||
ly_add_source_properties(
|
||||
SOURCES Tests/PhysXJointsTest.cpp
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
VALUES ENABLE_JOINTS_TYPED_TEST_CASE
|
||||
)
|
||||
endif()
|
||||
|
||||
ly_add_googletest(
|
||||
NAME Gem::PhysX.Tests
|
||||
)
|
||||
|
||||
@@ -144,11 +144,12 @@ namespace PhysX
|
||||
{
|
||||
return m_standardLimitConfig.m_isLimited;
|
||||
}
|
||||
GenericJointLimitsConfiguration EditorJointLimitPairConfig::ToGameTimeConfig() const
|
||||
|
||||
JointLimitProperties EditorJointLimitPairConfig::ToGameTimeConfig() const
|
||||
{
|
||||
return GenericJointLimitsConfiguration(m_standardLimitConfig.m_damping
|
||||
, m_standardLimitConfig.m_isLimited
|
||||
return JointLimitProperties(m_standardLimitConfig.m_isLimited
|
||||
, m_standardLimitConfig.m_isSoftLimit
|
||||
, m_standardLimitConfig.m_damping
|
||||
, m_limitPositive, m_limitNegative
|
||||
, m_standardLimitConfig.m_stiffness
|
||||
, m_standardLimitConfig.m_tolerance);
|
||||
@@ -193,11 +194,11 @@ namespace PhysX
|
||||
return m_standardLimitConfig.m_isLimited;
|
||||
}
|
||||
|
||||
GenericJointLimitsConfiguration EditorJointLimitConeConfig::ToGameTimeConfig() const
|
||||
JointLimitProperties EditorJointLimitConeConfig::ToGameTimeConfig() const
|
||||
{
|
||||
return GenericJointLimitsConfiguration(m_standardLimitConfig.m_damping
|
||||
, m_standardLimitConfig.m_isLimited
|
||||
return JointLimitProperties(m_standardLimitConfig.m_isLimited
|
||||
, m_standardLimitConfig.m_isSoftLimit
|
||||
, m_standardLimitConfig.m_damping
|
||||
, m_limitY
|
||||
, m_limitZ
|
||||
, m_standardLimitConfig.m_stiffness
|
||||
@@ -275,27 +276,31 @@ namespace PhysX
|
||||
, AzToolsFramework::Refresh_AttributesAndValues);
|
||||
}
|
||||
|
||||
GenericJointConfiguration EditorJointConfig::ToGameTimeConfig() const
|
||||
JointGenericProperties EditorJointConfig::ToGenericProperties() const
|
||||
{
|
||||
GenericJointConfiguration::GenericJointFlag flags = GenericJointConfiguration::GenericJointFlag::None;
|
||||
JointGenericProperties::GenericJointFlag flags = JointGenericProperties::GenericJointFlag::None;
|
||||
if (m_breakable)
|
||||
{
|
||||
flags |= GenericJointConfiguration::GenericJointFlag::Breakable;
|
||||
flags |= JointGenericProperties::GenericJointFlag::Breakable;
|
||||
}
|
||||
if (m_selfCollide)
|
||||
{
|
||||
flags |= GenericJointConfiguration::GenericJointFlag::SelfCollide;
|
||||
flags |= JointGenericProperties::GenericJointFlag::SelfCollide;
|
||||
}
|
||||
|
||||
return JointGenericProperties(flags, m_forceMax, m_torqueMax);
|
||||
}
|
||||
|
||||
JointComponentConfiguration EditorJointConfig::ToGameTimeConfig() const
|
||||
{
|
||||
AZ::Vector3 localRotation(m_localRotation);
|
||||
|
||||
return GenericJointConfiguration(m_forceMax
|
||||
, m_torqueMax
|
||||
, AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateFromEulerAnglesDegrees(localRotation),
|
||||
m_localPosition)
|
||||
, m_leadEntity
|
||||
, m_followerEntity
|
||||
, flags);
|
||||
return JointComponentConfiguration(
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(localRotation),
|
||||
m_localPosition),
|
||||
m_leadEntity,
|
||||
m_followerEntity);
|
||||
}
|
||||
|
||||
bool EditorJointConfig::IsInComponentMode() const
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <Source/Joint.h>
|
||||
#include <Source/JointComponent.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
@@ -68,7 +68,7 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
bool IsLimited() const;
|
||||
GenericJointLimitsConfiguration ToGameTimeConfig() const;
|
||||
JointLimitProperties ToGameTimeConfig() const;
|
||||
|
||||
EditorJointLimitConfig m_standardLimitConfig;
|
||||
float m_limitPositive = 45.0f;
|
||||
@@ -87,7 +87,7 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
bool IsLimited() const;
|
||||
GenericJointLimitsConfiguration ToGameTimeConfig() const;
|
||||
JointLimitProperties ToGameTimeConfig() const;
|
||||
|
||||
EditorJointLimitConfig m_standardLimitConfig;
|
||||
float m_limitY = 45.0f;
|
||||
@@ -105,7 +105,8 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
void SetLeadEntityId(AZ::EntityId leadEntityId);
|
||||
GenericJointConfiguration ToGameTimeConfig() const;
|
||||
JointGenericProperties ToGenericProperties() const;
|
||||
JointComponentConfiguration ToGameTimeConfig() const;
|
||||
|
||||
bool m_breakable = false;
|
||||
bool m_displayJointSetup = false;
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
struct D6JointLimitConfiguration
|
||||
: public AzPhysics::JointConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(D6JointLimitConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(D6JointLimitConfiguration, "{88E067B4-21E8-4FFA-9142-6C52605B704C}", AzPhysics::JointConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
float m_swingLimitY = 45.0f; ///< Maximum angle in degrees from the Y axis of the joint frame.
|
||||
float m_swingLimitZ = 45.0f; ///< Maximum angle in degrees from the Z axis of the joint frame.
|
||||
float m_twistLimitLower = -45.0f; ///< Lower limit in degrees for rotation about the X axis of the joint frame.
|
||||
float m_twistLimitUpper = 45.0f; ///< Upper limit in degrees for rotation about the X axis of the joint frame.
|
||||
};
|
||||
|
||||
//! Properties that are common for several types of joints.
|
||||
struct JointGenericProperties
|
||||
{
|
||||
enum class GenericJointFlag : AZ::u16
|
||||
{
|
||||
None = 0,
|
||||
Breakable = 1,
|
||||
SelfCollide = 1 << 1
|
||||
};
|
||||
|
||||
AZ_CLASS_ALLOCATOR(JointGenericProperties, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(JointGenericProperties, "{6CB15399-24F6-4F03-AAEF-1AE013B683E0}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointGenericProperties() = default;
|
||||
JointGenericProperties(GenericJointFlag flags, float forceMax, float torqueMax);
|
||||
|
||||
bool IsFlagSet(GenericJointFlag flag) const; ///< Returns if a particular flag is set as a bool.
|
||||
|
||||
/// Flags that indicates if joint is breakable, self-colliding, etc.
|
||||
/// Converting joint between breakable/non-breakable at game time is allowed.
|
||||
GenericJointFlag m_flags = GenericJointFlag::None;
|
||||
float m_forceMax = 1.0f; ///< Max force joint can tolerate before breaking.
|
||||
float m_torqueMax = 1.0f; ///< Max torque joint can tolerate before breaking.
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PhysX::JointGenericProperties::GenericJointFlag)
|
||||
|
||||
struct JointLimitProperties
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(JointLimitProperties, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(JointLimitProperties, "{31F941CB-6699-48BB-B12D-61874B52B984}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointLimitProperties() = default;
|
||||
JointLimitProperties(
|
||||
bool isLimited, bool isSoftLimit,
|
||||
float damping, float limitFirst, float limitSecond, float stiffness, float tolerance);
|
||||
|
||||
bool m_isLimited = true; ///< Specifies if limits are applied to the joint constraints. E.g. if the swing angles are limited.
|
||||
bool m_isSoftLimit = false; ///< If limit is soft, spring and damping are used, otherwise tolerance is used. Converting between soft/hard limit at game time is allowed.
|
||||
float m_damping = 20.0f; ///< The damping strength of the drive, the force proportional to the velocity error. Used if limit is soft.
|
||||
float m_limitFirst = 45.0f; ///< Positive angle limit in the case of twist angle limits, Y-axis swing limit in the case of cone limits.
|
||||
float m_limitSecond = 45.0f; ///< Negative angle limit in the case of twist angle limits, Z-axis swing limit in the case of cone limits.
|
||||
float m_stiffness = 100.0f; ///< The spring strength of the drive, the force proportional to the position error. Used if limit is soft.
|
||||
float m_tolerance = 0.1f; ///< Distance from the joint at which limits becomes enforced. Used if limit is hard.
|
||||
};
|
||||
|
||||
struct FixedJointConfiguration : public AzPhysics::JointConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(FixedJointConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(FixedJointConfiguration, "{9BCB368B-8D71-4928-B231-0225907E3BD9}", AzPhysics::JointConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointGenericProperties m_genericProperties;
|
||||
};
|
||||
|
||||
struct BallJointConfiguration : public AzPhysics::JointConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(BallJointConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(BallJointConfiguration, "{C2DE2479-B752-469D-BE05-900CD2CD8481}", AzPhysics::JointConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointGenericProperties m_genericProperties;
|
||||
JointLimitProperties m_limitProperties;
|
||||
};
|
||||
|
||||
struct HingeJointConfiguration : public AzPhysics::JointConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR(HingeJointConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(HingeJointConfiguration, "{FB04198E-0BA5-45C2-8343-66DA28ED45EA}", AzPhysics::JointConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointGenericProperties m_genericProperties;
|
||||
JointLimitProperties m_limitProperties;
|
||||
};
|
||||
} // namespace PhysX
|
||||
@@ -16,8 +16,10 @@
|
||||
#include <PhysX/MathConversion.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/RigidBodyBus.h>
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
|
||||
#include <PxPhysicsAPI.h>
|
||||
|
||||
@@ -33,15 +35,17 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
BallJointComponent::BallJointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& swingLimit)
|
||||
: JointComponent(config, swingLimit)
|
||||
BallJointComponent::BallJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties)
|
||||
: JointComponent(configuration, genericProperties, limitProperties)
|
||||
{
|
||||
}
|
||||
|
||||
void BallJointComponent::InitNativeJoint()
|
||||
{
|
||||
if (m_joint)
|
||||
if (m_jointHandle != AzPhysics::InvalidJointHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -52,50 +56,24 @@ namespace PhysX
|
||||
{
|
||||
return;
|
||||
}
|
||||
PHYSX_SCENE_READ_LOCK(leadFollowerInfo.m_followerActor->getScene());
|
||||
m_joint = AZStd::make_shared<BallJoint>(physx::PxSphericalJointCreate(
|
||||
PxGetPhysics(),
|
||||
leadFollowerInfo.m_leadActor,
|
||||
leadFollowerInfo.m_leadLocal,
|
||||
leadFollowerInfo.m_followerActor,
|
||||
leadFollowerInfo.m_followerLocal),
|
||||
leadFollowerInfo.m_leadBody,
|
||||
leadFollowerInfo.m_followerBody);
|
||||
|
||||
InitSwingLimits();
|
||||
}
|
||||
BallJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
configuration.m_childLocalPosition = leadFollowerInfo.m_followerLocal.GetTranslation();
|
||||
configuration.m_childLocalRotation = leadFollowerInfo.m_followerLocal.GetRotation();
|
||||
|
||||
void BallJointComponent::InitSwingLimits()
|
||||
{
|
||||
if (!m_joint)
|
||||
configuration.m_genericProperties = m_genericProperties;
|
||||
configuration.m_limitProperties = m_limits;
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
return;
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner,
|
||||
&configuration,
|
||||
leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
|
||||
physx::PxSphericalJoint* ballJointNative = static_cast<physx::PxSphericalJoint*>(m_joint->GetNativePointer());
|
||||
if (!ballJointNative)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_limits.m_isLimited)
|
||||
{
|
||||
ballJointNative->setSphericalJointFlag(physx::PxSphericalJointFlag::eLIMIT_ENABLED, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hard limit uses a tolerance value (distance to limit at which limit becomes active).
|
||||
// Soft limit allows angle to exceed limit but springs back with configurable spring stiffness and damping.
|
||||
physx::PxJointLimitCone swingLimit(AZ::DegToRad(m_limits.m_limitFirst)
|
||||
, AZ::DegToRad(m_limits.m_limitSecond)
|
||||
, m_limits.m_tolerance);
|
||||
if (m_limits.m_isSoftLimit)
|
||||
{
|
||||
swingLimit.stiffness = m_limits.m_stiffness;
|
||||
swingLimit.damping = m_limits.m_damping;
|
||||
}
|
||||
|
||||
ballJointNative->setLimitCone(swingLimit);
|
||||
ballJointNative->setSphericalJointFlag(physx::PxSphericalJointFlag::eLIMIT_ENABLED, true);
|
||||
}
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -25,15 +25,14 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
BallJointComponent() = default;
|
||||
BallJointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& swingLimit);
|
||||
BallJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties);
|
||||
~BallJointComponent() = default;
|
||||
|
||||
protected:
|
||||
// JointComponent
|
||||
void InitNativeJoint() override;
|
||||
|
||||
private:
|
||||
void InitSwingLimits();
|
||||
};
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace PhysX
|
||||
m_config.m_followerEntity = GetEntityId(); // joint is always in the same entity as the follower body.
|
||||
gameEntity->CreateComponent<BallJointComponent>(
|
||||
m_config.ToGameTimeConfig(),
|
||||
m_config.ToGenericProperties(),
|
||||
m_swingLimit.ToGameTimeConfig());
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
|
||||
|
||||
@@ -94,6 +94,6 @@ namespace PhysX
|
||||
void EditorFixedJointComponent::BuildGameEntity(AZ::Entity* gameEntity)
|
||||
{
|
||||
m_config.m_followerEntity = GetEntityId(); // joint is always in the same entity as the follower body.
|
||||
gameEntity->CreateComponent<FixedJointComponent>(m_config.ToGameTimeConfig());
|
||||
gameEntity->CreateComponent<FixedJointComponent>(m_config.ToGameTimeConfig(), m_config.ToGenericProperties());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace PhysX
|
||||
m_config.m_followerEntity = GetEntityId(); // joint is always in the same entity as the follower body.
|
||||
gameEntity->CreateComponent<HingeJointComponent>(
|
||||
m_config.ToGameTimeConfig(),
|
||||
m_config.ToGenericProperties(),
|
||||
m_angularLimit.ToGameTimeConfig());
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/RigidBodyBus.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
#include <PxPhysicsAPI.h>
|
||||
|
||||
@@ -33,20 +36,24 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
FixedJointComponent::FixedJointComponent(const GenericJointConfiguration& config)
|
||||
: JointComponent(config)
|
||||
FixedJointComponent::FixedJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties)
|
||||
: JointComponent(configuration, genericProperties)
|
||||
{
|
||||
}
|
||||
|
||||
FixedJointComponent::FixedJointComponent(const GenericJointConfiguration& config,
|
||||
const GenericJointLimitsConfiguration& limitConfig)
|
||||
: JointComponent(config, limitConfig)
|
||||
FixedJointComponent::FixedJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties)
|
||||
: JointComponent(configuration, genericProperties, limitProperties)
|
||||
{
|
||||
}
|
||||
|
||||
void FixedJointComponent::InitNativeJoint()
|
||||
{
|
||||
if (m_joint)
|
||||
if (m_jointHandle != AzPhysics::InvalidJointHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -57,14 +64,23 @@ namespace PhysX
|
||||
{
|
||||
return;
|
||||
}
|
||||
PHYSX_SCENE_READ_LOCK(leadFollowerInfo.m_followerActor->getScene());
|
||||
m_joint = AZStd::make_shared<FixedJoint>(physx::PxFixedJointCreate(
|
||||
PxGetPhysics(),
|
||||
leadFollowerInfo.m_leadActor,
|
||||
leadFollowerInfo.m_leadLocal,
|
||||
leadFollowerInfo.m_followerActor,
|
||||
leadFollowerInfo.m_followerLocal),
|
||||
leadFollowerInfo.m_leadBody,
|
||||
leadFollowerInfo.m_followerBody);
|
||||
|
||||
FixedJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
configuration.m_childLocalPosition = leadFollowerInfo.m_followerLocal.GetTranslation();
|
||||
configuration.m_childLocalRotation = leadFollowerInfo.m_followerLocal.GetRotation();
|
||||
|
||||
configuration.m_genericProperties = m_genericProperties;
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner,
|
||||
&configuration,
|
||||
leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
}
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -25,9 +25,13 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
FixedJointComponent() = default;
|
||||
explicit FixedJointComponent(const GenericJointConfiguration& config);
|
||||
FixedJointComponent(const GenericJointConfiguration& config,
|
||||
const GenericJointLimitsConfiguration& limitConfig);
|
||||
FixedJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties);
|
||||
FixedJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties);
|
||||
~FixedJointComponent() = default;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
#include <PhysX/MathConversion.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Physics/RigidBodyBus.h>
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
|
||||
#include <PxPhysicsAPI.h>
|
||||
|
||||
@@ -34,67 +36,45 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
HingeJointComponent::HingeJointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& angularLimitConfig)
|
||||
: JointComponent(config, angularLimitConfig)
|
||||
HingeJointComponent::HingeJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties)
|
||||
: JointComponent(configuration, genericProperties, limitProperties)
|
||||
{
|
||||
}
|
||||
|
||||
void HingeJointComponent::InitNativeJoint()
|
||||
{
|
||||
if (m_joint)
|
||||
if (m_jointHandle != AzPhysics::InvalidJointHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
JointComponent::LeadFollowerInfo leadFollowerInfo;
|
||||
ObtainLeadFollowerInfo(leadFollowerInfo);
|
||||
if (!leadFollowerInfo.m_followerActor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PHYSX_SCENE_READ_LOCK(leadFollowerInfo.m_followerActor->getScene());
|
||||
m_joint = AZStd::make_shared<HingeJoint>(physx::PxRevoluteJointCreate(
|
||||
PxGetPhysics(),
|
||||
leadFollowerInfo.m_leadActor,
|
||||
leadFollowerInfo.m_leadLocal,
|
||||
leadFollowerInfo.m_followerActor,
|
||||
leadFollowerInfo.m_followerLocal),
|
||||
leadFollowerInfo.m_leadBody,
|
||||
leadFollowerInfo.m_followerBody);
|
||||
|
||||
InitAngularLimits();
|
||||
}
|
||||
|
||||
void HingeJointComponent::InitAngularLimits()
|
||||
{
|
||||
if (!m_joint)
|
||||
if (leadFollowerInfo.m_followerActor == nullptr ||
|
||||
leadFollowerInfo.m_leadBody == nullptr ||
|
||||
leadFollowerInfo.m_followerBody == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
physx::PxRevoluteJoint* revoluteJointNative = static_cast<physx::PxRevoluteJoint*>(m_joint->GetNativePointer());
|
||||
if (!revoluteJointNative)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HingeJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
configuration.m_childLocalPosition = leadFollowerInfo.m_followerLocal.GetTranslation();
|
||||
configuration.m_childLocalRotation = leadFollowerInfo.m_followerLocal.GetRotation();
|
||||
|
||||
if (!m_limits.m_isLimited)
|
||||
{
|
||||
revoluteJointNative->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eLIMIT_ENABLED, false);
|
||||
return;
|
||||
}
|
||||
configuration.m_genericProperties = m_genericProperties;
|
||||
configuration.m_limitProperties = m_limits;
|
||||
|
||||
physx::PxJointAngularLimitPair limitPair(AZ::DegToRad(m_limits.m_limitSecond)
|
||||
, AZ::DegToRad(m_limits.m_limitFirst)
|
||||
, m_limits.m_tolerance);
|
||||
if (m_limits.m_isSoftLimit)
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
limitPair.stiffness = m_limits.m_stiffness;
|
||||
limitPair.damping = m_limits.m_damping;
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
|
||||
revoluteJointNative->setLimit(limitPair);
|
||||
revoluteJointNative->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eLIMIT_ENABLED, true);
|
||||
}
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -25,15 +25,14 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
HingeJointComponent() = default;
|
||||
explicit HingeJointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& angularLimit);
|
||||
HingeJointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties);
|
||||
~HingeJointComponent() = default;
|
||||
|
||||
protected:
|
||||
// JointComponent
|
||||
void InitNativeJoint() override;
|
||||
|
||||
private:
|
||||
void InitAngularLimits();
|
||||
};
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -1,646 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <PhysX_precompiled.h>
|
||||
#include <Joint.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <Include/PhysX/NativeTypeIdentifiers.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
namespace JointConstants
|
||||
{
|
||||
// Setting swing limits to very small values can cause extreme stability problems, so clamp above a small
|
||||
// threshold.
|
||||
static const float MinSwingLimitDegrees = 1.0f;
|
||||
} // namespace JointConstants
|
||||
|
||||
AzPhysics::SimulatedBody* Joint::GetParentBody() const
|
||||
{
|
||||
return m_parentBody;
|
||||
}
|
||||
|
||||
AzPhysics::SimulatedBody* Joint::GetChildBody() const
|
||||
{
|
||||
return m_childBody;
|
||||
}
|
||||
|
||||
bool IsAtLeastOneDynamic(AzPhysics::SimulatedBody* body0,
|
||||
AzPhysics::SimulatedBody* body1)
|
||||
{
|
||||
for (const AzPhysics::SimulatedBody* body : { body0, body1 })
|
||||
{
|
||||
if (body)
|
||||
{
|
||||
if (body->GetNativeType() == NativeTypeIdentifiers::RigidBody ||
|
||||
body->GetNativeType() == NativeTypeIdentifiers::ArticulationLink)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
physx::PxRigidActor* GetPxRigidActor(AzPhysics::SimulatedBody* worldBody)
|
||||
{
|
||||
if (worldBody && static_cast<physx::PxBase*>(worldBody->GetNativePointer())->is<physx::PxRigidActor>())
|
||||
{
|
||||
return static_cast<physx::PxRigidActor*>(worldBody->GetNativePointer());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void releasePxJoint(physx::PxJoint* joint)
|
||||
{
|
||||
PHYSX_SCENE_WRITE_LOCK(joint->getScene());
|
||||
joint->userData = nullptr;
|
||||
joint->release();
|
||||
}
|
||||
|
||||
Joint::Joint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody)
|
||||
: m_parentBody(parentBody)
|
||||
, m_childBody(childBody)
|
||||
{
|
||||
m_pxJoint = PxJointUniquePtr(pxJoint, releasePxJoint);
|
||||
}
|
||||
|
||||
bool Joint::SetPxActors()
|
||||
{
|
||||
physx::PxRigidActor* parentActor = GetPxRigidActor(m_parentBody);
|
||||
physx::PxRigidActor* childActor = GetPxRigidActor(m_childBody);
|
||||
if (!parentActor && !childActor)
|
||||
{
|
||||
AZ_Error("PhysX Joint", false, "Invalid PhysX actors in joint - at least one must be a PxRigidActor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pxJoint->setActors(parentActor, childActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Joint::SetParentBody(AzPhysics::SimulatedBody* parentBody)
|
||||
{
|
||||
if (IsAtLeastOneDynamic(parentBody, m_childBody))
|
||||
{
|
||||
m_parentBody = parentBody;
|
||||
SetPxActors();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "Call to SetParentBody would result in invalid joint - at least one "
|
||||
"body in a joint must be dynamic.");
|
||||
}
|
||||
}
|
||||
|
||||
void Joint::SetChildBody(AzPhysics::SimulatedBody* childBody)
|
||||
{
|
||||
if (IsAtLeastOneDynamic(m_parentBody, childBody))
|
||||
{
|
||||
m_childBody = childBody;
|
||||
SetPxActors();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "Call to SetChildBody would result in invalid joint - at least one "
|
||||
"body in a joint must be dynamic.");
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::string& Joint::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Joint::SetName(const AZStd::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void* Joint::GetNativePointer()
|
||||
{
|
||||
return m_pxJoint.get();
|
||||
}
|
||||
|
||||
const AZ::Crc32 D6Joint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::D6Joint;
|
||||
}
|
||||
|
||||
void D6Joint::GenerateJointLimitVisualizationData(
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
[[maybe_unused]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
[[maybe_unused]] AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 angularSubdivisionsClamped = AZ::GetClamp(angularSubdivisions, 4u, 32u);
|
||||
const AZ::u32 radialSubdivisionsClamped = AZ::GetClamp(radialSubdivisions, 1u, 4u);
|
||||
|
||||
const physx::PxD6Joint* joint = static_cast<physx::PxD6Joint*>(m_pxJoint.get());
|
||||
const AZ::Quaternion parentLocalRotation = PxMathConvert(joint->getLocalPose(physx::PxJointActorIndex::eACTOR0).q);
|
||||
const AZ::Quaternion parentWorldRotation = m_parentBody ? m_parentBody->GetOrientation() : AZ::Quaternion::CreateIdentity();
|
||||
const AZ::Quaternion childLocalRotation = PxMathConvert(joint->getLocalPose(physx::PxJointActorIndex::eACTOR1).q);
|
||||
const AZ::Quaternion childWorldRotation = m_childBody ? m_childBody->GetOrientation() : AZ::Quaternion::CreateIdentity();
|
||||
|
||||
const float swingAngleY = joint->getSwingYAngle();
|
||||
const float swingAngleZ = joint->getSwingZAngle();
|
||||
const float swingLimitY = joint->getSwingLimit().yAngle;
|
||||
const float swingLimitZ = joint->getSwingLimit().zAngle;
|
||||
const float twistAngle = joint->getTwist();
|
||||
const float twistLimitLower = joint->getTwistLimit().lower;
|
||||
const float twistLimitUpper = joint->getTwistLimit().upper;
|
||||
|
||||
JointUtils::AppendD6SwingConeToLineBuffer(parentLocalRotation, swingAngleY, swingAngleZ, swingLimitY, swingLimitZ,
|
||||
scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
JointUtils::AppendD6TwistArcToLineBuffer(parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper,
|
||||
scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
JointUtils::AppendD6CurrentTwistToLineBuffer(parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper,
|
||||
scale, lineBufferOut, lineValidityBufferOut);
|
||||
|
||||
// draw the X-axis of the child joint frame
|
||||
// make the axis slightly longer than the radius of the twist arc so that it is easy to see
|
||||
float axisLength = 1.25f * scale;
|
||||
AZ::Vector3 childAxis = (parentWorldRotation.GetConjugate() * childWorldRotation * childLocalRotation).TransformVector(
|
||||
AZ::Vector3::CreateAxisX(axisLength));
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(childAxis);
|
||||
}
|
||||
|
||||
const AZ::Crc32 FixedJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::FixedJoint;
|
||||
}
|
||||
|
||||
const AZ::Crc32 HingeJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::HingeJoint;
|
||||
}
|
||||
|
||||
const AZ::Crc32 BallJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::BallJoint;
|
||||
}
|
||||
|
||||
void GenericJointConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<GenericJointConfiguration>()
|
||||
->Version(2, &VersionConverter)
|
||||
->Field("Follower Local Transform", &GenericJointConfiguration::m_localTransformFromFollower)
|
||||
->Field("Maximum Force", &GenericJointConfiguration::m_forceMax)
|
||||
->Field("Maximum Torque", &GenericJointConfiguration::m_torqueMax)
|
||||
->Field("Lead Entity", &GenericJointConfiguration::m_leadEntity)
|
||||
->Field("Follower Entity", &GenericJointConfiguration::m_followerEntity)
|
||||
->Field("Flags", &GenericJointConfiguration::m_flags)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
bool GenericJointConfiguration::VersionConverter(
|
||||
AZ::SerializeContext& context,
|
||||
AZ::SerializeContext::DataElementNode& classElement)
|
||||
{
|
||||
if (classElement.GetVersion() <= 1)
|
||||
{
|
||||
// Convert bool breakable to GenericJointConfiguration::GenericJointFlag
|
||||
const int breakableElementIndex = classElement.FindElement(AZ_CRC("Breakable", 0xb274ecd4));
|
||||
if (breakableElementIndex >= 0)
|
||||
{
|
||||
bool breakable = false;
|
||||
AZ::SerializeContext::DataElementNode& breakableNode = classElement.GetSubElement(breakableElementIndex);
|
||||
breakableNode.GetData(breakable);
|
||||
if (!breakableNode.GetData<bool>(breakable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
classElement.RemoveElement(breakableElementIndex);
|
||||
GenericJointConfiguration::GenericJointFlag flags = breakable ? GenericJointConfiguration::GenericJointFlag::Breakable : GenericJointConfiguration::GenericJointFlag::None;
|
||||
classElement.AddElementWithData(context, "Flags", flags);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GenericJointConfiguration::GenericJointConfiguration(float forceMax,
|
||||
float torqueMax,
|
||||
AZ::Transform localTransformFromFollower,
|
||||
AZ::EntityId leadEntity,
|
||||
AZ::EntityId followerEntity,
|
||||
GenericJointFlag flags)
|
||||
: m_forceMax(forceMax)
|
||||
, m_torqueMax(torqueMax)
|
||||
, m_localTransformFromFollower(localTransformFromFollower)
|
||||
, m_leadEntity(leadEntity)
|
||||
, m_followerEntity(followerEntity)
|
||||
, m_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
bool GenericJointConfiguration::GetFlag(GenericJointFlag flag)
|
||||
{
|
||||
return static_cast<bool>(m_flags & flag);
|
||||
}
|
||||
|
||||
void GenericJointLimitsConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<GenericJointLimitsConfiguration>()
|
||||
->Version(1)
|
||||
->Field("First Limit", &GenericJointLimitsConfiguration::m_limitFirst)
|
||||
->Field("Second Limit", &GenericJointLimitsConfiguration::m_limitSecond)
|
||||
->Field("Tolerance", &GenericJointLimitsConfiguration::m_tolerance)
|
||||
->Field("Is Limited", &GenericJointLimitsConfiguration::m_isLimited)
|
||||
->Field("Is Soft Limit", &GenericJointLimitsConfiguration::m_isSoftLimit)
|
||||
->Field("Damping", &GenericJointLimitsConfiguration::m_damping)
|
||||
->Field("Spring", &GenericJointLimitsConfiguration::m_stiffness)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
GenericJointLimitsConfiguration::GenericJointLimitsConfiguration(float damping
|
||||
, bool isLimited
|
||||
, bool isSoftLimit
|
||||
, float limitFirst
|
||||
, float limitSecond
|
||||
, float stiffness
|
||||
, float tolerance)
|
||||
: m_damping(damping)
|
||||
, m_isLimited(isLimited)
|
||||
, m_isSoftLimit(isSoftLimit)
|
||||
, m_limitFirst(limitFirst)
|
||||
, m_limitSecond(limitSecond)
|
||||
, m_stiffness(stiffness)
|
||||
, m_tolerance(tolerance)
|
||||
{
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::TypeId> JointUtils::GetSupportedJointTypes()
|
||||
{
|
||||
return AZStd::vector<AZ::TypeId>
|
||||
{
|
||||
D6JointLimitConfiguration::RTTI_Type()
|
||||
};
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Physics::JointLimitConfiguration> JointUtils::CreateJointLimitConfiguration([[maybe_unused]] AZ::TypeId jointType)
|
||||
{
|
||||
return AZStd::make_shared<D6JointLimitConfiguration>();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Physics::Joint> JointUtils::CreateJoint(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration,
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody)
|
||||
{
|
||||
if (!configuration)
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - configuration was nullptr.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (auto d6Config = AZStd::rtti_pointer_cast<D6JointLimitConfiguration>(configuration))
|
||||
{
|
||||
if (!IsAtLeastOneDynamic(parentBody, childBody))
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be dynamic.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
physx::PxRigidActor* parentActor = GetPxRigidActor(parentBody);
|
||||
physx::PxRigidActor* childActor = GetPxRigidActor(childBody);
|
||||
|
||||
if (!parentActor && !childActor)
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be a PxRigidActor.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const physx::PxTransform parentWorldTransform = parentActor ? parentActor->getGlobalPose() : physx::PxTransform(physx::PxIdentity);
|
||||
const physx::PxTransform childWorldTransform = childActor ? childActor->getGlobalPose() : physx::PxTransform(physx::PxIdentity);
|
||||
const physx::PxVec3 childOffset = childWorldTransform.p - parentWorldTransform.p;
|
||||
physx::PxTransform parentLocalTransform(PxMathConvert(d6Config->m_parentLocalRotation).getNormalized());
|
||||
const physx::PxTransform childLocalTransform(PxMathConvert(d6Config->m_childLocalRotation).getNormalized());
|
||||
parentLocalTransform.p = parentWorldTransform.q.rotateInv(childOffset);
|
||||
|
||||
physx::PxD6Joint* joint = PxD6JointCreate(PxGetPhysics(), parentActor, parentLocalTransform,
|
||||
childActor, childLocalTransform);
|
||||
|
||||
joint->setMotion(physx::PxD6Axis::eTWIST, physx::PxD6Motion::eLIMITED);
|
||||
joint->setMotion(physx::PxD6Axis::eSWING1, physx::PxD6Motion::eLIMITED);
|
||||
joint->setMotion(physx::PxD6Axis::eSWING2, physx::PxD6Motion::eLIMITED);
|
||||
|
||||
AZ_Warning("PhysX Joint",
|
||||
d6Config->m_swingLimitY >= JointConstants::MinSwingLimitDegrees && d6Config->m_swingLimitZ >= JointConstants::MinSwingLimitDegrees,
|
||||
"Very small swing limit requested for joint between \"%s\" and \"%s\", increasing to %f degrees to improve stability",
|
||||
parentActor ? parentActor->getName() : "world", childActor ? childActor->getName() : "world",
|
||||
JointConstants::MinSwingLimitDegrees);
|
||||
float swingLimitY = AZ::DegToRad(AZ::GetMax(JointConstants::MinSwingLimitDegrees, d6Config->m_swingLimitY));
|
||||
float swingLimitZ = AZ::DegToRad(AZ::GetMax(JointConstants::MinSwingLimitDegrees, d6Config->m_swingLimitZ));
|
||||
physx::PxJointLimitCone limitCone(swingLimitY, swingLimitZ);
|
||||
joint->setSwingLimit(limitCone);
|
||||
|
||||
float twistLower = AZ::DegToRad(AZStd::GetMin(d6Config->m_twistLimitLower, d6Config->m_twistLimitUpper));
|
||||
float twistUpper = AZ::DegToRad(AZStd::GetMax(d6Config->m_twistLimitLower, d6Config->m_twistLimitUpper));
|
||||
physx::PxJointAngularLimitPair twistLimitPair(twistLower, twistUpper);
|
||||
joint->setTwistLimit(twistLimitPair);
|
||||
|
||||
return AZStd::make_shared<D6Joint>(joint, parentBody, childBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "Unrecognized joint limit configuration.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
D6JointState JointUtils::CalculateD6JointState(
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Quaternion& childLocalRotation)
|
||||
{
|
||||
D6JointState result;
|
||||
|
||||
const AZ::Quaternion parentRotation = parentWorldRotation * parentLocalRotation;
|
||||
const AZ::Quaternion childRotation = childWorldRotation * childLocalRotation;
|
||||
const AZ::Quaternion relativeRotation = parentRotation.GetConjugate() * childRotation;
|
||||
AZ::Quaternion twistQuat = AZ::IsClose(relativeRotation.GetX(), 0.0f, AZ::Constants::FloatEpsilon)
|
||||
? AZ::Quaternion::CreateIdentity()
|
||||
: AZ::Quaternion(relativeRotation.GetX(), 0.0f, 0.0f, relativeRotation.GetW()).GetNormalized();
|
||||
AZ::Quaternion swingQuat = relativeRotation * twistQuat.GetConjugate();
|
||||
|
||||
// make sure the twist angle has the correct sign for the rotation
|
||||
twistQuat *= AZ::GetSign(twistQuat.GetX());
|
||||
// make sure we get the shortest arcs for the swing degrees of freedom
|
||||
swingQuat *= AZ::GetSign(swingQuat.GetW());
|
||||
// the PhysX swing limits work in terms of tan quarter angles
|
||||
result.m_swingAngleY = 4.0f * atan2f(swingQuat.GetY(), 1.0f + swingQuat.GetW());
|
||||
result.m_swingAngleZ = 4.0f * atan2f(swingQuat.GetZ(), 1.0f + swingQuat.GetW());
|
||||
const float twistAngle = twistQuat.GetAngle();
|
||||
// GetAngle returns an angle in the range 0..2 pi, but the twist limits work in the range -pi..pi
|
||||
const float wrappedTwistAngle = twistAngle > AZ::Constants::Pi ? twistAngle - AZ::Constants::TwoPi : twistAngle;
|
||||
result.m_twistAngle = wrappedTwistAngle;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool JointUtils::IsD6SwingValid(
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ)
|
||||
{
|
||||
const float epsilon = AZ::Constants::FloatEpsilon;
|
||||
const float yFactor = tanf(0.25f * swingAngleY) / AZStd::GetMax(epsilon, tanf(0.25f * swingLimitY));
|
||||
const float zFactor = tanf(0.25f * swingAngleZ) / AZStd::GetMax(epsilon, tanf(0.25f * swingLimitZ));
|
||||
|
||||
return (yFactor * yFactor + zFactor * zFactor <= 1.0f + epsilon);
|
||||
}
|
||||
|
||||
void JointUtils::AppendD6SwingConeToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesSwingCone = angularSubdivisions * (1u + radialSubdivisions);
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesSwingCone);
|
||||
lineValidityBufferOut.reserve(lineValidityBufferOut.size() + numLinesSwingCone);
|
||||
|
||||
// the orientation quat for a radial line in the cone can be represented in terms of sin and cos half angles
|
||||
// these expressions can be efficiently calculated using tan quarter angles as follows:
|
||||
// writing t = tan(x / 4)
|
||||
// sin(x / 2) = 2 * t / (1 + t * t)
|
||||
// cos(x / 2) = (1 - t * t) / (1 + t * t)
|
||||
const float tanQuarterSwingZ = tanf(0.25f * swingLimitZ);
|
||||
const float tanQuarterSwingY = tanf(0.25f * swingLimitY);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = AZ::Constants::TwoPi / angularSubdivisions * angularIndex;
|
||||
// the axis about which to rotate the x-axis to get the radial vector for this segment of the cone
|
||||
const AZ::Vector3 rotationAxis(0, -tanQuarterSwingY * sinf(angle), tanQuarterSwingZ * cosf(angle));
|
||||
const float normalizationFactor = rotationAxis.GetLengthSq();
|
||||
const AZ::Quaternion radialVectorRotation = 1.0f / (1.0f + normalizationFactor) *
|
||||
AZ::Quaternion::CreateFromVector3AndValue(2.0f * rotationAxis, 1.0f - normalizationFactor);
|
||||
const AZ::Vector3 radialVector = (parentLocalRotation * radialVectorRotation).TransformVector(AZ::Vector3::CreateAxisX(scale));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
if (angularIndex < angularSubdivisions)
|
||||
{
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
}
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool swingValid = IsD6SwingValid(swingAngleY, swingAngleZ, swingLimitY, swingLimitZ);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesSwingCone, swingValid);
|
||||
}
|
||||
|
||||
void JointUtils::AppendD6TwistArcToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesTwistArc = angularSubdivisions * (1u + radialSubdivisions) + 1u;
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesTwistArc);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
const float twistRange = twistLimitUpper - twistLimitLower;
|
||||
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = twistLimitLower + twistRange / angularSubdivisions * angularIndex;
|
||||
const AZ::Vector3 radialVector = parentLocalRotation.TransformVector(scale * AZ::Vector3(0.0f, cosf(angle), sinf(angle)));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
const float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool twistValid = (twistAngle >= twistLimitLower && twistAngle <= twistLimitUpper);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesTwistArc, twistValid);
|
||||
}
|
||||
|
||||
void JointUtils::AppendD6CurrentTwistToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
[[maybe_unused]] float twistLimitLower,
|
||||
[[maybe_unused]] float twistLimitUpper,
|
||||
float scale,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut
|
||||
)
|
||||
{
|
||||
const AZ::Vector3 twistVector = parentLocalRotation.TransformVector(1.25f * scale * AZ::Vector3(0.0f, cosf(twistAngle), sinf(twistAngle)));
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(twistVector);
|
||||
lineValidityBufferOut.push_back(true);
|
||||
}
|
||||
|
||||
void JointUtils::GenerateJointLimitVisualizationData(
|
||||
const Physics::JointLimitConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
[[maybe_unused]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
[[maybe_unused]] AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
if (const auto d6JointConfiguration = azrtti_cast<const D6JointLimitConfiguration*>(&configuration))
|
||||
{
|
||||
const AZ::u32 angularSubdivisionsClamped = AZ::GetClamp(angularSubdivisions, 4u, 32u);
|
||||
const AZ::u32 radialSubdivisionsClamped = AZ::GetClamp(radialSubdivisions, 1u, 4u);
|
||||
|
||||
const D6JointState jointState = CalculateD6JointState(parentRotation, d6JointConfiguration->m_parentLocalRotation,
|
||||
childRotation, d6JointConfiguration->m_childLocalRotation);
|
||||
const float swingAngleY = jointState.m_swingAngleY;
|
||||
const float swingAngleZ = jointState.m_swingAngleZ;
|
||||
const float twistAngle = jointState.m_twistAngle;
|
||||
const float swingLimitY = AZ::DegToRad(d6JointConfiguration->m_swingLimitY);
|
||||
const float swingLimitZ = AZ::DegToRad(d6JointConfiguration->m_swingLimitZ);
|
||||
const float twistLimitLower = AZ::DegToRad(d6JointConfiguration->m_twistLimitLower);
|
||||
const float twistLimitUpper = AZ::DegToRad(d6JointConfiguration->m_twistLimitUpper);
|
||||
|
||||
AppendD6SwingConeToLineBuffer(d6JointConfiguration->m_parentLocalRotation, swingAngleY, swingAngleZ, swingLimitY,
|
||||
swingLimitZ, scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
AppendD6TwistArcToLineBuffer(d6JointConfiguration->m_parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper,
|
||||
scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
AppendD6CurrentTwistToLineBuffer(d6JointConfiguration->m_parentLocalRotation, twistAngle, twistLimitLower,
|
||||
twistLimitUpper, scale, lineBufferOut, lineValidityBufferOut);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration> JointUtils::ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
AZ_UNUSED(exampleLocalRotations);
|
||||
|
||||
if (jointLimitTypeId == D6JointLimitConfiguration::RTTI_Type())
|
||||
{
|
||||
const AZ::Vector3& normalizedAxis = axis.IsZero()
|
||||
? AZ::Vector3::CreateAxisX()
|
||||
: axis.GetNormalized();
|
||||
|
||||
D6JointLimitConfiguration d6JointLimitConfig;
|
||||
const AZ::Quaternion childLocalRotation = AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisX(),
|
||||
childWorldRotation.GetConjugate().TransformVector(normalizedAxis));
|
||||
d6JointLimitConfig.m_childLocalRotation = childLocalRotation;
|
||||
d6JointLimitConfig.m_parentLocalRotation = parentWorldRotation.GetConjugate() * childWorldRotation * childLocalRotation;
|
||||
|
||||
return AZStd::make_unique<D6JointLimitConfiguration>(d6JointLimitConfig);
|
||||
}
|
||||
|
||||
AZ_Warning("PhysX Joint Utils", false, "Unsupported joint type in ComputeInitialJointLimitConfiguration");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* D6JointLimitConfiguration::GetTypeName()
|
||||
{
|
||||
return "D6 Joint";
|
||||
}
|
||||
|
||||
void D6JointLimitConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<D6JointLimitConfiguration, Physics::JointLimitConfiguration>()
|
||||
->Version(1)
|
||||
->Field("SwingLimitY", &D6JointLimitConfiguration::m_swingLimitY)
|
||||
->Field("SwingLimitZ", &D6JointLimitConfiguration::m_swingLimitZ)
|
||||
->Field("TwistLowerLimit", &D6JointLimitConfiguration::m_twistLimitLower)
|
||||
->Field("TwistUpperLimit", &D6JointLimitConfiguration::m_twistLimitUpper)
|
||||
;
|
||||
|
||||
AZ::EditContext* editContext = serializeContext->GetEditContext();
|
||||
if (editContext)
|
||||
{
|
||||
editContext->Class<D6JointLimitConfiguration>(
|
||||
"PhysX D6 Joint Configuration", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_swingLimitY, "Swing limit Y",
|
||||
"Maximum angle from the Y axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, JointConstants::MinSwingLimitDegrees)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_swingLimitZ, "Swing limit Z",
|
||||
"Maximum angle from the Z axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, JointConstants::MinSwingLimitDegrees)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_twistLimitLower, "Twist lower limit",
|
||||
"Lower limit for rotation about the X axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, -180.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_twistLimitUpper, "Twist upper limit",
|
||||
"Upper limit for rotation about the X axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, -180.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PhysX
|
||||
@@ -1,311 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Joint.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct SimulatedBody;
|
||||
}
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
class D6JointLimitConfiguration
|
||||
: public Physics::JointLimitConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(D6JointLimitConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(D6JointLimitConfiguration, "{90C5C23D-16C0-4F23-AD50-A190E402388E}", Physics::JointLimitConfiguration);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
const char* GetTypeName() override;
|
||||
|
||||
float m_swingLimitY = 45.0f; ///< Maximum angle in degrees from the Y axis of the joint frame.
|
||||
float m_swingLimitZ = 45.0f; ///< Maximum angle in degrees from the Z axis of the joint frame.
|
||||
float m_twistLimitLower = -45.0f; ///< Lower limit in degrees for rotation about the X axis of the joint frame.
|
||||
float m_twistLimitUpper = 45.0f; ///< Upper limit in degrees for rotation about the X axis of the joint frame.
|
||||
};
|
||||
|
||||
class Joint
|
||||
: public Physics::Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Joint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Joint, "{3C739E22-8EF0-419F-966B-C575A1F5A08B}", Physics::Joint);
|
||||
|
||||
Joint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody);
|
||||
|
||||
virtual ~Joint() = default;
|
||||
|
||||
AzPhysics::SimulatedBody* GetParentBody() const override;
|
||||
AzPhysics::SimulatedBody* GetChildBody() const override;
|
||||
void SetParentBody(AzPhysics::SimulatedBody* parentBody) override;
|
||||
void SetChildBody(AzPhysics::SimulatedBody* childBody) override;
|
||||
const AZStd::string& GetName() const override;
|
||||
void SetName(const AZStd::string& name) override;
|
||||
void* GetNativePointer() override;
|
||||
|
||||
protected:
|
||||
bool SetPxActors();
|
||||
|
||||
using PxJointUniquePtr = AZStd::unique_ptr<physx::PxJoint, AZStd::function<void(physx::PxJoint*)>>;
|
||||
PxJointUniquePtr m_pxJoint;
|
||||
AzPhysics::SimulatedBody* m_parentBody;
|
||||
AzPhysics::SimulatedBody* m_childBody;
|
||||
AZStd::string m_name;
|
||||
};
|
||||
|
||||
class D6Joint
|
||||
: public Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(D6Joint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(D6Joint, "{962C4044-2BD2-4E4C-913C-FB8E85A2A12A}", Joint);
|
||||
|
||||
D6Joint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody)
|
||||
: Joint(pxJoint, parentBody, childBody)
|
||||
{
|
||||
}
|
||||
virtual ~D6Joint() = default;
|
||||
|
||||
const AZ::Crc32 GetNativeType() const override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) override;
|
||||
};
|
||||
|
||||
struct D6JointState
|
||||
{
|
||||
float m_swingAngleY;
|
||||
float m_swingAngleZ;
|
||||
float m_twistAngle;
|
||||
};
|
||||
|
||||
/// A fixed joint locks 2 bodies relative to one another on all axes of freedom.
|
||||
class FixedJoint : public Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FixedJoint, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(FixedJoint, "{203FB99C-7DC5-478A-A52C-A1F2AAF61FB8}");
|
||||
|
||||
FixedJoint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody)
|
||||
: Joint(pxJoint, parentBody, childBody)
|
||||
{
|
||||
}
|
||||
|
||||
const AZ::Crc32 GetNativeType() const override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
float /*scale*/,
|
||||
AZ::u32 /*angularSubdivisions*/,
|
||||
AZ::u32 /*radialSubdivisions*/,
|
||||
AZStd::vector<AZ::Vector3>& /*vertexBufferOut*/,
|
||||
AZStd::vector<AZ::u32>& /*indexBufferOut*/,
|
||||
AZStd::vector<AZ::Vector3>& /*lineBufferOut*/,
|
||||
AZStd::vector<bool>& /*lineValidityBufferOut*/) override {}
|
||||
};
|
||||
|
||||
/// A hinge joint locks 2 bodies relative to one another except about the x-axis of the joint between them.
|
||||
class HingeJoint : public Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(HingeJoint, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(HingeJoint, "{8EFF1002-B08C-47CE-883C-82F0CF3736E0}");
|
||||
|
||||
HingeJoint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody)
|
||||
: Joint(pxJoint, parentBody, childBody)
|
||||
{
|
||||
}
|
||||
|
||||
const AZ::Crc32 GetNativeType() const override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
float /*scale*/,
|
||||
AZ::u32 /*angularSubdivisions*/,
|
||||
AZ::u32 /*radialSubdivisions*/,
|
||||
AZStd::vector<AZ::Vector3>& /*vertexBufferOut*/,
|
||||
AZStd::vector<AZ::u32>& /*indexBufferOut*/,
|
||||
AZStd::vector<AZ::Vector3>& /*lineBufferOut*/,
|
||||
AZStd::vector<bool>& /*lineValidityBufferOut*/) override {}
|
||||
};
|
||||
|
||||
/// A ball joint locks 2 bodies relative to one another except about the y and z axes of the joint between them.
|
||||
class BallJoint : public Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(BallJoint, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(BallJoint, "{9FADA1C2-0E2F-4E1B-9E83-6292A1606372}");
|
||||
|
||||
BallJoint(physx::PxJoint* pxJoint, AzPhysics::SimulatedBody* parentBody,
|
||||
AzPhysics::SimulatedBody* childBody)
|
||||
: Joint(pxJoint, parentBody, childBody)
|
||||
{
|
||||
}
|
||||
|
||||
const AZ::Crc32 GetNativeType() const override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
float /*scale*/,
|
||||
AZ::u32 /*angularSubdivisions*/,
|
||||
AZ::u32 /*radialSubdivisions*/,
|
||||
AZStd::vector<AZ::Vector3>& /*vertexBufferOut*/,
|
||||
AZStd::vector<AZ::u32>& /*indexBufferOut*/,
|
||||
AZStd::vector<AZ::Vector3>& /*lineBufferOut*/,
|
||||
AZStd::vector<bool>& /*lineValidityBufferOut*/) override {}
|
||||
};
|
||||
|
||||
/// Common parameters for all physics joint types.
|
||||
class GenericJointConfiguration
|
||||
{
|
||||
public:
|
||||
enum class GenericJointFlag : AZ::u16
|
||||
{
|
||||
None = 0,
|
||||
Breakable = 1,
|
||||
SelfCollide = 1 << 1
|
||||
};
|
||||
|
||||
AZ_CLASS_ALLOCATOR(GenericJointConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(GenericJointConfiguration, "{AB2E2F92-0248-48A8-9DDD-21284AF0C1DF}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static bool VersionConverter(
|
||||
AZ::SerializeContext& context,
|
||||
AZ::SerializeContext::DataElementNode& classElement);
|
||||
|
||||
GenericJointConfiguration() = default;
|
||||
GenericJointConfiguration(float forceMax,
|
||||
float torqueMax,
|
||||
AZ::Transform localTransformFromFollower,
|
||||
AZ::EntityId leadEntity,
|
||||
AZ::EntityId followerEntity,
|
||||
GenericJointFlag flags);
|
||||
|
||||
bool GetFlag(GenericJointFlag flag); ///< Returns if a particular flag is set as a bool.
|
||||
|
||||
GenericJointFlag m_flags = GenericJointFlag::None; ///< Flags that indicates if joint is breakable, self-colliding, etc.. Converting joint between breakable/non-breakable at game time is allowed.
|
||||
float m_forceMax = 1.0f; ///< Max force joint can tolerate before breaking.
|
||||
float m_torqueMax = 1.0f; ///< Max torque joint can tolerate before breaking.
|
||||
AZ::EntityId m_leadEntity; ///< EntityID for entity containing body that is lead to this joint constraint.
|
||||
AZ::EntityId m_followerEntity; ///< EntityID for entity containing body that is follower to this joint constraint.
|
||||
AZ::Transform m_localTransformFromFollower; ///< Joint's location and orientation in the frame (coordinate system) of the follower entity.
|
||||
};
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PhysX::GenericJointConfiguration::GenericJointFlag)
|
||||
|
||||
/// Generic pair of limit values for joint types, e.g. a pair of angular values.
|
||||
/// This is different from JointLimitConfiguration used in non-generic joints for character/ragdoll/animation.
|
||||
class GenericJointLimitsConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(GenericJointLimitsConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(GenericJointLimitsConfiguration, "{9D129B49-F4E6-4F2A-B94D-AC2D6AC6CE02}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
GenericJointLimitsConfiguration() = default;
|
||||
GenericJointLimitsConfiguration(float damping
|
||||
, bool isLimited
|
||||
, bool isSoftLimit
|
||||
, float limitFirst
|
||||
, float limitSecond
|
||||
, float stiffness
|
||||
, float tolerance);
|
||||
|
||||
bool m_isLimited = true; ///< Specifies if limits are applied to the joint constraints. E.g. if the swing angles are limited.
|
||||
bool m_isSoftLimit = false; ///< If limit is soft, spring and damping are used, otherwise tolerance is used. Converting between soft/hard limit at game time is allowed.
|
||||
float m_damping = 20.0f; ///< The damping strength of the drive, the force proportional to the velocity error. Used if limit is soft.
|
||||
float m_limitFirst = 45.0f; ///< Positive angle limit in the case of twist angle limits, Y-axis swing limit in the case of cone limits.
|
||||
float m_limitSecond = 45.0f; ///< Negative angle limit in the case of twist angle limits, Z-axis swing limit in the case of cone limits.
|
||||
float m_stiffness = 100.0f; ///< The spring strength of the drive, the force proportional to the position error. Used if limit is soft.
|
||||
float m_tolerance = 0.1f; ///< Distance from the joint at which limits becomes enforced. Used if limit is hard.
|
||||
};
|
||||
|
||||
class JointUtils
|
||||
{
|
||||
public:
|
||||
static AZStd::vector<AZ::TypeId> GetSupportedJointTypes();
|
||||
|
||||
static AZStd::shared_ptr<Physics::JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType);
|
||||
|
||||
static AZStd::shared_ptr<Physics::Joint> CreateJoint(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration,
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody);
|
||||
|
||||
static D6JointState CalculateD6JointState(
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Quaternion& childLocalRotation);
|
||||
|
||||
static bool IsD6SwingValid(
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ);
|
||||
|
||||
static void AppendD6SwingConeToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
static void AppendD6TwistArcToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
static void AppendD6CurrentTwistToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
static void GenerateJointLimitVisualizationData(
|
||||
const Physics::JointLimitConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
static AZStd::unique_ptr<Physics::JointLimitConfiguration> ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations);
|
||||
};
|
||||
} // namespace PhysX
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <PhysX_precompiled.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <Joint/PhysXJointUtils.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
JointGenericProperties::JointGenericProperties(GenericJointFlag flags, float forceMax, float torqueMax)
|
||||
: m_flags(flags)
|
||||
, m_forceMax(forceMax)
|
||||
, m_torqueMax(torqueMax)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
JointLimitProperties::JointLimitProperties(
|
||||
bool isLimited, bool isSoftLimit,
|
||||
float damping, float limitFirst, float limitSecond, float stiffness, float tolerance)
|
||||
: m_isLimited(isLimited)
|
||||
, m_isSoftLimit(isSoftLimit)
|
||||
, m_damping(damping)
|
||||
, m_limitFirst(limitFirst)
|
||||
, m_limitSecond(limitSecond)
|
||||
, m_stiffness(stiffness)
|
||||
, m_tolerance(tolerance)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool JointGenericProperties::IsFlagSet(GenericJointFlag flag) const
|
||||
{
|
||||
return static_cast<bool>(m_flags & flag);
|
||||
}
|
||||
|
||||
void D6JointLimitConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<D6JointLimitConfiguration, AzPhysics::JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("SwingLimitY", &D6JointLimitConfiguration::m_swingLimitY)
|
||||
->Field("SwingLimitZ", &D6JointLimitConfiguration::m_swingLimitZ)
|
||||
->Field("TwistLowerLimit", &D6JointLimitConfiguration::m_twistLimitLower)
|
||||
->Field("TwistUpperLimit", &D6JointLimitConfiguration::m_twistLimitUpper)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<D6JointLimitConfiguration>(
|
||||
"PhysX D6 Joint Configuration", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_swingLimitY, "Swing limit Y",
|
||||
"Maximum angle from the Y axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, JointConstants::MinSwingLimitDegrees)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_swingLimitZ, "Swing limit Z",
|
||||
"Maximum angle from the Z axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, JointConstants::MinSwingLimitDegrees)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_twistLimitLower, "Twist lower limit",
|
||||
"Lower limit for rotation about the X axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, -180.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &D6JointLimitConfiguration::m_twistLimitUpper, "Twist upper limit",
|
||||
"Upper limit for rotation about the X axis of the joint frame")
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " degrees")
|
||||
->Attribute(AZ::Edit::Attributes::Min, -180.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 180.0f)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JointGenericProperties::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointGenericProperties>()
|
||||
->Version(1)
|
||||
->Field("Maximum Force", &JointGenericProperties::m_forceMax)
|
||||
->Field("Maximum Torque", &JointGenericProperties::m_torqueMax)
|
||||
->Field("Flags", &JointGenericProperties::m_flags)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void JointLimitProperties::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointLimitProperties>()
|
||||
->Version(1)
|
||||
->Field("First Limit", &JointLimitProperties::m_limitFirst)
|
||||
->Field("Second Limit", &JointLimitProperties::m_limitSecond)
|
||||
->Field("Tolerance", &JointLimitProperties::m_tolerance)
|
||||
->Field("Is Limited", &JointLimitProperties::m_isLimited)
|
||||
->Field("Is Soft Limit", &JointLimitProperties::m_isSoftLimit)
|
||||
->Field("Damping", &JointLimitProperties::m_damping)
|
||||
->Field("Spring", &JointLimitProperties::m_stiffness)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void FixedJointConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<FixedJointConfiguration, AzPhysics::JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Generic Properties", &FixedJointConfiguration::m_genericProperties)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void BallJointConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<BallJointConfiguration, AzPhysics::JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Generic Properties", &BallJointConfiguration::m_genericProperties)
|
||||
->Field("Limit Properties", &BallJointConfiguration::m_limitProperties)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void HingeJointConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<HingeJointConfiguration, AzPhysics::JointConfiguration>()
|
||||
->Version(1)
|
||||
->Field("Generic Properties", &HingeJointConfiguration::m_genericProperties)
|
||||
->Field("Limit Properties", &HingeJointConfiguration::m_limitProperties)
|
||||
;
|
||||
}
|
||||
}
|
||||
} // namespace PhysX
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <PhysX_precompiled.h>
|
||||
#include <Joint/PhysXJoint.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <Include/PhysX/NativeTypeIdentifiers.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <Source/Joint/PhysXJointUtils.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
AzPhysics::SimulatedBodyHandle PhysXJoint::GetParentBodyHandle() const
|
||||
{
|
||||
return m_parentBodyHandle;
|
||||
}
|
||||
|
||||
AzPhysics::SimulatedBodyHandle PhysXJoint::GetChildBodyHandle() const
|
||||
{
|
||||
return m_childBodyHandle;
|
||||
}
|
||||
|
||||
PhysXJoint::PhysXJoint(
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
: m_sceneHandle(sceneHandle)
|
||||
, m_parentBodyHandle(parentBodyHandle)
|
||||
, m_childBodyHandle(childBodyHandle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool PhysXJoint::SetPxActors()
|
||||
{
|
||||
physx::PxRigidActor* parentActor = Utils::GetPxRigidActor(m_sceneHandle, m_parentBodyHandle);
|
||||
physx::PxRigidActor* childActor = Utils::GetPxRigidActor(m_sceneHandle, m_childBodyHandle);
|
||||
if (!parentActor && !childActor)
|
||||
{
|
||||
AZ_Error("PhysX Joint", false, "Invalid PhysX actors in joint - at least one must be a PxRigidActor.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pxJoint->setActors(parentActor, childActor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PhysXJoint::SetParentBody(AzPhysics::SimulatedBodyHandle parentBodyHandle)
|
||||
{
|
||||
auto* parentBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, parentBodyHandle);
|
||||
auto* childBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, m_childBodyHandle);
|
||||
|
||||
if (Utils::IsAtLeastOneDynamic(parentBody, childBody))
|
||||
{
|
||||
m_parentBodyHandle = parentBodyHandle;
|
||||
SetPxActors();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "Call to SetParentBody would result in invalid joint - at least one "
|
||||
"body in a joint must be dynamic.");
|
||||
}
|
||||
}
|
||||
|
||||
void PhysXJoint::SetChildBody(AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
auto* parentBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, m_parentBodyHandle);
|
||||
auto* childBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, childBodyHandle);
|
||||
|
||||
if (Utils::IsAtLeastOneDynamic(parentBody, childBody))
|
||||
{
|
||||
m_childBodyHandle = childBodyHandle;
|
||||
SetPxActors();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "Call to SetChildBody would result in invalid joint - at least one "
|
||||
"body in a joint must be dynamic.");
|
||||
}
|
||||
}
|
||||
|
||||
void* PhysXJoint::GetNativePointer() const
|
||||
{
|
||||
return m_pxJoint.get();
|
||||
}
|
||||
|
||||
PhysXD6Joint::PhysXD6Joint(const D6JointLimitConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
: PhysXJoint(sceneHandle, parentBodyHandle, childBodyHandle)
|
||||
{
|
||||
m_pxJoint = Utils::PxJointFactories::CreatePxD6Joint(configuration, sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
}
|
||||
|
||||
PhysXFixedJoint::PhysXFixedJoint(const FixedJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
: PhysXJoint(sceneHandle, parentBodyHandle, childBodyHandle)
|
||||
{
|
||||
m_pxJoint = Utils::PxJointFactories::CreatePxFixedJoint(configuration, sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
}
|
||||
|
||||
PhysXBallJoint::PhysXBallJoint(const BallJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
: PhysXJoint(sceneHandle, parentBodyHandle, childBodyHandle)
|
||||
{
|
||||
m_pxJoint = Utils::PxJointFactories::CreatePxBallJoint(configuration, sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
}
|
||||
|
||||
PhysXHingeJoint::PhysXHingeJoint(const HingeJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
: PhysXJoint(sceneHandle, parentBodyHandle, childBodyHandle)
|
||||
{
|
||||
m_pxJoint = Utils::PxJointFactories::CreatePxHingeJoint(configuration, sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
}
|
||||
|
||||
AZ::Crc32 PhysXD6Joint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::D6Joint;
|
||||
}
|
||||
|
||||
AZ::Crc32 PhysXFixedJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::FixedJoint;
|
||||
}
|
||||
|
||||
AZ::Crc32 PhysXBallJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::BallJoint;
|
||||
}
|
||||
|
||||
AZ::Crc32 PhysXHingeJoint::GetNativeType() const
|
||||
{
|
||||
return NativeTypeIdentifiers::HingeJoint;
|
||||
}
|
||||
|
||||
void PhysXD6Joint::GenerateJointLimitVisualizationData(
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
[[maybe_unused]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
[[maybe_unused]] AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
auto* parentBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, m_parentBodyHandle);
|
||||
auto* childBody = Utils::GetSimulatedBodyFromHandle(m_sceneHandle, m_childBodyHandle);
|
||||
|
||||
const AZ::u32 angularSubdivisionsClamped = AZ::GetClamp(angularSubdivisions, 4u, 32u);
|
||||
const AZ::u32 radialSubdivisionsClamped = AZ::GetClamp(radialSubdivisions, 1u, 4u);
|
||||
|
||||
const physx::PxD6Joint* joint = static_cast<physx::PxD6Joint*>(m_pxJoint.get());
|
||||
const AZ::Quaternion parentLocalRotation = PxMathConvert(joint->getLocalPose(physx::PxJointActorIndex::eACTOR0).q);
|
||||
const AZ::Quaternion parentWorldRotation = parentBody ? parentBody->GetOrientation() : AZ::Quaternion::CreateIdentity();
|
||||
const AZ::Quaternion childLocalRotation = PxMathConvert(joint->getLocalPose(physx::PxJointActorIndex::eACTOR1).q);
|
||||
const AZ::Quaternion childWorldRotation = childBody ? childBody->GetOrientation() : AZ::Quaternion::CreateIdentity();
|
||||
|
||||
const float swingAngleY = joint->getSwingYAngle();
|
||||
const float swingAngleZ = joint->getSwingZAngle();
|
||||
const float swingLimitY = joint->getSwingLimit().yAngle;
|
||||
const float swingLimitZ = joint->getSwingLimit().zAngle;
|
||||
const float twistAngle = joint->getTwist();
|
||||
const float twistLimitLower = joint->getTwistLimit().lower;
|
||||
const float twistLimitUpper = joint->getTwistLimit().upper;
|
||||
|
||||
Utils::Joints::AppendD6SwingConeToLineBuffer(
|
||||
parentLocalRotation, swingAngleY, swingAngleZ, swingLimitY, swingLimitZ,
|
||||
scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
Utils::Joints::AppendD6TwistArcToLineBuffer(
|
||||
parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper,
|
||||
scale, angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
Utils::Joints::AppendD6CurrentTwistToLineBuffer(
|
||||
parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper,
|
||||
scale, lineBufferOut, lineValidityBufferOut);
|
||||
|
||||
// draw the X-axis of the child joint frame
|
||||
// make the axis slightly longer than the radius of the twist arc so that it is easy to see
|
||||
float axisLength = 1.25f * scale;
|
||||
AZ::Vector3 childAxis = (parentWorldRotation.GetConjugate() * childWorldRotation * childLocalRotation).TransformVector(
|
||||
AZ::Vector3::CreateAxisX(axisLength));
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(childAxis);
|
||||
}
|
||||
} // namespace PhysX
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <Joint/PhysXJointUtils.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
class PhysXJoint
|
||||
: public AzPhysics::Joint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PhysXJoint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PhysXJoint, "{DBE1D185-E318-407D-A5A1-AC1DE7F4A62D}", AzPhysics::Joint);
|
||||
|
||||
PhysXJoint(
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
virtual ~PhysXJoint() = default;
|
||||
|
||||
AzPhysics::SimulatedBodyHandle GetParentBodyHandle() const override;
|
||||
AzPhysics::SimulatedBodyHandle GetChildBodyHandle() const override;
|
||||
void SetParentBody(AzPhysics::SimulatedBodyHandle parentBody) override;
|
||||
void SetChildBody(AzPhysics::SimulatedBodyHandle childBody) override;
|
||||
void* GetNativePointer() const override;
|
||||
|
||||
protected:
|
||||
bool SetPxActors();
|
||||
|
||||
Utils::PxJointUniquePtr m_pxJoint;
|
||||
AzPhysics::SceneHandle m_sceneHandle;
|
||||
AzPhysics::SimulatedBodyHandle m_parentBodyHandle;
|
||||
AzPhysics::SimulatedBodyHandle m_childBodyHandle;
|
||||
AZStd::string m_name;
|
||||
};
|
||||
|
||||
class PhysXD6Joint
|
||||
: public PhysXJoint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PhysXD6Joint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PhysXD6Joint, "{144B2FAF-A3EE-4FE1-9328-2C44FE1E3676}", PhysX::PhysXJoint);
|
||||
|
||||
PhysXD6Joint(const D6JointLimitConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
virtual ~PhysXD6Joint() = default;
|
||||
|
||||
AZ::Crc32 GetNativeType() const override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) override;
|
||||
};
|
||||
|
||||
//! A fixed joint locks 2 bodies relative to one another on all axes of freedom.
|
||||
class PhysXFixedJoint : public PhysXJoint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PhysXFixedJoint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PhysXFixedJoint, "{B821D6D8-7B41-479D-9325-F9BC9754C5F8}", PhysX::PhysXJoint);
|
||||
|
||||
PhysXFixedJoint(const FixedJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
virtual ~PhysXFixedJoint() = default;
|
||||
|
||||
AZ::Crc32 GetNativeType() const override;
|
||||
};
|
||||
|
||||
//! A ball joint locks 2 bodies relative to one another except about the y and z axes of the joint between them.
|
||||
class PhysXBallJoint : public PhysXJoint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PhysXBallJoint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PhysXBallJoint, "{9494CE43-3AE2-40AB-ADF7-FDC5F8B0F15A}", PhysX::PhysXJoint);
|
||||
|
||||
PhysXBallJoint(const BallJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
virtual ~PhysXBallJoint() = default;
|
||||
|
||||
AZ::Crc32 GetNativeType() const override;
|
||||
};
|
||||
|
||||
//! A hinge joint locks 2 bodies relative to one another except about the x-axis of the joint between them.
|
||||
class PhysXHingeJoint : public PhysXJoint
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PhysXHingeJoint, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PhysXHingeJoint, "{9C5B955C-6C80-45FA-855D-DDA449C85313}", PhysX::PhysXJoint);
|
||||
|
||||
PhysXHingeJoint(const HingeJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
virtual ~PhysXHingeJoint() = default;
|
||||
|
||||
AZ::Crc32 GetNativeType() const override;
|
||||
};
|
||||
} // namespace PhysX
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <PhysX_precompiled.h>
|
||||
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <Source/Joint/PhysXJointUtils.h>
|
||||
#include <Include/PhysX/NativeTypeIdentifiers.h>
|
||||
|
||||
namespace PhysX {
|
||||
namespace Utils
|
||||
{
|
||||
struct PxJointActorData
|
||||
{
|
||||
static PxJointActorData InvalidPxJointActorData;
|
||||
|
||||
physx::PxRigidActor* parentActor = nullptr;
|
||||
physx::PxRigidActor* childActor = nullptr;
|
||||
};
|
||||
PxJointActorData PxJointActorData::InvalidPxJointActorData;
|
||||
|
||||
PxJointActorData GetJointPxActors(
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
auto* parentBody = GetSimulatedBodyFromHandle(sceneHandle, parentBodyHandle);
|
||||
auto* childBody = GetSimulatedBodyFromHandle(sceneHandle, childBodyHandle);
|
||||
|
||||
if (!IsAtLeastOneDynamic(parentBody, childBody))
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be dynamic.");
|
||||
return PxJointActorData::InvalidPxJointActorData;
|
||||
}
|
||||
|
||||
physx::PxRigidActor* parentActor = GetPxRigidActor(sceneHandle, parentBodyHandle);
|
||||
physx::PxRigidActor* childActor = GetPxRigidActor(sceneHandle, childBodyHandle);
|
||||
|
||||
if (!parentActor && !childActor)
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be a PxRigidActor.");
|
||||
return PxJointActorData::InvalidPxJointActorData;
|
||||
}
|
||||
|
||||
return PxJointActorData{
|
||||
parentActor,
|
||||
childActor
|
||||
};
|
||||
}
|
||||
|
||||
bool IsAtLeastOneDynamic(AzPhysics::SimulatedBody* body0,
|
||||
AzPhysics::SimulatedBody* body1)
|
||||
{
|
||||
for (const AzPhysics::SimulatedBody* body : { body0, body1 })
|
||||
{
|
||||
if (body)
|
||||
{
|
||||
if (body->GetNativeType() == NativeTypeIdentifiers::RigidBody ||
|
||||
body->GetNativeType() == NativeTypeIdentifiers::ArticulationLink)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
physx::PxRigidActor* GetPxRigidActor(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle worldBodyHandle)
|
||||
{
|
||||
auto* worldBody = GetSimulatedBodyFromHandle(sceneHandle, worldBodyHandle);
|
||||
if (worldBody != nullptr
|
||||
&& static_cast<physx::PxBase*>(worldBody->GetNativePointer())->is<physx::PxRigidActor>())
|
||||
{
|
||||
return static_cast<physx::PxRigidActor*>(worldBody->GetNativePointer());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ReleasePxJoint(physx::PxJoint* joint)
|
||||
{
|
||||
PHYSX_SCENE_WRITE_LOCK(joint->getScene());
|
||||
joint->userData = nullptr;
|
||||
joint->release();
|
||||
}
|
||||
|
||||
AzPhysics::SimulatedBody* GetSimulatedBodyFromHandle(AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle bodyHandle)
|
||||
{
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
return sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void InitializeGenericProperties(const JointGenericProperties& properties, physx::PxJoint* nativeJoint)
|
||||
{
|
||||
if (!nativeJoint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PHYSX_SCENE_WRITE_LOCK(nativeJoint->getScene());
|
||||
nativeJoint->setConstraintFlag(
|
||||
physx::PxConstraintFlag::eCOLLISION_ENABLED,
|
||||
properties.IsFlagSet(JointGenericProperties::GenericJointFlag::SelfCollide));
|
||||
|
||||
if (properties.IsFlagSet(JointGenericProperties::GenericJointFlag::Breakable))
|
||||
{
|
||||
nativeJoint->setBreakForce(properties.m_forceMax, properties.m_torqueMax);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeSphericalLimitProperties(const JointLimitProperties& properties, physx::PxSphericalJoint* nativeJoint)
|
||||
{
|
||||
if (!nativeJoint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!properties.m_isLimited)
|
||||
{
|
||||
nativeJoint->setSphericalJointFlag(physx::PxSphericalJointFlag::eLIMIT_ENABLED, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hard limit uses a tolerance value (distance to limit at which limit becomes active).
|
||||
// Soft limit allows angle to exceed limit but springs back with configurable spring stiffness and damping.
|
||||
physx::PxJointLimitCone swingLimit(
|
||||
AZ::DegToRad(properties.m_limitFirst),
|
||||
AZ::DegToRad(properties.m_limitSecond),
|
||||
properties.m_tolerance);
|
||||
|
||||
if (properties.m_isSoftLimit)
|
||||
{
|
||||
swingLimit.stiffness = properties.m_stiffness;
|
||||
swingLimit.damping = properties.m_damping;
|
||||
}
|
||||
|
||||
nativeJoint->setLimitCone(swingLimit);
|
||||
nativeJoint->setSphericalJointFlag(physx::PxSphericalJointFlag::eLIMIT_ENABLED, true);
|
||||
}
|
||||
|
||||
void InitializeRevoluteLimitProperties(const JointLimitProperties& properties, physx::PxRevoluteJoint* nativeJoint)
|
||||
{
|
||||
if (!nativeJoint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!properties.m_isLimited)
|
||||
{
|
||||
nativeJoint->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eLIMIT_ENABLED, false);
|
||||
return;
|
||||
}
|
||||
|
||||
physx::PxJointAngularLimitPair limitPair(
|
||||
AZ::DegToRad(properties.m_limitSecond),
|
||||
AZ::DegToRad(properties.m_limitFirst),
|
||||
properties.m_tolerance);
|
||||
|
||||
if (properties.m_isSoftLimit)
|
||||
{
|
||||
limitPair.stiffness = properties.m_stiffness;
|
||||
limitPair.damping = properties.m_damping;
|
||||
}
|
||||
|
||||
nativeJoint->setLimit(limitPair);
|
||||
nativeJoint->setRevoluteJointFlag(physx::PxRevoluteJointFlag::eLIMIT_ENABLED, true);
|
||||
}
|
||||
|
||||
namespace PxJointFactories
|
||||
{
|
||||
PxJointUniquePtr CreatePxD6Joint(
|
||||
const PhysX::D6JointLimitConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const physx::PxTransform parentWorldTransform =
|
||||
actorData.parentActor ? actorData.parentActor->getGlobalPose() : physx::PxTransform(physx::PxIdentity);
|
||||
const physx::PxTransform childWorldTransform =
|
||||
actorData.childActor ? actorData.childActor->getGlobalPose() : physx::PxTransform(physx::PxIdentity);
|
||||
const physx::PxVec3 childOffset = childWorldTransform.p - parentWorldTransform.p;
|
||||
physx::PxTransform parentLocalTransform(PxMathConvert(configuration.m_parentLocalRotation).getNormalized());
|
||||
const physx::PxTransform childLocalTransform(PxMathConvert(configuration.m_childLocalRotation).getNormalized());
|
||||
parentLocalTransform.p = parentWorldTransform.q.rotateInv(childOffset);
|
||||
|
||||
physx::PxD6Joint* joint = PxD6JointCreate(PxGetPhysics(),
|
||||
actorData.parentActor, parentLocalTransform, actorData.childActor, childLocalTransform);
|
||||
|
||||
joint->setMotion(physx::PxD6Axis::eTWIST, physx::PxD6Motion::eLIMITED);
|
||||
joint->setMotion(physx::PxD6Axis::eSWING1, physx::PxD6Motion::eLIMITED);
|
||||
joint->setMotion(physx::PxD6Axis::eSWING2, physx::PxD6Motion::eLIMITED);
|
||||
|
||||
AZ_Warning("PhysX Joint",
|
||||
configuration.m_swingLimitY >= JointConstants::MinSwingLimitDegrees && configuration.m_swingLimitZ >= JointConstants::MinSwingLimitDegrees,
|
||||
"Very small swing limit requested for joint between \"%s\" and \"%s\", increasing to %f degrees to improve stability",
|
||||
actorData.parentActor ? actorData.parentActor->getName() : "world",
|
||||
actorData.childActor ? actorData.childActor->getName() : "world",
|
||||
JointConstants::MinSwingLimitDegrees);
|
||||
|
||||
const float swingLimitY = AZ::DegToRad(AZ::GetMax(JointConstants::MinSwingLimitDegrees, configuration.m_swingLimitY));
|
||||
const float swingLimitZ = AZ::DegToRad(AZ::GetMax(JointConstants::MinSwingLimitDegrees, configuration.m_swingLimitZ));
|
||||
physx::PxJointLimitCone limitCone(swingLimitY, swingLimitZ);
|
||||
joint->setSwingLimit(limitCone);
|
||||
|
||||
const float twistLower = AZ::DegToRad(AZStd::GetMin(configuration.m_twistLimitLower, configuration.m_twistLimitUpper));
|
||||
const float twistUpper = AZ::DegToRad(AZStd::GetMax(configuration.m_twistLimitLower, configuration.m_twistLimitUpper));
|
||||
physx::PxJointAngularLimitPair twistLimitPair(twistLower, twistUpper);
|
||||
joint->setTwistLimit(twistLimitPair);
|
||||
|
||||
return Utils::PxJointUniquePtr(joint, ReleasePxJoint);
|
||||
}
|
||||
|
||||
PxJointUniquePtr CreatePxFixedJoint(
|
||||
const PhysX::FixedJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
physx::PxFixedJoint* joint;
|
||||
const AZ::Transform parentLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_parentLocalRotation, configuration.m_parentLocalPosition);
|
||||
const AZ::Transform childLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_childLocalRotation, configuration.m_childLocalPosition);
|
||||
|
||||
{
|
||||
PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene());
|
||||
joint = physx::PxFixedJointCreate(PxGetPhysics(),
|
||||
actorData.parentActor, PxMathConvert(parentLocalTM),
|
||||
actorData.childActor, PxMathConvert(childLocalTM));
|
||||
}
|
||||
|
||||
InitializeGenericProperties(
|
||||
configuration.m_genericProperties,
|
||||
static_cast<physx::PxJoint*>(joint));
|
||||
|
||||
return Utils::PxJointUniquePtr(joint, ReleasePxJoint);
|
||||
}
|
||||
|
||||
PxJointUniquePtr CreatePxBallJoint(
|
||||
const PhysX::BallJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
physx::PxSphericalJoint* joint;
|
||||
const AZ::Transform parentLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_parentLocalRotation, configuration.m_parentLocalPosition);
|
||||
const AZ::Transform childLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_childLocalRotation, configuration.m_childLocalPosition);
|
||||
|
||||
{
|
||||
PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene());
|
||||
joint = physx::PxSphericalJointCreate(PxGetPhysics(),
|
||||
actorData.parentActor, PxMathConvert(parentLocalTM),
|
||||
actorData.childActor, PxMathConvert(childLocalTM));
|
||||
}
|
||||
|
||||
InitializeSphericalLimitProperties(configuration.m_limitProperties, joint);
|
||||
InitializeGenericProperties(
|
||||
configuration.m_genericProperties,
|
||||
static_cast<physx::PxJoint*>(joint));
|
||||
|
||||
return Utils::PxJointUniquePtr(joint, ReleasePxJoint);
|
||||
}
|
||||
|
||||
PxJointUniquePtr CreatePxHingeJoint(
|
||||
const PhysX::HingeJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle)
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
physx::PxRevoluteJoint* joint;
|
||||
const AZ::Transform parentLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_parentLocalRotation, configuration.m_parentLocalPosition);
|
||||
const AZ::Transform childLocalTM = AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
configuration.m_childLocalRotation, configuration.m_childLocalPosition);
|
||||
|
||||
{
|
||||
PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene());
|
||||
joint = physx::PxRevoluteJointCreate(PxGetPhysics(),
|
||||
actorData.parentActor, PxMathConvert(parentLocalTM),
|
||||
actorData.childActor, PxMathConvert(childLocalTM));
|
||||
}
|
||||
|
||||
InitializeRevoluteLimitProperties(configuration.m_limitProperties, joint);
|
||||
InitializeGenericProperties(
|
||||
configuration.m_genericProperties,
|
||||
static_cast<physx::PxJoint*>(joint));
|
||||
|
||||
return Utils::PxJointUniquePtr(joint, ReleasePxJoint);
|
||||
}
|
||||
} // namespace PxJointFactories
|
||||
|
||||
namespace Joints
|
||||
{
|
||||
bool IsD6SwingValid(float swingAngleY, float swingAngleZ, float swingLimitY, float swingLimitZ)
|
||||
{
|
||||
const float epsilon = AZ::Constants::FloatEpsilon;
|
||||
const float yFactor = AZStd::tan(0.25f * swingAngleY) / AZStd::GetMax(epsilon, AZStd::tan(0.25f * swingLimitY));
|
||||
const float zFactor = AZStd::tan(0.25f * swingAngleZ) / AZStd::GetMax(epsilon, AZStd::tan(0.25f * swingLimitZ));
|
||||
|
||||
return (yFactor * yFactor + zFactor * zFactor <= 1.0f + epsilon);
|
||||
}
|
||||
|
||||
void AppendD6SwingConeToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesSwingCone = angularSubdivisions * (1u + radialSubdivisions);
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesSwingCone);
|
||||
lineValidityBufferOut.reserve(lineValidityBufferOut.size() + numLinesSwingCone);
|
||||
|
||||
// the orientation quat for a radial line in the cone can be represented in terms of sin and cos half angles
|
||||
// these expressions can be efficiently calculated using tan quarter angles as follows:
|
||||
// writing t = tan(x / 4)
|
||||
// sin(x / 2) = 2 * t / (1 + t * t)
|
||||
// cos(x / 2) = (1 - t * t) / (1 + t * t)
|
||||
const float tanQuarterSwingZ = AZStd::tan(0.25f * swingLimitZ);
|
||||
const float tanQuarterSwingY = AZStd::tan(0.25f * swingLimitY);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = AZ::Constants::TwoPi / angularSubdivisions * angularIndex;
|
||||
// the axis about which to rotate the x-axis to get the radial vector for this segment of the cone
|
||||
const AZ::Vector3 rotationAxis(0, -tanQuarterSwingY * sinf(angle), tanQuarterSwingZ * cosf(angle));
|
||||
const float normalizationFactor = rotationAxis.GetLengthSq();
|
||||
const AZ::Quaternion radialVectorRotation = 1.0f / (1.0f + normalizationFactor) *
|
||||
AZ::Quaternion::CreateFromVector3AndValue(2.0f * rotationAxis, 1.0f - normalizationFactor);
|
||||
const AZ::Vector3 radialVector =
|
||||
(parentLocalRotation * radialVectorRotation).TransformVector(AZ::Vector3::CreateAxisX(scale));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
if (angularIndex < angularSubdivisions)
|
||||
{
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
}
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool swingValid = IsD6SwingValid(swingAngleY, swingAngleZ, swingLimitY, swingLimitZ);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesSwingCone, swingValid);
|
||||
}
|
||||
|
||||
void AppendD6TwistArcToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesTwistArc = angularSubdivisions * (1u + radialSubdivisions) + 1u;
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesTwistArc);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
const float twistRange = twistLimitUpper - twistLimitLower;
|
||||
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = twistLimitLower + twistRange / angularSubdivisions * angularIndex;
|
||||
const AZ::Vector3 radialVector =
|
||||
parentLocalRotation.TransformVector(scale * AZ::Vector3(0.0f, cosf(angle), sinf(angle)));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
const float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool twistValid = (twistAngle >= twistLimitLower && twistAngle <= twistLimitUpper);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesTwistArc, twistValid);
|
||||
}
|
||||
|
||||
void AppendD6CurrentTwistToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
[[maybe_unused]] float twistLimitLower,
|
||||
[[maybe_unused]] float twistLimitUpper,
|
||||
float scale,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::Vector3 twistVector =
|
||||
parentLocalRotation.TransformVector(1.25f * scale * AZ::Vector3(0.0f, cosf(twistAngle), sinf(twistAngle)));
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(twistVector);
|
||||
lineValidityBufferOut.push_back(true);
|
||||
}
|
||||
} // namespace Joints
|
||||
} // namespace Utils
|
||||
} // namespace PhysX
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
|
||||
#include <PxPhysicsAPI.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
namespace JointConstants
|
||||
{
|
||||
// Setting swing limits to very small values can cause extreme stability problems, so clamp above a small
|
||||
// threshold.
|
||||
static const float MinSwingLimitDegrees = 1.0f;
|
||||
} // namespace JointConstants
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
using PxJointUniquePtr = AZStd::unique_ptr<physx::PxJoint, AZStd::function<void(physx::PxJoint*)>>;
|
||||
|
||||
bool IsAtLeastOneDynamic(AzPhysics::SimulatedBody* body0, AzPhysics::SimulatedBody* body1);
|
||||
|
||||
physx::PxRigidActor* GetPxRigidActor(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle worldBodyHandle);
|
||||
AzPhysics::SimulatedBody* GetSimulatedBodyFromHandle(
|
||||
AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle);
|
||||
|
||||
namespace PxJointFactories
|
||||
{
|
||||
PxJointUniquePtr CreatePxD6Joint(const PhysX::D6JointLimitConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
PxJointUniquePtr CreatePxFixedJoint(const PhysX::FixedJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
PxJointUniquePtr CreatePxBallJoint(const PhysX::BallJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
|
||||
PxJointUniquePtr CreatePxHingeJoint(const PhysX::HingeJointConfiguration& configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle);
|
||||
} // namespace PxActorFactories
|
||||
|
||||
namespace Joints
|
||||
{
|
||||
bool IsD6SwingValid(float swingAngleY, float swingAngleZ, float swingLimitY, float swingLimitZ);
|
||||
|
||||
void AppendD6SwingConeToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
void AppendD6TwistArcToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
|
||||
void AppendD6CurrentTwistToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut);
|
||||
} // namespace Joints
|
||||
} // namespace Utils
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -18,33 +18,65 @@
|
||||
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
|
||||
#include <PhysX/NativeTypeIdentifiers.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <Source/Joint.h>
|
||||
#include <Source/JointComponent.h>
|
||||
#include <Source/Utils.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
void JointComponent::Reflect(AZ::ReflectContext* context)
|
||||
JointComponentConfiguration::JointComponentConfiguration(
|
||||
AZ::Transform localTransformFromFollower,
|
||||
AZ::EntityId leadEntity,
|
||||
AZ::EntityId followerEntity)
|
||||
: m_localTransformFromFollower(localTransformFromFollower)
|
||||
, m_leadEntity(leadEntity)
|
||||
, m_followerEntity(followerEntity)
|
||||
{
|
||||
}
|
||||
|
||||
void JointComponentConfiguration::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointComponentConfiguration>()
|
||||
->Version(2)
|
||||
->Field("Follower Local Transform", &JointComponentConfiguration::m_localTransformFromFollower)
|
||||
->Field("Lead Entity", &JointComponentConfiguration::m_leadEntity)
|
||||
->Field("Follower Entity", &JointComponentConfiguration::m_followerEntity)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void JointComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
JointComponentConfiguration::Reflect(context);
|
||||
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<JointComponent, AZ::Component>()
|
||||
->Version(1)
|
||||
->Version(2)
|
||||
->Field("Joint Configuration", &JointComponent::m_configuration)
|
||||
->Field("Joint Generic Properties", &JointComponent::m_genericProperties)
|
||||
->Field("Joint Limits", &JointComponent::m_limits)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
JointComponent::JointComponent(const GenericJointConfiguration& config)
|
||||
: m_configuration(config)
|
||||
JointComponent::JointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties)
|
||||
: m_configuration(configuration)
|
||||
, m_genericProperties(genericProperties)
|
||||
{
|
||||
}
|
||||
|
||||
JointComponent::JointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& limits)
|
||||
: m_configuration(AZStd::move(config))
|
||||
, m_limits(limits)
|
||||
JointComponent::JointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties)
|
||||
: m_configuration(configuration)
|
||||
, m_genericProperties(genericProperties)
|
||||
, m_limits(limitProperties)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -67,16 +99,22 @@ namespace PhysX
|
||||
void JointComponent::Deactivate()
|
||||
{
|
||||
AZ::EntityBus::Handler::BusDisconnect();
|
||||
m_joint.reset();
|
||||
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
||||
{
|
||||
if (auto* scene = physicsSystem->GetScene(m_jointSceneOwner))
|
||||
{
|
||||
scene->RemoveJoint(m_jointHandle);
|
||||
m_jointSceneOwner = AzPhysics::InvalidSceneHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
physx::PxTransform JointComponent::GetJointLocalPose(const physx::PxRigidActor* actor
|
||||
, const physx::PxTransform& jointPose)
|
||||
AZ::Transform JointComponent::GetJointLocalPose(const physx::PxRigidActor* actor, const AZ::Transform& jointPose)
|
||||
{
|
||||
if (!actor)
|
||||
{
|
||||
AZ_Error("JointComponent::GetJointLocalPose", false, "Can't get pose for invalid actor pointer.");
|
||||
return physx::PxTransform();
|
||||
return AZ::Transform::CreateIdentity();
|
||||
}
|
||||
|
||||
PHYSX_SCENE_READ_LOCK(actor->getScene());
|
||||
@@ -84,41 +122,17 @@ namespace PhysX
|
||||
physx::PxTransform actorTranslateInv(-actorPose.p);
|
||||
physx::PxTransform actorRotateInv(actorPose.q);
|
||||
actorRotateInv = actorRotateInv.getInverse();
|
||||
return actorRotateInv * actorTranslateInv * jointPose;
|
||||
return PxMathConvert(actorRotateInv * actorTranslateInv) * jointPose;
|
||||
}
|
||||
|
||||
AZ::Transform JointComponent::GetJointTransform(AZ::EntityId entityId
|
||||
, const GenericJointConfiguration& jointConfig)
|
||||
, const JointComponentConfiguration& jointConfig)
|
||||
{
|
||||
AZ::Transform jointTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(entityId);
|
||||
jointTransform = jointTransform * jointConfig.m_localTransformFromFollower;
|
||||
return jointTransform;
|
||||
}
|
||||
|
||||
void JointComponent::InitGenericProperties()
|
||||
{
|
||||
if (!m_joint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
physx::PxJoint* jointNative = static_cast<physx::PxJoint*>(m_joint->GetNativePointer());
|
||||
if (!jointNative)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PHYSX_SCENE_WRITE_LOCK(jointNative->getScene());
|
||||
jointNative->setConstraintFlag(
|
||||
physx::PxConstraintFlag::eCOLLISION_ENABLED,
|
||||
m_configuration.GetFlag(GenericJointConfiguration::GenericJointFlag::SelfCollide));
|
||||
|
||||
if (m_configuration.GetFlag(GenericJointConfiguration::GenericJointFlag::Breakable))
|
||||
{
|
||||
jointNative->setBreakForce(m_configuration.m_forceMax
|
||||
, m_configuration.m_torqueMax);
|
||||
}
|
||||
}
|
||||
|
||||
void JointComponent::ObtainLeadFollowerInfo(JointComponent::LeadFollowerInfo& info)
|
||||
{
|
||||
info = LeadFollowerInfo();
|
||||
@@ -160,16 +174,15 @@ namespace PhysX
|
||||
|
||||
const AZ::Transform jointTransform = GetJointTransform(GetEntityId(), m_configuration);
|
||||
|
||||
physx::PxTransform jointPose = PxMathConvert(jointTransform);
|
||||
if (info.m_leadActor)
|
||||
{
|
||||
info.m_leadLocal = GetJointLocalPose(info.m_leadActor, jointPose); // joint position & orientation in lead actor's frame.
|
||||
info.m_leadLocal = GetJointLocalPose(info.m_leadActor, jointTransform); // joint position & orientation in lead actor's frame.
|
||||
}
|
||||
else
|
||||
{
|
||||
info.m_leadLocal = jointPose; // lead is null, attaching follower to global position of joint.
|
||||
info.m_leadLocal = jointTransform; // lead is null, attaching follower to global position of joint.
|
||||
}
|
||||
info.m_followerLocal = PxMathConvert(m_configuration.m_localTransformFromFollower);// joint position & orientation in follower actor's frame.
|
||||
info.m_followerLocal = m_configuration.m_localTransformFromFollower;// joint position & orientation in follower actor's frame.
|
||||
}
|
||||
|
||||
void JointComponent::WarnInvalidJointSetup(AZ::EntityId entityId, const AZStd::string& message)
|
||||
@@ -189,7 +202,6 @@ namespace PhysX
|
||||
if (!m_configuration.m_leadEntity.IsValid() || entityId == m_configuration.m_leadEntity)
|
||||
{
|
||||
InitNativeJoint(); // Invoke overriden specific joint type instantiation
|
||||
InitGenericProperties();
|
||||
}
|
||||
// Else, follower entity is activated, subscribe to be notified that lead entity is activated.
|
||||
else
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
#include <Source/Joint.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
@@ -27,6 +27,24 @@ namespace AzPhysics
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
class JointComponentConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(JointComponentConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_TYPE_INFO(JointComponentConfiguration, "{1454F33F-AA6E-424B-A70C-9E463FBDEA19}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointComponentConfiguration() = default;
|
||||
JointComponentConfiguration(
|
||||
AZ::Transform localTransformFromFollower,
|
||||
AZ::EntityId leadEntity,
|
||||
AZ::EntityId followerEntity);
|
||||
|
||||
AZ::EntityId m_leadEntity; ///< EntityID for entity containing body that is lead to this joint constraint.
|
||||
AZ::EntityId m_followerEntity; ///< EntityID for entity containing body that is follower to this joint constraint.
|
||||
AZ::Transform m_localTransformFromFollower; ///< Joint's location and orientation in the frame (coordinate system) of the follower entity.
|
||||
};
|
||||
|
||||
/// Base class for game-time generic joint components.
|
||||
class JointComponent: public AZ::Component
|
||||
, protected AZ::EntityBus::Handler
|
||||
@@ -36,9 +54,13 @@ namespace PhysX
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JointComponent() = default;
|
||||
explicit JointComponent(const GenericJointConfiguration& config);
|
||||
JointComponent(const GenericJointConfiguration& config
|
||||
, const GenericJointLimitsConfiguration& limits);
|
||||
JointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties);
|
||||
JointComponent(
|
||||
const JointComponentConfiguration& configuration,
|
||||
const JointGenericProperties& genericProperties,
|
||||
const JointLimitProperties& limitProperties);
|
||||
|
||||
protected:
|
||||
/// Struct to provide subclasses with native pointers during joint initialization.
|
||||
@@ -47,8 +69,8 @@ namespace PhysX
|
||||
{
|
||||
physx::PxRigidActor* m_leadActor = nullptr;
|
||||
physx::PxRigidActor* m_followerActor = nullptr;
|
||||
physx::PxTransform m_leadLocal = physx::PxTransform(physx::PxIdentity);
|
||||
physx::PxTransform m_followerLocal = physx::PxTransform(physx::PxIdentity);
|
||||
AZ::Transform m_leadLocal = AZ::Transform::CreateIdentity();
|
||||
AZ::Transform m_followerLocal = AZ::Transform::CreateIdentity();
|
||||
AzPhysics::SimulatedBody* m_leadBody = nullptr;
|
||||
AzPhysics::SimulatedBody* m_followerBody = nullptr;
|
||||
};
|
||||
@@ -63,14 +85,10 @@ namespace PhysX
|
||||
/// Invoked in JointComponent::OnEntityActivated for specific joint types to instantiate native joint pointer.
|
||||
virtual void InitNativeJoint() {};
|
||||
|
||||
physx::PxTransform GetJointLocalPose(const physx::PxRigidActor* actor,
|
||||
const physx::PxTransform& jointPose);
|
||||
AZ::Transform GetJointLocalPose(const physx::PxRigidActor* actor, const AZ::Transform& jointPose);
|
||||
|
||||
AZ::Transform GetJointTransform(AZ::EntityId entityId,
|
||||
const GenericJointConfiguration& jointConfig);
|
||||
|
||||
/// Initializes joint properties common to all native joint types after native joint creation.
|
||||
void InitGenericProperties();
|
||||
const JointComponentConfiguration& jointConfig);
|
||||
|
||||
/// Used on initialization by sub-classes to get native pointers from entity IDs.
|
||||
/// This allows sub-classes to instantiate specific native types. This base class does not need knowledge of any specific joint type.
|
||||
@@ -79,8 +97,11 @@ namespace PhysX
|
||||
/// Issues warnings for invalid scenarios when initializing a joint from entity IDs.
|
||||
void WarnInvalidJointSetup(AZ::EntityId entityId, const AZStd::string& message);
|
||||
|
||||
GenericJointConfiguration m_configuration;
|
||||
GenericJointLimitsConfiguration m_limits;
|
||||
AZStd::shared_ptr<PhysX::Joint> m_joint = nullptr;
|
||||
|
||||
JointComponentConfiguration m_configuration;
|
||||
JointGenericProperties m_genericProperties;
|
||||
JointLimitProperties m_limits;
|
||||
AzPhysics::JointHandle m_jointHandle = AzPhysics::InvalidJointHandle;
|
||||
AzPhysics::SceneHandle m_jointSceneOwner = AzPhysics::InvalidSceneHandle;
|
||||
};
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#include <AzFramework/Physics/MaterialBus.h>
|
||||
#include <cfloat>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <Source/RigidBody.h>
|
||||
#include <Source/Scene/PhysXScene.h>
|
||||
#include <Source/Shape.h>
|
||||
#include <Source/Joint.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
@@ -262,21 +262,24 @@ namespace PhysX
|
||||
physx::PxTransform parentTM(parentOffset);
|
||||
physx::PxTransform childTM(physx::PxIdentity);
|
||||
|
||||
AZStd::shared_ptr<Physics::JointLimitConfiguration> jointLimitConfig = configuration.m_nodes[nodeIndex].m_jointLimit;
|
||||
if (!jointLimitConfig)
|
||||
AZStd::shared_ptr<AzPhysics::JointConfiguration> jointConfig = configuration.m_nodes[nodeIndex].m_jointConfig;
|
||||
if (!jointConfig)
|
||||
{
|
||||
AZStd::vector<AZ::TypeId> supportedJointLimitTypes = JointUtils::GetSupportedJointTypes();
|
||||
|
||||
if (!supportedJointLimitTypes.empty())
|
||||
{
|
||||
jointLimitConfig = JointUtils::CreateJointLimitConfiguration(supportedJointLimitTypes[0]);
|
||||
}
|
||||
jointConfig = AZStd::make_shared<D6JointLimitConfiguration>();
|
||||
}
|
||||
|
||||
AzPhysics::JointHandle jointHandle = sceneInterface->AddJoint(
|
||||
sceneHandle, jointConfig.get(),
|
||||
ragdoll->GetNode(parentIndex)->GetRigidBody().m_bodyHandle,
|
||||
ragdoll->GetNode(nodeIndex)->GetRigidBody().m_bodyHandle);
|
||||
|
||||
AZStd::shared_ptr<Physics::Joint> joint = JointUtils::CreateJoint(
|
||||
jointLimitConfig,
|
||||
&ragdoll->GetNode(parentIndex)->GetRigidBody(),
|
||||
&ragdoll->GetNode(nodeIndex)->GetRigidBody());
|
||||
AzPhysics::Joint* joint = sceneInterface->GetJointFromHandle(sceneHandle, jointHandle);
|
||||
|
||||
if (!joint)
|
||||
{
|
||||
AZ_Error("PhysX Ragdoll", false, "Failed to create joint for node index %i.", nodeIndex);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Moving from PhysX 3.4 to 4.1, the allowed range of the twist angle was expanded from -pi..pi
|
||||
// to -2*pi..2*pi.
|
||||
|
||||
@@ -378,8 +378,8 @@ namespace PhysX
|
||||
else
|
||||
{
|
||||
actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, false);
|
||||
const AZStd::shared_ptr<Physics::Joint>& joint = m_nodes[nodeIndex]->GetJoint();
|
||||
if (joint)
|
||||
|
||||
if (AzPhysics::Joint* joint = m_nodes[nodeIndex]->GetJoint())
|
||||
{
|
||||
if (physx::PxD6Joint* pxJoint = static_cast<physx::PxD6Joint*>(joint->GetNativePointer()))
|
||||
{
|
||||
|
||||
@@ -38,11 +38,17 @@ namespace PhysX
|
||||
|
||||
RagdollNode::~RagdollNode()
|
||||
{
|
||||
DestroyJoint();
|
||||
DestroyPhysicsBody();
|
||||
}
|
||||
|
||||
void RagdollNode::SetJoint(const AZStd::shared_ptr<Physics::Joint>& joint)
|
||||
void RagdollNode::SetJoint(AzPhysics::Joint* joint)
|
||||
{
|
||||
if (m_joint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_joint = joint;
|
||||
}
|
||||
|
||||
@@ -52,7 +58,7 @@ namespace PhysX
|
||||
return *m_rigidBody;
|
||||
}
|
||||
|
||||
const AZStd::shared_ptr<Physics::Joint>& RagdollNode::GetJoint() const
|
||||
AzPhysics::Joint* RagdollNode::GetJoint()
|
||||
{
|
||||
return m_joint;
|
||||
}
|
||||
@@ -167,4 +173,16 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
void RagdollNode::DestroyJoint()
|
||||
{
|
||||
if (m_joint != nullptr && m_sceneOwner != AzPhysics::InvalidSceneHandle)
|
||||
{
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
sceneInterface->RemoveJoint(m_sceneOwner, m_joint->m_jointHandle);
|
||||
}
|
||||
m_joint = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -32,11 +32,11 @@ namespace PhysX
|
||||
explicit RagdollNode(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig);
|
||||
~RagdollNode();
|
||||
|
||||
void SetJoint(const AZStd::shared_ptr<Physics::Joint>& joint);
|
||||
void SetJoint(AzPhysics::Joint* joint);
|
||||
|
||||
// Physics::RagdollNode
|
||||
AzPhysics::RigidBody& GetRigidBody() override;
|
||||
const AZStd::shared_ptr<Physics::Joint>& GetJoint() const override;
|
||||
AzPhysics::Joint* GetJoint() override;
|
||||
bool IsSimulating() const override;
|
||||
|
||||
// AzPhysics::SimulatedBody
|
||||
@@ -60,9 +60,10 @@ namespace PhysX
|
||||
private:
|
||||
void CreatePhysicsBody(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig);
|
||||
void DestroyPhysicsBody();
|
||||
void DestroyJoint();
|
||||
|
||||
AZStd::shared_ptr<Physics::Joint> m_joint;
|
||||
AzPhysics::RigidBody* m_rigidBody;
|
||||
AzPhysics::Joint* m_joint = nullptr;
|
||||
AzPhysics::RigidBody* m_rigidBody = nullptr;
|
||||
AzPhysics::SimulatedBodyHandle m_rigidBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
AzPhysics::SceneHandle m_sceneOwner = AzPhysics::InvalidSceneHandle;
|
||||
PhysX::ActorData m_actorUserData;
|
||||
|
||||
@@ -379,7 +379,7 @@ namespace PhysX
|
||||
|
||||
for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
|
||||
{
|
||||
if (const AZStd::shared_ptr<Physics::Joint>& joint = ragdoll->GetNode(nodeIndex)->GetJoint())
|
||||
if (const AzPhysics::Joint* joint = ragdoll->GetNode(nodeIndex)->GetJoint())
|
||||
{
|
||||
if (auto* pxJoint = static_cast<physx::PxD6Joint*>(joint->GetNativePointer()))
|
||||
{
|
||||
|
||||
@@ -10,3 +10,5 @@
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE FALSE)
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE FALSE)
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE TRUE)
|
||||
@@ -10,3 +10,4 @@
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE TRUE)
|
||||
@@ -10,3 +10,4 @@
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_PHYSX_SUPPORTED TRUE)
|
||||
set(PAL_TRAIT_JOINTS_TYPED_TEST_CASE TRUE)
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <PhysXCharacters/API/CharacterController.h>
|
||||
#include <PhysXCharacters/API/CharacterUtils.h>
|
||||
#include <System/PhysXSystem.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
#include <Joint/PhysXJoint.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
@@ -232,6 +234,18 @@ namespace PhysX
|
||||
scene->GetSceneHandle());
|
||||
}
|
||||
|
||||
template<class JointType, class ConfigurationType>
|
||||
AzPhysics::Joint* CreateJoint(const ConfigurationType* configuration,
|
||||
AzPhysics::SceneHandle sceneHandle,
|
||||
AzPhysics::SimulatedBodyHandle parentBodyHandle,
|
||||
AzPhysics::SimulatedBodyHandle childBodyHandle,
|
||||
AZ::Crc32& crc)
|
||||
{
|
||||
JointType* newBody = aznew JointType(*configuration, sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
crc = AZ::Crc32(newBody, sizeof(*newBody));
|
||||
return newBody;
|
||||
}
|
||||
|
||||
//helper to perform a ray cast
|
||||
AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest* raycastRequest,
|
||||
AZStd::vector<physx::PxRaycastHit>& raycastBuffer,
|
||||
@@ -813,6 +827,90 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
AzPhysics::JointHandle PhysXScene::AddJoint(const AzPhysics::JointConfiguration* jointConfig,
|
||||
AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody)
|
||||
{
|
||||
AzPhysics::Joint* newJoint = nullptr;
|
||||
AZ::Crc32 newJointCrc;
|
||||
if (azrtti_istypeof<PhysX::D6JointLimitConfiguration>(jointConfig))
|
||||
{
|
||||
newJoint = Internal::CreateJoint<PhysXD6Joint, D6JointLimitConfiguration>(
|
||||
azdynamic_cast<const D6JointLimitConfiguration*>(jointConfig),
|
||||
m_sceneHandle, parentBody, childBody, newJointCrc);
|
||||
}
|
||||
else if (azrtti_istypeof<PhysX::FixedJointConfiguration*>(jointConfig))
|
||||
{
|
||||
newJoint = Internal::CreateJoint<PhysXFixedJoint, FixedJointConfiguration>(
|
||||
azdynamic_cast<const FixedJointConfiguration*>(jointConfig),
|
||||
m_sceneHandle, parentBody, childBody, newJointCrc);
|
||||
}
|
||||
else if (azrtti_istypeof<PhysX::BallJointConfiguration*>(jointConfig))
|
||||
{
|
||||
newJoint = Internal::CreateJoint<PhysXBallJoint, BallJointConfiguration>(
|
||||
azdynamic_cast<const BallJointConfiguration*>(jointConfig),
|
||||
m_sceneHandle, parentBody, childBody, newJointCrc);
|
||||
}
|
||||
else if (azrtti_istypeof<PhysX::HingeJointConfiguration*>(jointConfig))
|
||||
{
|
||||
newJoint = Internal::CreateJoint<PhysXHingeJoint, HingeJointConfiguration>(
|
||||
azdynamic_cast<const HingeJointConfiguration*>(jointConfig),
|
||||
m_sceneHandle, parentBody, childBody, newJointCrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("PhysXScene", false, "Unknown JointConfiguration.");
|
||||
return AzPhysics::InvalidJointHandle;
|
||||
}
|
||||
|
||||
if (newJoint != nullptr)
|
||||
{
|
||||
AzPhysics::JointIndex index = index = m_joints.size();
|
||||
m_joints.emplace_back(newJointCrc, newJoint);
|
||||
|
||||
const AzPhysics::JointHandle newJointHandle(newJointCrc, index);
|
||||
newJoint->m_sceneOwner = m_sceneHandle;
|
||||
newJoint->m_jointHandle = newJointHandle;
|
||||
|
||||
return newJointHandle;
|
||||
}
|
||||
|
||||
return AzPhysics::InvalidJointHandle;
|
||||
}
|
||||
|
||||
AzPhysics::Joint* PhysXScene::GetJointFromHandle(AzPhysics::JointHandle jointHandle)
|
||||
{
|
||||
if (jointHandle == AzPhysics::InvalidJointHandle)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AzPhysics::JointIndex index = AZStd::get<AzPhysics::HandleTypeIndex::Index>(jointHandle);
|
||||
if (index < m_joints.size()
|
||||
&& m_joints[index].first == AZStd::get<AzPhysics::HandleTypeIndex::Crc>(jointHandle))
|
||||
{
|
||||
return m_joints[index].second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PhysXScene::RemoveJoint(AzPhysics::JointHandle jointHandle)
|
||||
{
|
||||
if (jointHandle == AzPhysics::InvalidJointHandle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AzPhysics::JointIndex index = AZStd::get<AzPhysics::HandleTypeIndex::Index>(jointHandle);
|
||||
if (index < m_joints.size()
|
||||
&& m_joints[index].first == AZStd::get<AzPhysics::HandleTypeIndex::Crc>(jointHandle))
|
||||
{
|
||||
m_deferredDeletionsJoints.push_back(m_joints[index].second);
|
||||
m_joints[index] = AZStd::make_pair(AZ::Crc32(), nullptr);
|
||||
m_freeJointSlots.push(index);
|
||||
jointHandle = AzPhysics::InvalidJointHandle;
|
||||
}
|
||||
}
|
||||
|
||||
AzPhysics::SceneQueryHits PhysXScene::QueryScene(const AzPhysics::SceneQueryRequest* request)
|
||||
{
|
||||
if (request == nullptr)
|
||||
@@ -996,6 +1094,13 @@ namespace PhysX
|
||||
{
|
||||
delete simulatedBody;
|
||||
}
|
||||
|
||||
AZStd::vector<AzPhysics::Joint*> jointDeletions;
|
||||
jointDeletions.swap(m_deferredDeletionsJoints);
|
||||
for (auto* joint : jointDeletions)
|
||||
{
|
||||
delete joint;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysXScene::ProcessTriggerEvents()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Physics/PhysicsScene.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsEvents.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
@@ -52,6 +53,10 @@ namespace PhysX
|
||||
void RemoveSimulatedBodies(AzPhysics::SimulatedBodyHandleList& bodyHandles) override;
|
||||
void EnableSimulationOfBody(AzPhysics::SimulatedBodyHandle bodyHandle) override;
|
||||
void DisableSimulationOfBody(AzPhysics::SimulatedBodyHandle bodyHandle) override;
|
||||
AzPhysics::JointHandle AddJoint(const AzPhysics::JointConfiguration* jointConfig,
|
||||
AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody) override;
|
||||
AzPhysics::Joint* GetJointFromHandle(AzPhysics::JointHandle jointHandle) override;
|
||||
void RemoveJoint(AzPhysics::JointHandle jointHandle) override;
|
||||
AzPhysics::SceneQueryHits QueryScene(const AzPhysics::SceneQueryRequest* request) override;
|
||||
AzPhysics::SceneQueryHitsList QuerySceneBatch(const AzPhysics::SceneQueryRequests& requests) override;
|
||||
[[nodiscard]] bool QuerySceneAsync(AzPhysics::SceneQuery::AsyncRequestId requestId,
|
||||
@@ -94,6 +99,10 @@ namespace PhysX
|
||||
AZStd::vector<AzPhysics::SimulatedBody*> m_deferredDeletions;
|
||||
AZStd::queue<AzPhysics::SimulatedBodyIndex> m_freeSceneSlots;
|
||||
|
||||
AZStd::vector<AZStd::pair<AZ::Crc32, AzPhysics::Joint*>> m_joints;
|
||||
AZStd::vector<AzPhysics::Joint*> m_deferredDeletionsJoints;
|
||||
AZStd::queue<AzPhysics::JointIndex> m_freeJointSlots;
|
||||
|
||||
AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physicsSystemConfigChanged;
|
||||
|
||||
static thread_local AZStd::vector<physx::PxRaycastHit> s_rayCastBuffer; //!< thread local structure to hold hits for a single raycast or shapecast.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#include <Scene/PhysXSceneInterface.h>
|
||||
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
||||
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
|
||||
#include <System/PhysXSystem.h>
|
||||
@@ -144,6 +145,36 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
AzPhysics::JointHandle PhysXSceneInterface::AddJoint(
|
||||
AzPhysics::SceneHandle sceneHandle, const AzPhysics::JointConfiguration* jointConfig,
|
||||
AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody)
|
||||
{
|
||||
if (AzPhysics::Scene* scene = m_physxSystem->GetScene(sceneHandle))
|
||||
{
|
||||
return scene->AddJoint(jointConfig, parentBody, childBody);
|
||||
}
|
||||
|
||||
return AzPhysics::InvalidJointHandle;
|
||||
}
|
||||
|
||||
AzPhysics::Joint* PhysXSceneInterface::GetJointFromHandle(AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle jointHandle)
|
||||
{
|
||||
if (AzPhysics::Scene* scene = m_physxSystem->GetScene(sceneHandle))
|
||||
{
|
||||
return scene->GetJointFromHandle(jointHandle);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PhysXSceneInterface::RemoveJoint(AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle jointHandle)
|
||||
{
|
||||
if (AzPhysics::Scene* scene = m_physxSystem->GetScene(sceneHandle))
|
||||
{
|
||||
scene->RemoveJoint(jointHandle);
|
||||
}
|
||||
}
|
||||
|
||||
AzPhysics::SceneQueryHits PhysXSceneInterface::QueryScene(
|
||||
AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequest* request)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,10 @@ namespace PhysX
|
||||
void RemoveSimulatedBodies(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandleList& bodyHandles) override;
|
||||
void EnableSimulationOfBody(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle) override;
|
||||
void DisableSimulationOfBody(AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle) override;
|
||||
AzPhysics::JointHandle AddJoint(AzPhysics::SceneHandle sceneHandle, const AzPhysics::JointConfiguration* jointConfig,
|
||||
AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody) override;
|
||||
AzPhysics::Joint* GetJointFromHandle(AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle jointHandle) override;
|
||||
void RemoveJoint(AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle jointHandle) override;
|
||||
AzPhysics::SceneQueryHits QueryScene(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequest* request) override;
|
||||
AzPhysics::SceneQueryHitsList QuerySceneBatch(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequests& requests) override;
|
||||
[[nodiscard]] bool QuerySceneAsync(AzPhysics::SceneHandle sceneHandle, AzPhysics::SceneQuery::AsyncRequestId requestId,
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <System/PhysXJointInterface.h>
|
||||
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
|
||||
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct D6JointState
|
||||
{
|
||||
float m_swingAngleY;
|
||||
float m_swingAngleZ;
|
||||
float m_twistAngle;
|
||||
};
|
||||
|
||||
D6JointState CalculateD6JointState(
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Quaternion& childLocalRotation)
|
||||
{
|
||||
D6JointState result;
|
||||
|
||||
const AZ::Quaternion parentRotation = parentWorldRotation * parentLocalRotation;
|
||||
const AZ::Quaternion childRotation = childWorldRotation * childLocalRotation;
|
||||
const AZ::Quaternion relativeRotation = parentRotation.GetConjugate() * childRotation;
|
||||
AZ::Quaternion twistQuat = AZ::IsClose(relativeRotation.GetX(), 0.0f, AZ::Constants::FloatEpsilon)
|
||||
? AZ::Quaternion::CreateIdentity()
|
||||
: AZ::Quaternion(relativeRotation.GetX(), 0.0f, 0.0f, relativeRotation.GetW()).GetNormalized();
|
||||
AZ::Quaternion swingQuat = relativeRotation * twistQuat.GetConjugate();
|
||||
|
||||
// make sure the twist angle has the correct sign for the rotation
|
||||
twistQuat *= AZ::GetSign(twistQuat.GetX());
|
||||
// make sure we get the shortest arcs for the swing degrees of freedom
|
||||
swingQuat *= AZ::GetSign(swingQuat.GetW());
|
||||
// the PhysX swing limits work in terms of tan quarter angles
|
||||
result.m_swingAngleY = 4.0f * atan2f(swingQuat.GetY(), 1.0f + swingQuat.GetW());
|
||||
result.m_swingAngleZ = 4.0f * atan2f(swingQuat.GetZ(), 1.0f + swingQuat.GetW());
|
||||
const float twistAngle = twistQuat.GetAngle();
|
||||
// GetAngle returns an angle in the range 0..2 pi, but the twist limits work in the range -pi..pi
|
||||
const float wrappedTwistAngle = twistAngle > AZ::Constants::Pi ? twistAngle - AZ::Constants::TwoPi : twistAngle;
|
||||
result.m_twistAngle = wrappedTwistAngle;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsD6SwingValid(float swingAngleY, float swingAngleZ, float swingLimitY, float swingLimitZ)
|
||||
{
|
||||
const float epsilon = AZ::Constants::FloatEpsilon;
|
||||
const float yFactor = tanf(0.25f * swingAngleY) / AZStd::GetMax(epsilon, tanf(0.25f * swingLimitY));
|
||||
const float zFactor = tanf(0.25f * swingAngleZ) / AZStd::GetMax(epsilon, tanf(0.25f * swingLimitZ));
|
||||
|
||||
return (yFactor * yFactor + zFactor * zFactor <= 1.0f + epsilon);
|
||||
}
|
||||
|
||||
void AppendD6SwingConeToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float swingAngleY,
|
||||
float swingAngleZ,
|
||||
float swingLimitY,
|
||||
float swingLimitZ,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesSwingCone = angularSubdivisions * (1u + radialSubdivisions);
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesSwingCone);
|
||||
lineValidityBufferOut.reserve(lineValidityBufferOut.size() + numLinesSwingCone);
|
||||
|
||||
// the orientation quat for a radial line in the cone can be represented in terms of sin and cos half angles
|
||||
// these expressions can be efficiently calculated using tan quarter angles as follows:
|
||||
// writing t = tan(x / 4)
|
||||
// sin(x / 2) = 2 * t / (1 + t * t)
|
||||
// cos(x / 2) = (1 - t * t) / (1 + t * t)
|
||||
const float tanQuarterSwingZ = tanf(0.25f * swingLimitZ);
|
||||
const float tanQuarterSwingY = tanf(0.25f * swingLimitY);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = AZ::Constants::TwoPi / angularSubdivisions * angularIndex;
|
||||
// the axis about which to rotate the x-axis to get the radial vector for this segment of the cone
|
||||
const AZ::Vector3 rotationAxis(0, -tanQuarterSwingY * sinf(angle), tanQuarterSwingZ * cosf(angle));
|
||||
const float normalizationFactor = rotationAxis.GetLengthSq();
|
||||
const AZ::Quaternion radialVectorRotation = 1.0f / (1.0f + normalizationFactor) *
|
||||
AZ::Quaternion::CreateFromVector3AndValue(2.0f * rotationAxis, 1.0f - normalizationFactor);
|
||||
const AZ::Vector3 radialVector =
|
||||
(parentLocalRotation * radialVectorRotation).TransformVector(AZ::Vector3::CreateAxisX(scale));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
if (angularIndex < angularSubdivisions)
|
||||
{
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
}
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool swingValid = IsD6SwingValid(swingAngleY, swingAngleZ, swingLimitY, swingLimitZ);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesSwingCone, swingValid);
|
||||
}
|
||||
|
||||
void AppendD6TwistArcToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
float twistLimitLower,
|
||||
float twistLimitUpper,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::u32 numLinesTwistArc = angularSubdivisions * (1u + radialSubdivisions) + 1u;
|
||||
lineBufferOut.reserve(lineBufferOut.size() + 2u * numLinesTwistArc);
|
||||
|
||||
AZ::Vector3 previousRadialVector = AZ::Vector3::CreateZero();
|
||||
const float twistRange = twistLimitUpper - twistLimitLower;
|
||||
|
||||
for (AZ::u32 angularIndex = 0; angularIndex <= angularSubdivisions; angularIndex++)
|
||||
{
|
||||
const float angle = twistLimitLower + twistRange / angularSubdivisions * angularIndex;
|
||||
const AZ::Vector3 radialVector = parentLocalRotation.TransformVector(scale * AZ::Vector3(0.0f, cosf(angle), sinf(angle)));
|
||||
|
||||
if (angularIndex > 0)
|
||||
{
|
||||
for (AZ::u32 radialIndex = 1; radialIndex <= radialSubdivisions; radialIndex++)
|
||||
{
|
||||
const float radiusFraction = 1.0f / radialSubdivisions * radialIndex;
|
||||
lineBufferOut.push_back(radiusFraction * radialVector);
|
||||
lineBufferOut.push_back(radiusFraction * previousRadialVector);
|
||||
}
|
||||
}
|
||||
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(radialVector);
|
||||
|
||||
previousRadialVector = radialVector;
|
||||
}
|
||||
|
||||
const bool twistValid = (twistAngle >= twistLimitLower && twistAngle <= twistLimitUpper);
|
||||
lineValidityBufferOut.insert(lineValidityBufferOut.end(), numLinesTwistArc, twistValid);
|
||||
}
|
||||
|
||||
void AppendD6CurrentTwistToLineBuffer(
|
||||
const AZ::Quaternion& parentLocalRotation,
|
||||
float twistAngle,
|
||||
[[maybe_unused]] float twistLimitLower,
|
||||
[[maybe_unused]] float twistLimitUpper,
|
||||
float scale,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
const AZ::Vector3 twistVector =
|
||||
parentLocalRotation.TransformVector(1.25f * scale * AZ::Vector3(0.0f, cosf(twistAngle), sinf(twistAngle)));
|
||||
lineBufferOut.push_back(AZ::Vector3::CreateZero());
|
||||
lineBufferOut.push_back(twistVector);
|
||||
lineValidityBufferOut.push_back(true);
|
||||
}
|
||||
|
||||
template<typename Configuration>
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration> ConfigurationFactory(
|
||||
const AZ::Quaternion& parentLocalRotation, const AZ::Quaternion& childLocalRotation)
|
||||
{
|
||||
auto jointConfig = AZStd::make_unique<Configuration>();
|
||||
jointConfig->m_childLocalRotation = childLocalRotation;
|
||||
jointConfig->m_parentLocalRotation = parentLocalRotation;
|
||||
|
||||
return jointConfig;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const AZStd::vector<AZ::TypeId> PhysXJointHelpersInterface::GetSupportedJointTypeIds() const
|
||||
{
|
||||
static AZStd::vector<AZ::TypeId> jointTypes = {
|
||||
D6JointLimitConfiguration::RTTI_Type(),
|
||||
FixedJointConfiguration::RTTI_Type(),
|
||||
BallJointConfiguration::RTTI_Type(),
|
||||
HingeJointConfiguration::RTTI_Type()
|
||||
};
|
||||
return jointTypes;
|
||||
}
|
||||
|
||||
AZStd::optional<const AZ::TypeId> PhysXJointHelpersInterface::GetSupportedJointTypeId(AzPhysics::JointType typeEnum) const
|
||||
{
|
||||
switch (typeEnum)
|
||||
{
|
||||
case AzPhysics::JointType::D6Joint:
|
||||
return azrtti_typeid<D6JointLimitConfiguration>();
|
||||
case AzPhysics::JointType::FixedJoint:
|
||||
return azrtti_typeid<FixedJointConfiguration>();
|
||||
case AzPhysics::JointType::BallJoint:
|
||||
return azrtti_typeid<BallJointConfiguration>();
|
||||
case AzPhysics::JointType::HingeJoint:
|
||||
return azrtti_typeid<HingeJointConfiguration>();
|
||||
default:
|
||||
AZ_Warning("PhysX Joint Utils", false, "Unsupported joint type in GetSupportedJointTypeId");
|
||||
}
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration> PhysXJointHelpersInterface::ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
[[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
const AZ::Vector3& normalizedAxis = axis.IsZero() ? AZ::Vector3::CreateAxisX() : axis.GetNormalized();
|
||||
const AZ::Quaternion childLocalRotation = AZ::Quaternion::CreateShortestArc(
|
||||
AZ::Vector3::CreateAxisX(), childWorldRotation.GetConjugate().TransformVector(normalizedAxis));
|
||||
const AZ::Quaternion parentLocalRotation = parentWorldRotation.GetConjugate() * childWorldRotation * childLocalRotation;
|
||||
|
||||
if (jointLimitTypeId == azrtti_typeid<D6JointLimitConfiguration>())
|
||||
{
|
||||
return ConfigurationFactory<D6JointLimitConfiguration>(parentLocalRotation, childLocalRotation);
|
||||
}
|
||||
else if (jointLimitTypeId == azrtti_typeid<FixedJointConfiguration>())
|
||||
{
|
||||
return ConfigurationFactory<FixedJointConfiguration>(parentLocalRotation, childLocalRotation);
|
||||
}
|
||||
else if (jointLimitTypeId == azrtti_typeid<BallJointConfiguration>())
|
||||
{
|
||||
return ConfigurationFactory<BallJointConfiguration>(parentLocalRotation, childLocalRotation);
|
||||
}
|
||||
else if (jointLimitTypeId == azrtti_typeid<HingeJointConfiguration>())
|
||||
{
|
||||
return ConfigurationFactory<HingeJointConfiguration>(parentLocalRotation, childLocalRotation);
|
||||
}
|
||||
|
||||
AZ_Warning("PhysX Joint Utils", false, "Unsupported joint type in ComputeInitialJointLimitConfiguration");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PhysXJointHelpersInterface::GenerateJointLimitVisualizationData(
|
||||
const AzPhysics::JointConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
[[maybe_unused]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
[[maybe_unused]] AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
if (const auto d6JointConfiguration = azrtti_cast<const D6JointLimitConfiguration*>(&configuration))
|
||||
{
|
||||
const AZ::u32 angularSubdivisionsClamped = AZ::GetClamp(angularSubdivisions, 4u, 32u);
|
||||
const AZ::u32 radialSubdivisionsClamped = AZ::GetClamp(radialSubdivisions, 1u, 4u);
|
||||
|
||||
const D6JointState jointState = CalculateD6JointState(
|
||||
parentRotation, d6JointConfiguration->m_parentLocalRotation, childRotation, d6JointConfiguration->m_childLocalRotation);
|
||||
const float swingAngleY = jointState.m_swingAngleY;
|
||||
const float swingAngleZ = jointState.m_swingAngleZ;
|
||||
const float twistAngle = jointState.m_twistAngle;
|
||||
const float swingLimitY = AZ::DegToRad(d6JointConfiguration->m_swingLimitY);
|
||||
const float swingLimitZ = AZ::DegToRad(d6JointConfiguration->m_swingLimitZ);
|
||||
const float twistLimitLower = AZ::DegToRad(d6JointConfiguration->m_twistLimitLower);
|
||||
const float twistLimitUpper = AZ::DegToRad(d6JointConfiguration->m_twistLimitUpper);
|
||||
|
||||
AppendD6SwingConeToLineBuffer(
|
||||
d6JointConfiguration->m_parentLocalRotation, swingAngleY, swingAngleZ, swingLimitY, swingLimitZ, scale,
|
||||
angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
AppendD6TwistArcToLineBuffer(
|
||||
d6JointConfiguration->m_parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper, scale,
|
||||
angularSubdivisionsClamped, radialSubdivisionsClamped, lineBufferOut, lineValidityBufferOut);
|
||||
AppendD6CurrentTwistToLineBuffer(
|
||||
d6JointConfiguration->m_parentLocalRotation, twistAngle, twistLimitLower, twistLimitUpper, scale, lineBufferOut,
|
||||
lineValidityBufferOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
|
||||
* a third party where indicated.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Physics/Common/PhysicsJoint.h>
|
||||
|
||||
namespace AzPhysics
|
||||
{
|
||||
struct JointConfiguration;
|
||||
}
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
class PhysXJointHelpersInterface
|
||||
: public AZ::Interface<AzPhysics::JointHelpersInterface>::Registrar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(PhysX::PhysXJointHelpersInterface, "{48AC5137-2226-4C57-8E4C-FCF3C1965252}", AzPhysics::JointHelpersInterface);
|
||||
|
||||
const AZStd::vector<AZ::TypeId> GetSupportedJointTypeIds() const override;
|
||||
AZStd::optional<const AZ::TypeId> GetSupportedJointTypeId(AzPhysics::JointType typeEnum) const override;
|
||||
|
||||
AZStd::unique_ptr<AzPhysics::JointConfiguration> ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) override;
|
||||
|
||||
void GenerateJointLimitVisualizationData(
|
||||
const AzPhysics::JointConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) override;
|
||||
};
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <System/PhysXSdkCallbacks.h>
|
||||
|
||||
#include <PhysX/Configuration/PhysXConfiguration.h>
|
||||
#include <System/PhysXJointInterface.h>
|
||||
|
||||
namespace physx
|
||||
{
|
||||
@@ -128,6 +129,7 @@ namespace PhysX
|
||||
Debug::PhysXDebug m_physXDebug; //! Handler for the PhysXDebug Interface.
|
||||
PhysXSettingsRegistryManager& m_registryManager; //! Handles all settings registry interactions.
|
||||
PhysXSceneInterface m_sceneInterface; //! Implemented the Scene Az::Interface.
|
||||
PhysXJointHelpersInterface m_jointHelperInterface; //! Implementation of the JointHelpersInterface.
|
||||
|
||||
class MaterialLibraryAssetHelper
|
||||
: private AZ::Data::AssetBus::Handler
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <Source/Utils.h>
|
||||
#include <Source/Collision.h>
|
||||
#include <Source/Shape.h>
|
||||
#include <Source/Joint.h>
|
||||
#include <Source/Pipeline/MeshAssetHandler.h>
|
||||
#include <Source/Pipeline/HeightFieldAssetHandler.h>
|
||||
#include <Source/PhysXCharacters/API/CharacterUtils.h>
|
||||
@@ -93,7 +92,6 @@ namespace PhysX
|
||||
|
||||
void SystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
D6JointLimitConfiguration::Reflect(context);
|
||||
Pipeline::MeshAsset::Reflect(context);
|
||||
|
||||
PhysX::ReflectionUtils::ReflectPhysXOnlyApi(context);
|
||||
@@ -347,49 +345,6 @@ namespace PhysX
|
||||
return AZStd::make_shared<PhysX::Material>(materialConfiguration);
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::TypeId> SystemComponent::GetSupportedJointTypes()
|
||||
{
|
||||
return JointUtils::GetSupportedJointTypes();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Physics::JointLimitConfiguration> SystemComponent::CreateJointLimitConfiguration(AZ::TypeId jointType)
|
||||
{
|
||||
return JointUtils::CreateJointLimitConfiguration(jointType);
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<Physics::Joint> SystemComponent::CreateJoint(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration,
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody)
|
||||
{
|
||||
return JointUtils::CreateJoint(configuration, parentBody, childBody);
|
||||
}
|
||||
|
||||
void SystemComponent::GenerateJointLimitVisualizationData(
|
||||
const Physics::JointLimitConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut)
|
||||
{
|
||||
JointUtils::GenerateJointLimitVisualizationData(configuration, parentRotation, childRotation, scale,
|
||||
angularSubdivisions, radialSubdivisions, vertexBufferOut, indexBufferOut, lineBufferOut, lineValidityBufferOut);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration> SystemComponent::ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
|
||||
{
|
||||
return JointUtils::ComputeInitialJointLimitConfiguration(jointLimitTypeId, parentWorldRotation,
|
||||
childWorldRotation, axis, exampleLocalRotations);
|
||||
}
|
||||
|
||||
void SystemComponent::ReleaseNativeMeshObject(void* nativeMeshObject)
|
||||
{
|
||||
if (nativeMeshObject)
|
||||
|
||||
@@ -115,28 +115,6 @@ namespace PhysX
|
||||
AZStd::shared_ptr<Physics::Shape> CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration) override;
|
||||
AZStd::shared_ptr<Physics::Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) override;
|
||||
|
||||
AZStd::vector<AZ::TypeId> GetSupportedJointTypes() override;
|
||||
AZStd::shared_ptr<Physics::JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType) override;
|
||||
AZStd::shared_ptr<Physics::Joint> CreateJoint(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration,
|
||||
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody) override;
|
||||
void GenerateJointLimitVisualizationData(
|
||||
const Physics::JointLimitConfiguration& configuration,
|
||||
const AZ::Quaternion& parentRotation,
|
||||
const AZ::Quaternion& childRotation,
|
||||
float scale,
|
||||
AZ::u32 angularSubdivisions,
|
||||
AZ::u32 radialSubdivisions,
|
||||
AZStd::vector<AZ::Vector3>& vertexBufferOut,
|
||||
AZStd::vector<AZ::u32>& indexBufferOut,
|
||||
AZStd::vector<AZ::Vector3>& lineBufferOut,
|
||||
AZStd::vector<bool>& lineValidityBufferOut) override;
|
||||
AZStd::unique_ptr<Physics::JointLimitConfiguration> ComputeInitialJointLimitConfiguration(
|
||||
const AZ::TypeId& jointLimitTypeId,
|
||||
const AZ::Quaternion& parentWorldRotation,
|
||||
const AZ::Quaternion& childWorldRotation,
|
||||
const AZ::Vector3& axis,
|
||||
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) override;
|
||||
|
||||
void ReleaseNativeMeshObject(void* nativeMeshObject) override;
|
||||
|
||||
// Assets related data
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
#include <Source/Shape.h>
|
||||
#include <Source/StaticRigidBodyComponent.h>
|
||||
#include <Source/RigidBodyStatic.h>
|
||||
#include <Source/Joint.h>
|
||||
#include <Source/Utils.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
@@ -1394,8 +1394,12 @@ namespace PhysX
|
||||
|
||||
ForceRegionBusBehaviorHandler::Reflect(context);
|
||||
|
||||
GenericJointConfiguration::Reflect(context);
|
||||
GenericJointLimitsConfiguration::Reflect(context);
|
||||
D6JointLimitConfiguration::Reflect(context);
|
||||
JointGenericProperties::Reflect(context);
|
||||
JointLimitProperties::Reflect(context);
|
||||
FixedJointConfiguration::Reflect(context);
|
||||
BallJointConfiguration::Reflect(context);
|
||||
HingeJointConfiguration::Reflect(context);
|
||||
}
|
||||
|
||||
void ForceRegionBusBehaviorHandler::Reflect(AZ::ReflectContext* context)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
namespace AzPhysics
|
||||
{
|
||||
class Scene;
|
||||
struct RigidBody;
|
||||
}
|
||||
|
||||
namespace PhysX::Benchmarks
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <Benchmarks/PhysXBenchmarksCommon.h>
|
||||
|
||||
#include <PhysXTestCommon.h>
|
||||
#include <Joint.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
|
||||
namespace PhysX::Benchmarks
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace PhysX::Benchmarks
|
||||
{
|
||||
AzPhysics::RigidBody* m_parent;
|
||||
AzPhysics::SimulatedBody* m_child;
|
||||
AZStd::shared_ptr<Physics::Joint> m_joint;
|
||||
AzPhysics::JointHandle m_jointHandle;
|
||||
};
|
||||
//! Structure to hold the upper and lower twist limits
|
||||
//! used with Utils::CreateJoints GenerateTwistLimitsFuncPtr
|
||||
@@ -122,13 +122,11 @@ namespace PhysX::Benchmarks
|
||||
|
||||
//! Helper function to add the required number of joints to the provided world
|
||||
//! @param numJoints, the requested number of joints to spawn
|
||||
//! @param system, current active physics system
|
||||
//! @param scene, the physics scene to spawn the joints and their world bodies into
|
||||
//! @param parentPositionGenerator, [optional] function pointer to allow caller to pick the spawn position of the parent body
|
||||
//! @param childPositionGenerator, [optional] function pointer to allow caller to pick the spawn position of the child body
|
||||
//! @param GenerateTwistLimitsFuncPtr, [optional] function pointer to allow caller to pick the twist limits of the joint
|
||||
AZStd::vector<JointGroup> CreateJoints(int numJoints,
|
||||
Physics::System* system,
|
||||
AzPhysics::Scene* scene,
|
||||
GenerateSpawnPositionFuncPtr* parentPositionGenerator = nullptr,
|
||||
GenerateSpawnPositionFuncPtr* childPositionGenerator = nullptr,
|
||||
@@ -173,18 +171,18 @@ namespace PhysX::Benchmarks
|
||||
AzPhysics::SimulatedBodyHandle staticRigidBodyHandle = scene->AddSimulatedBody(&staticRigidBodyConfig);
|
||||
newJoint.m_child = scene->GetSimulatedBodyFromHandle(staticRigidBodyHandle);
|
||||
|
||||
AZStd::shared_ptr <PhysX::D6JointLimitConfiguration> config = AZStd::make_shared<D6JointLimitConfiguration>();
|
||||
PhysX::D6JointLimitConfiguration config;
|
||||
|
||||
TwistLimits limits(JointConstants::CreateJointDefaults::UpperLimit, JointConstants::CreateJointDefaults::LowerLimit);
|
||||
if (twistLimitsGenerator)
|
||||
{
|
||||
limits = (*twistLimitsGenerator)(i);
|
||||
}
|
||||
config->m_twistLimitUpper = limits.m_upperLimit;
|
||||
config->m_twistLimitLower = limits.m_lowerLimit;
|
||||
config->m_swingLimitY = 1.0f;
|
||||
config->m_swingLimitZ = 1.0f;
|
||||
newJoint.m_joint = system->CreateJoint(config, newJoint.m_parent, newJoint.m_child);
|
||||
config.m_twistLimitUpper = limits.m_upperLimit;
|
||||
config.m_twistLimitLower = limits.m_lowerLimit;
|
||||
config.m_swingLimitY = 1.0f;
|
||||
config.m_swingLimitZ = 1.0f;
|
||||
newJoint.m_jointHandle = scene->AddJoint(&config, newJoint.m_parent->m_bodyHandle, newJoint.m_child->m_bodyHandle);
|
||||
joints.emplace_back(AZStd::move(newJoint));
|
||||
}
|
||||
|
||||
@@ -201,8 +199,6 @@ namespace PhysX::Benchmarks
|
||||
virtual void SetUp([[maybe_unused]] const ::benchmark::State &state) override
|
||||
{
|
||||
PhysXBaseBenchmarkFixture::SetUpInternal();
|
||||
//need to get the Physics::System to be able to spawn the rigid bodies
|
||||
m_system = AZ::Interface<Physics::System>::Get();
|
||||
}
|
||||
|
||||
virtual void TearDown([[maybe_unused]] const ::benchmark::State &state) override
|
||||
@@ -218,8 +214,6 @@ namespace PhysX::Benchmarks
|
||||
return sceneConfig;
|
||||
}
|
||||
// PhysXBaseBenchmarkFixture Interface ---------
|
||||
|
||||
Physics::System *m_system;
|
||||
};
|
||||
|
||||
//! BM_Joints_AtRest - This test will spawn the requested number of joints
|
||||
@@ -237,7 +231,7 @@ namespace PhysX::Benchmarks
|
||||
return position;
|
||||
};
|
||||
|
||||
AZStd::vector<Utils::JointGroup> joinGroups = Utils::CreateJoints(aznumeric_cast<int>(state.range(0)), m_system, m_defaultScene,
|
||||
AZStd::vector<Utils::JointGroup> joinGroups = Utils::CreateJoints(aznumeric_cast<int>(state.range(0)), m_defaultScene,
|
||||
&parentPosGenerator, &childPosGenerator);
|
||||
|
||||
//setup the sub tick tracker
|
||||
@@ -260,6 +254,11 @@ namespace PhysX::Benchmarks
|
||||
}
|
||||
subTickTracker.Stop();
|
||||
|
||||
for (const auto& jointGroup : joinGroups)
|
||||
{
|
||||
m_defaultScene->RemoveJoint(jointGroup.m_jointHandle);
|
||||
}
|
||||
|
||||
//sort the frame times and get the P50, P90, P99 percentiles
|
||||
Utils::ReportFramePercentileCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
||||
Utils::ReportFrameStandardDeviationAndMeanCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
||||
@@ -287,7 +286,7 @@ namespace PhysX::Benchmarks
|
||||
return Utils::TwistLimits(JointConstants::JointSettings::SwingingJointUpperLimit, JointConstants::JointSettings::SwingingJointLowerLimit);
|
||||
};
|
||||
|
||||
AZStd::vector<Utils::JointGroup> joinGroups = Utils::CreateJoints(aznumeric_cast<int>(state.range(0)), m_system, m_defaultScene,
|
||||
AZStd::vector<Utils::JointGroup> joinGroups = Utils::CreateJoints(aznumeric_cast<int>(state.range(0)), m_defaultScene,
|
||||
&parentPosGenerator, &childPosGenerator, &twistGenerator);
|
||||
|
||||
//setup the sub tick tracker
|
||||
@@ -326,6 +325,11 @@ namespace PhysX::Benchmarks
|
||||
}
|
||||
subTickTracker.Stop();
|
||||
|
||||
for (const auto& jointGroup : joinGroups)
|
||||
{
|
||||
m_defaultScene->RemoveJoint(jointGroup.m_jointHandle);
|
||||
}
|
||||
|
||||
//sort the frame times and get the P50, P90, P99 percentiles
|
||||
Utils::ReportFramePercentileCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
||||
Utils::ReportFrameStandardDeviationAndMeanCounters(state, tickTimes, subTickTracker.GetSubTickTimes());
|
||||
@@ -370,17 +374,18 @@ namespace PhysX::Benchmarks
|
||||
snakeRigidBodies = Utils::GetRigidBodiesFromHandles(m_defaultScene, snakeRigidBodyHandles);
|
||||
|
||||
//build the snake
|
||||
AZStd::vector<AZStd::shared_ptr<Physics::Joint>> joints;
|
||||
AZStd::shared_ptr <PhysX::D6JointLimitConfiguration> config = AZStd::make_shared<D6JointLimitConfiguration>();
|
||||
config->m_twistLimitUpper = JointConstants::CreateJointDefaults::UpperLimit;
|
||||
config->m_twistLimitLower = JointConstants::CreateJointDefaults::LowerLimit;
|
||||
config->m_swingLimitY = 1.0f;
|
||||
config->m_swingLimitZ = 1.0f;
|
||||
AZStd::vector<AzPhysics::JointHandle> jointHandles;
|
||||
PhysX::D6JointLimitConfiguration config;
|
||||
config.m_twistLimitUpper = JointConstants::CreateJointDefaults::UpperLimit;
|
||||
config.m_twistLimitLower = JointConstants::CreateJointDefaults::LowerLimit;
|
||||
config.m_swingLimitY = 1.0f;
|
||||
config.m_swingLimitZ = 1.0f;
|
||||
//build the head
|
||||
joints.emplace_back(m_system->CreateJoint(config, snakeRigidBodies[0], snakeHead));
|
||||
jointHandles.emplace_back(m_defaultScene->AddJoint(&config, snakeRigidBodies[0]->m_bodyHandle, snakeHead->m_bodyHandle));
|
||||
for (size_t i = 0; (i+1) < snakeRigidBodies.size(); i++)
|
||||
{
|
||||
joints.emplace_back(m_system->CreateJoint(config, snakeRigidBodies[i + 1], snakeRigidBodies[i]));
|
||||
jointHandles.emplace_back(
|
||||
m_defaultScene->AddJoint(&config, snakeRigidBodies[i + 1]->m_bodyHandle, snakeRigidBodies[i]->m_bodyHandle));
|
||||
}
|
||||
|
||||
//setup the sub tick tracker
|
||||
@@ -404,6 +409,10 @@ namespace PhysX::Benchmarks
|
||||
subTickTracker.Stop();
|
||||
|
||||
m_defaultScene->RemoveSimulatedBodies(snakeRigidBodyHandles);
|
||||
for (const auto& jointHandle : jointHandles)
|
||||
{
|
||||
m_defaultScene->RemoveJoint(jointHandle);
|
||||
}
|
||||
snakeRigidBodyHandles.clear();
|
||||
|
||||
//sort the frame times and get the P50, P90, P99 percentiles
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace PhysX
|
||||
};
|
||||
|
||||
class GenericPhysicsInterfaceTest
|
||||
: protected GenericPhysicsFixture
|
||||
: public GenericPhysicsFixture
|
||||
, public testing::Test
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -18,17 +18,18 @@
|
||||
|
||||
#include <BoxColliderComponent.h>
|
||||
#include <RigidBodyComponent.h>
|
||||
#include <Joint.h>
|
||||
#include <JointComponent.h>
|
||||
#include <BallJointComponent.h>
|
||||
#include <FixedJointComponent.h>
|
||||
#include <HingeJointComponent.h>
|
||||
#include <PhysX/Joint/Configuration/PhysXJointConfiguration.h>
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Physics/ShapeConfiguration.h>
|
||||
#include <AzFramework/Physics/SystemBus.h>
|
||||
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/PhysicsSystem.h>
|
||||
|
||||
namespace PhysX
|
||||
{
|
||||
@@ -38,8 +39,9 @@ namespace PhysX
|
||||
AZStd::unique_ptr<AZ::Entity> AddBodyColliderEntity( AzPhysics::SceneHandle sceneHandle,
|
||||
const AZ::Vector3& position,
|
||||
const AZ::Vector3& initialLinearVelocity,
|
||||
AZStd::shared_ptr<GenericJointConfiguration> jointConfig = nullptr,
|
||||
AZStd::shared_ptr<GenericJointLimitsConfiguration> jointLimitsConfig = nullptr)
|
||||
AZStd::shared_ptr<JointComponentConfiguration> jointConfig = nullptr,
|
||||
AZStd::shared_ptr<JointGenericProperties> jointGenericProperties = nullptr,
|
||||
AZStd::shared_ptr<JointLimitProperties> jointLimitProperties = nullptr)
|
||||
{
|
||||
const char* entityName = "testEntity";
|
||||
auto entity = AZStd::make_unique<AZ::Entity>(entityName);
|
||||
@@ -68,10 +70,12 @@ namespace PhysX
|
||||
{
|
||||
jointConfig->m_followerEntity = entity->GetId();
|
||||
|
||||
GenericJointLimitsConfiguration defaultJointLimitsConfig;
|
||||
JointGenericProperties defaultJointGenericProperties;
|
||||
JointLimitProperties defaultJointLimitProperties;
|
||||
entity->CreateComponent<JointComponentType>(
|
||||
*jointConfig,
|
||||
(jointLimitsConfig)? *jointLimitsConfig : defaultJointLimitsConfig);
|
||||
(jointGenericProperties)? *jointGenericProperties : defaultJointGenericProperties,
|
||||
(jointLimitProperties)? *jointLimitProperties : defaultJointLimitProperties);
|
||||
}
|
||||
|
||||
entity->Init();
|
||||
@@ -114,7 +118,7 @@ namespace PhysX
|
||||
leadPosition,
|
||||
leadInitialLinearVelocity);
|
||||
|
||||
auto jointConfig = AZStd::make_shared<GenericJointConfiguration>();
|
||||
auto jointConfig = AZStd::make_shared<JointComponentConfiguration>();
|
||||
jointConfig->m_leadEntity = leadEntity->GetId();
|
||||
jointConfig->m_localTransformFromFollower = jointLocalTransform;
|
||||
|
||||
@@ -150,17 +154,18 @@ namespace PhysX
|
||||
leadPosition,
|
||||
leadInitialLinearVelocity);
|
||||
|
||||
auto jointConfig = AZStd::make_shared<GenericJointConfiguration>();
|
||||
auto jointConfig = AZStd::make_shared<JointComponentConfiguration>();
|
||||
jointConfig->m_leadEntity = leadEntity->GetId();
|
||||
jointConfig->m_localTransformFromFollower = jointLocalTransform;
|
||||
|
||||
auto jointLimits = AZStd::make_shared <GenericJointLimitsConfiguration>();
|
||||
auto jointLimits = AZStd::make_shared <JointLimitProperties>();
|
||||
jointLimits->m_isLimited = false;
|
||||
|
||||
auto followerEntity = AddBodyColliderEntity<HingeJointComponent>(m_testSceneHandle,
|
||||
followerPosition,
|
||||
followerInitialLinearVelocity,
|
||||
jointConfig,
|
||||
nullptr,
|
||||
jointLimits);
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
@@ -191,21 +196,104 @@ namespace PhysX
|
||||
leadPosition,
|
||||
leadInitialLinearVelocity);
|
||||
|
||||
auto jointConfig = AZStd::make_shared<GenericJointConfiguration>();
|
||||
auto jointConfig = AZStd::make_shared<JointComponentConfiguration>();
|
||||
jointConfig->m_leadEntity = leadEntity->GetId();
|
||||
jointConfig->m_localTransformFromFollower = jointLocalTransform;
|
||||
|
||||
auto jointLimits = AZStd::make_shared <GenericJointLimitsConfiguration>();
|
||||
auto jointLimits = AZStd::make_shared <JointLimitProperties>();
|
||||
jointLimits->m_isLimited = false;
|
||||
|
||||
auto followerEntity = AddBodyColliderEntity<BallJointComponent>(m_testSceneHandle,
|
||||
followerPosition,
|
||||
followerInitialLinearVelocity,
|
||||
jointConfig,
|
||||
nullptr,
|
||||
jointLimits);
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_TRUE(followerEndPosition.GetZ() > followerPosition.GetZ());
|
||||
}
|
||||
|
||||
// for some reason TYPED_TEST_CASE with the fixture is not working on Android + Linux
|
||||
#ifdef ENABLE_JOINTS_TYPED_TEST_CASE
|
||||
template<class JointConfigurationType>
|
||||
class PhysXJointsApiTest : public PhysX::GenericPhysicsInterfaceTest
|
||||
{
|
||||
public:
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
PhysX::GenericPhysicsInterfaceTest::SetUp();
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
AzPhysics::RigidBodyConfiguration parentConfiguration;
|
||||
AzPhysics::RigidBodyConfiguration childConfiguration;
|
||||
|
||||
auto colliderConfig = AZStd::make_shared<Physics::ColliderConfiguration>();
|
||||
auto shapeConfiguration = AZStd::make_shared<Physics::BoxShapeConfiguration>(AZ::Vector3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
parentConfiguration.m_colliderAndShapeData = AzPhysics::ShapeColliderPair(colliderConfig, shapeConfiguration);
|
||||
childConfiguration.m_colliderAndShapeData = AzPhysics::ShapeColliderPair(colliderConfig, shapeConfiguration);
|
||||
|
||||
// Put the child body a bit to the lower side of X to avoid it colliding with parent
|
||||
childConfiguration.m_position.SetX(childConfiguration.m_position.GetX() - 2.0f);
|
||||
m_childInitialPos = childConfiguration.m_position;
|
||||
parentConfiguration.m_initialLinearVelocity.SetX(10.0f);
|
||||
|
||||
m_parentBodyHandle = sceneInterface->AddSimulatedBody(m_testSceneHandle, &parentConfiguration);
|
||||
m_childBodyHandle = sceneInterface->AddSimulatedBody(m_testSceneHandle, &childConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
sceneInterface->RemoveSimulatedBody(m_testSceneHandle, m_parentBodyHandle);
|
||||
sceneInterface->RemoveSimulatedBody(m_testSceneHandle, m_childBodyHandle);
|
||||
}
|
||||
|
||||
PhysX::GenericPhysicsInterfaceTest::TearDown();
|
||||
}
|
||||
|
||||
AzPhysics::SimulatedBodyHandle m_parentBodyHandle = AzPhysics::InvalidJointHandle;
|
||||
AzPhysics::SimulatedBodyHandle m_childBodyHandle = AzPhysics::InvalidJointHandle;
|
||||
AZ::Vector3 m_childInitialPos;
|
||||
};
|
||||
|
||||
using JointTypes = testing::Types<
|
||||
D6JointLimitConfiguration,
|
||||
FixedJointConfiguration,
|
||||
BallJointConfiguration,
|
||||
HingeJointConfiguration>;
|
||||
TYPED_TEST_CASE(PhysXJointsApiTest, JointTypes);
|
||||
|
||||
TYPED_TEST(PhysXJointsApiTest, Joint_ChildFollowsParent)
|
||||
{
|
||||
TypeParam jointConfiguration;
|
||||
AzPhysics::JointHandle jointHandle = AzPhysics::InvalidJointHandle;
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
jointHandle = sceneInterface->AddJoint(m_testSceneHandle, &jointConfiguration, m_parentBodyHandle, m_childBodyHandle);
|
||||
}
|
||||
|
||||
EXPECT_NE(jointHandle, AzPhysics::InvalidJointHandle);
|
||||
|
||||
// run physics to trigger the the move of parent body
|
||||
TestUtils::UpdateScene(m_testSceneHandle, AzPhysics::SystemConfiguration::DefaultFixedTimestep, 1);
|
||||
|
||||
AZ::Vector3 childCurrentPos;
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
auto* childBody = sceneInterface->GetSimulatedBodyFromHandle(m_testSceneHandle, m_childBodyHandle);
|
||||
childCurrentPos = childBody->GetPosition();
|
||||
}
|
||||
|
||||
EXPECT_GT(childCurrentPos.GetX(), m_childInitialPos.GetX());
|
||||
}
|
||||
#endif // ENABLE_JOINTS_TYPED_TEST_CASE
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Class name="AZStd::string" field="name" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::vector" field="nodes" type="{023260FD-3D32-570B-A75E-4099359BE960}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_pelvis_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -27,9 +27,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="-0.0391054 -0.7143280 0.0391054 0.6976625" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0117843 0.0553034 0.9984280" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -42,7 +42,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_arm_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -65,9 +65,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0288827 -0.3743261 -0.0537340 0.9254376" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0054825 -0.0006252 1.0001229" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -80,7 +80,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_spine_01_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -103,9 +103,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0045330 0.0049514 1.0000752" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0045330 0.0049514 1.0000751" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -118,7 +118,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_spine_02_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -141,9 +141,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 0.0000000 -0.0000000 1.0001725" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 0.0000000 -0.0000000 1.0001724" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -156,7 +156,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_spine_03_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -179,9 +179,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 0.0000000 0.0000000 1.0002152" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 0.0000000 0.0000000 1.0002151" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -194,7 +194,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_spine_04_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -217,9 +217,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0004615 -0.1719919 0.9851767" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0004615 -0.1719919 0.9851766" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -232,7 +232,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_clavicle_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -255,9 +255,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="-0.0195780 -0.7155011 0.0194289 0.6982983" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0135283 0.0381485 0.9993421" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -270,7 +270,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_wrist_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -293,9 +293,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0883498 0.0613066 0.9941655" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0883498 0.0613066 0.9941654" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -308,7 +308,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_elbow_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -331,9 +331,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 0.0000000 0.6087880 0.7948525" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0000001 0.0000000 1.0002161" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -346,7 +346,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_neck_01_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -369,9 +369,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0000000 0.0967176 0.9951238" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0000000 0.0000000 0.9998127" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -384,7 +384,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_head_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -407,9 +407,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0029691 0.5012505 0.8653531" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0029691 0.5012505 0.8653531" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -422,7 +422,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="C_neck_02_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -445,9 +445,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 0.0000000 0.0028993 1.0001502" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="-0.0000000 0.0000000 0.0028993 1.0001502" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -460,7 +460,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_clavicle_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -483,9 +483,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0195778 0.7154908 0.0194290 0.6983082" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0135140 -0.0000000 -0.9993417 0.0381484" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -498,7 +498,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_wrist_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -521,9 +521,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0883390 0.0000000 -0.9943419 0.0613376" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0883390 -0.0000000 -0.9943417 0.0613376" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -536,7 +536,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_arm_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -559,9 +559,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.3743524 0.0288702 -0.9254135 -0.0538333" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0024797 -0.0000000 -1.0001022 0.0071253" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -574,7 +574,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_elbow_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -597,9 +597,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0000000 0.8197944 -0.5787863" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="-0.0000031 0.0000000 1.0002232 0.0000017" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -612,7 +612,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_leg_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -635,9 +635,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.2611587 0.9659281 -0.0034238 -0.0126628" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 0.0000000 -0.0000000 0.9998225" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -650,7 +650,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_foot_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -673,9 +673,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="-0.0073839 -0.0140681 0.5175676 0.8556790" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 0.0000000 -0.0000000 1.0001576" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -688,7 +688,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="L_knee_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -711,9 +711,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0000000 -0.0000000 0.3640593 -0.9358648" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0000000 -0.0000000 0.9999046" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -726,7 +726,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_leg_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -749,9 +749,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="-0.2770883 -0.9615672 -0.0035520 -0.0123266" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000005 0.0000000 0.9998229 0.0000000" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -764,7 +764,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_foot_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -787,9 +787,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="0.0140685 -0.0073837 -0.8556802 0.5175687" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000004 -0.0000000 -1.0001591 0.0000003" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
@@ -802,7 +802,7 @@
|
||||
</Class>
|
||||
</Class>
|
||||
</Class>
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="4" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RagdollNodeConfiguration" field="element" version="5" type="{A1796586-85AB-496E-93C9-C5841F03B1AD}">
|
||||
<Class name="RigidBodyConfiguration" field="BaseClass1" version="2" type="{ACFA8900-8530-4744-AF00-AA533C868A8E}">
|
||||
<Class name="WorldBodyConfiguration" field="BaseClass1" version="1" type="{6EEB377C-DC60-4E10-AF12-9626C0763B2D}">
|
||||
<Class name="AZStd::string" field="name" value="R_knee_JNT" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
|
||||
@@ -825,9 +825,9 @@
|
||||
<Class name="Matrix3x3" field="Inertia tensor" value="1.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 1.0000000" type="{15A4332F-7C3F-4A58-AC35-50E1CE53FB9C}"/>
|
||||
<Class name="float" field="Maximum Angular Velocity" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
|
||||
</Class>
|
||||
<Class name="AZStd::shared_ptr" field="JointLimit" type="{F5C4DCF0-277D-5536-921B-A6A4AEEF7226}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{90C5C23D-16C0-4F23-AD50-A190E402388E}">
|
||||
<Class name="JointLimitConfiguration" field="BaseClass1" version="1" type="{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}">
|
||||
<Class name="AZStd::shared_ptr" field="JointConfig" type="{B7A3D04D-1ECC-5D84-8C93-B4C9E4F8F6B8}">
|
||||
<Class name="D6JointLimitConfiguration" field="element" version="1" type="{88E067B4-21E8-4FFA-9142-6C52605B704C}">
|
||||
<Class name="JointConfiguration" field="BaseClass1" version="1" type="{DF91D39A-4901-48C4-9159-93FD2ACA5252}">
|
||||
<Class name="Quaternion" field="ParentLocalRotation" value="-0.0000033 0.0000092 -0.9416476 -0.3386196" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
<Class name="Vector3" field="ParentLocalPosition" value="0.0000000 0.0000000 0.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
|
||||
<Class name="Quaternion" field="ChildLocalRotation" value="0.0000000 -0.0000000 -0.9999050 0.0000000" type="{73103120-3DD3-4873-BAB3-9713FA2804FB}"/>
|
||||
|
||||
@@ -208,8 +208,8 @@ namespace PhysX
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(joint->GetChildBody(), &node->GetRigidBody());
|
||||
EXPECT_EQ(joint->GetParentBody(), &ragdoll->GetNode(parentIndex)->GetRigidBody());
|
||||
EXPECT_EQ(joint->GetChildBodyHandle(), node->GetRigidBody().m_bodyHandle);
|
||||
EXPECT_EQ(joint->GetParentBodyHandle(), ragdoll->GetNode(parentIndex)->GetRigidBody().m_bodyHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user