Merge branch 'development' into TIF/Runtime
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
namespace AzToolsFramework::ViewportUi::Internal
|
||||
{
|
||||
// margin for the Viewport UI Overlay in pixels
|
||||
const static int ViewportUiOverlayMargin = 5;
|
||||
const static int HighlightBorderSize = 5;
|
||||
const static int TopHighlightBorderSize = 25;
|
||||
const static char* HighlightBorderColor = "#44B2F8";
|
||||
@@ -387,7 +385,6 @@ namespace AzToolsFramework::ViewportUi::Internal
|
||||
m_fullScreenLayout.setSpacing(0);
|
||||
m_fullScreenLayout.setContentsMargins(0, 0, 0, 0);
|
||||
m_fullScreenLayout.addLayout(&m_uiOverlayLayout, 0, 0, 1, 1);
|
||||
m_uiOverlayLayout.setMargin(ViewportUiOverlayMargin);
|
||||
|
||||
// format the label which will appear on top of the highlight border
|
||||
AZStd::string styleSheet = AZStd::string::format(
|
||||
|
||||
+40
-5
@@ -25,13 +25,15 @@ namespace AzToolsFramework::ViewportUi::Internal
|
||||
: QGridLayout(parent)
|
||||
{
|
||||
// set margins and spacing for internal contents
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
setContentsMargins(
|
||||
ViewportUiOverlayMargin, ViewportUiOverlayMargin + ViewportUiOverlayTopMarginPadding, ViewportUiOverlayMargin,
|
||||
ViewportUiOverlayMargin);
|
||||
setSpacing(ViewportUiDisplayLayoutSpacing);
|
||||
|
||||
// create a 3x2 map of sub layouts which will stack widgets according to their mapped alignment
|
||||
m_internalLayouts = AZStd::unordered_map<Qt::Alignment, QBoxLayout*> {
|
||||
CreateSubLayout(new QVBoxLayout(), 0, 0, Qt::AlignTop | Qt::AlignLeft),
|
||||
CreateSubLayout(new QHBoxLayout(), 1, 0, Qt::AlignBottom | Qt::AlignLeft),
|
||||
CreateSubLayout(new QVBoxLayout(), 1, 0, Qt::AlignBottom | Qt::AlignLeft),
|
||||
CreateSubLayout(new QVBoxLayout(), 0, 1, Qt::AlignTop),
|
||||
CreateSubLayout(new QHBoxLayout(), 1, 1, Qt::AlignBottom),
|
||||
CreateSubLayout(new QVBoxLayout(), 0, 2, Qt::AlignTop | Qt::AlignRight),
|
||||
@@ -50,9 +52,42 @@ namespace AzToolsFramework::ViewportUi::Internal
|
||||
if (auto layoutForAlignment = m_internalLayouts.find(alignment);
|
||||
layoutForAlignment != m_internalLayouts.end())
|
||||
{
|
||||
// place the widget before the invisible spacer
|
||||
// spacer must be last item in layout to not interfere with positioning
|
||||
int index = layoutForAlignment->second->count() - 1;
|
||||
// place the widget before or after the invisible spacer
|
||||
// depending on the layout alignment
|
||||
int index = 0;
|
||||
switch (alignment)
|
||||
{
|
||||
case Qt::AlignTop | Qt::AlignLeft:
|
||||
case Qt::AlignTop:
|
||||
index = layoutForAlignment->second->count() - 1;
|
||||
break;
|
||||
case Qt::AlignBottom | Qt::AlignRight:
|
||||
case Qt::AlignBottom:
|
||||
index = layoutForAlignment->second->count();
|
||||
break;
|
||||
// TopRight and BottomLeft are special cases
|
||||
// place the spacer differently according to whether it's a vertical or horizontal layout
|
||||
case Qt::AlignTop | Qt::AlignRight:
|
||||
if (QVBoxLayout* vLayout = qobject_cast<QVBoxLayout*>(layoutForAlignment->second))
|
||||
{
|
||||
index = layoutForAlignment->second->count() - 1;
|
||||
}
|
||||
else if (QHBoxLayout* hLayout = qobject_cast<QHBoxLayout*>(layoutForAlignment->second))
|
||||
{
|
||||
index = layoutForAlignment->second->count();
|
||||
}
|
||||
break;
|
||||
case Qt::AlignBottom | Qt::AlignLeft:
|
||||
if (QVBoxLayout* vLayout = qobject_cast<QVBoxLayout*>(layoutForAlignment->second))
|
||||
{
|
||||
index = layoutForAlignment->second->count();
|
||||
}
|
||||
else if (QHBoxLayout* hLayout = qobject_cast<QHBoxLayout*>(layoutForAlignment->second))
|
||||
{
|
||||
index = layoutForAlignment->second->count() - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
layoutForAlignment->second->insertWidget(index, widget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
namespace AzToolsFramework::ViewportUi::Internal
|
||||
{
|
||||
// margin for the Viewport UI Overlay in pixels
|
||||
constexpr int ViewportUiOverlayMargin = 5;
|
||||
// padding to make space for ImGui
|
||||
constexpr int ViewportUiOverlayTopMarginPadding = 20;
|
||||
|
||||
//! QGridLayout implementation that uses a grid of QVBox/QHBoxLayouts internally to stack widgets.
|
||||
class ViewportUiDisplayLayout : public QGridLayout
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,6 @@ set(FILES
|
||||
Source/Shape.cpp
|
||||
Source/Material.cpp
|
||||
Source/Material.h
|
||||
Source/Joint.cpp
|
||||
Source/Joint.h
|
||||
Source/ForceRegionForces.cpp
|
||||
Source/ForceRegionForces.h
|
||||
Source/ForceRegion.cpp
|
||||
@@ -104,6 +102,7 @@ set(FILES
|
||||
Include/PhysX/Debug/PhysXDebugConfiguration.h
|
||||
Include/PhysX/Debug/PhysXDebugInterface.h
|
||||
Include/PhysX/Configuration/PhysXConfiguration.h
|
||||
Include/PhysX/Joint/Configuration/PhysXJointConfiguration.h
|
||||
Source/Common/PhysXSceneQueryHelpers.h
|
||||
Source/Common/PhysXSceneQueryHelpers.cpp
|
||||
Source/Configuration/PhysXConfiguration.cpp
|
||||
@@ -112,6 +111,11 @@ set(FILES
|
||||
Source/Debug/PhysXDebug.h
|
||||
Source/Debug/PhysXDebug.cpp
|
||||
Source/Debug/Configuration/PhysXDebugConfiguration.cpp
|
||||
Source/Joint/PhysXJoint.h
|
||||
Source/Joint/PhysXJoint.cpp
|
||||
Source/Joint/PhysXJointUtils.h
|
||||
Source/Joint/PhysXJointUtils.cpp
|
||||
Source/Joint/Configuration/PhysXJointConfiguration.cpp
|
||||
Source/Scene/PhysXScene.h
|
||||
Source/Scene/PhysXScene.cpp
|
||||
Source/Scene/PhysXSceneInterface.h
|
||||
@@ -128,6 +132,8 @@ set(FILES
|
||||
Source/System/PhysXCpuDispatcher.h
|
||||
Source/System/PhysXJob.cpp
|
||||
Source/System/PhysXJob.h
|
||||
Source/System/PhysXJointInterface.h
|
||||
Source/System/PhysXJointInterface.cpp
|
||||
Source/System/PhysXSdkCallbacks.h
|
||||
Source/System/PhysXSdkCallbacks.cpp
|
||||
Source/System/PhysXSystem.h
|
||||
|
||||
@@ -783,7 +783,7 @@ namespace PhysXDebug
|
||||
Physics::RagdollNode* ragdollNode = actorData->GetRagdollNode();
|
||||
if (ragdollNode)
|
||||
{
|
||||
const AZStd::shared_ptr<Physics::Joint>& joint = ragdollNode->GetJoint();
|
||||
AzPhysics::Joint* joint = ragdollNode->GetJoint();
|
||||
physx::PxJoint* pxJoint = static_cast<physx::PxJoint*>(joint->GetNativePointer());
|
||||
physx::PxTransform jointPose = actor1->getGlobalPose() * pxJoint->getLocalPose(physx::PxJointActorIndex::eACTOR1);
|
||||
if (!m_culling.m_enabled || m_cullingBox.contains(jointPose.p))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user