HingeJointComponent.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Source/HingeJointComponent.h>
  9. #include <PhysX/MathConversion.h>
  10. #include <PhysX/PhysXLocks.h>
  11. #include <AzCore/Component/TransformBus.h>
  12. #include <AzCore/Interface/Interface.h>
  13. #include <AzCore/Serialization/SerializeContext.h>
  14. #include <AzFramework/Physics/RigidBodyBus.h>
  15. #include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
  16. #include <AzFramework/Physics/PhysicsScene.h>
  17. #include <PxPhysicsAPI.h>
  18. #include <PhysX/NativeTypeIdentifiers.h>
  19. namespace PhysX
  20. {
  21. void HingeJointComponent::Reflect(AZ::ReflectContext* context)
  22. {
  23. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  24. if (serializeContext)
  25. {
  26. serializeContext->Class<HingeJointComponent, JointComponent>()
  27. ->Version(2)
  28. ;
  29. }
  30. }
  31. HingeJointComponent::HingeJointComponent(
  32. const JointComponentConfiguration& configuration,
  33. const JointGenericProperties& genericProperties,
  34. const JointLimitProperties& limitProperties,
  35. const JointMotorProperties& motorProperties)
  36. : JointComponent(configuration, genericProperties, limitProperties, motorProperties)
  37. {
  38. }
  39. void HingeJointComponent::InitNativeJoint()
  40. {
  41. if (m_jointHandle != AzPhysics::InvalidJointHandle)
  42. {
  43. return;
  44. }
  45. JointComponent::LeadFollowerInfo leadFollowerInfo;
  46. ObtainLeadFollowerInfo(leadFollowerInfo);
  47. if (leadFollowerInfo.m_followerActor == nullptr ||
  48. leadFollowerInfo.m_followerBody == nullptr)
  49. {
  50. return;
  51. }
  52. // if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle.
  53. AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle;
  54. if (leadFollowerInfo.m_leadBody != nullptr)
  55. {
  56. parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle;
  57. }
  58. else
  59. {
  60. AZ_TracePrintf(
  61. "PhysX", "Entity [%s] Hinge Joint component missing lead entity. This joint will be a global constraint on the follower's global position.",
  62. GetEntity()->GetName().c_str());
  63. }
  64. HingeJointConfiguration configuration;
  65. configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
  66. configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
  67. configuration.m_childLocalPosition = leadFollowerInfo.m_followerLocal.GetTranslation();
  68. configuration.m_childLocalRotation = leadFollowerInfo.m_followerLocal.GetRotation();
  69. configuration.m_genericProperties = m_genericProperties;
  70. configuration.m_limitProperties = m_limits;
  71. configuration.m_motorProperties = m_motor;
  72. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  73. {
  74. m_jointHandle = sceneInterface->AddJoint(
  75. leadFollowerInfo.m_followerBody->m_sceneOwner,
  76. &configuration,
  77. parentHandle,
  78. leadFollowerInfo.m_followerBody->m_bodyHandle);
  79. m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
  80. }
  81. CachePhysXNativeRevoluteJoint();
  82. JointRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(GetEntityId(), GetId()));
  83. }
  84. void HingeJointComponent::DeinitNativeJoint()
  85. {
  86. JointRequestBus::Handler::BusDisconnect();
  87. m_nativeJoint = nullptr;
  88. }
  89. void HingeJointComponent::CachePhysXNativeRevoluteJoint()
  90. {
  91. if (m_nativeJoint)
  92. {
  93. return;
  94. }
  95. auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
  96. AZ_Assert(sceneInterface, "No sceneInterface");
  97. const auto joint = sceneInterface->GetJointFromHandle(m_jointSceneOwner, m_jointHandle);
  98. AZ_Assert(joint->GetNativeType() == NativeTypeIdentifiers::HingeJoint, "It is not PhysXHingeJoint");
  99. physx::PxJoint* nativeJoint = static_cast<physx::PxJoint*>(joint->GetNativePointer());
  100. physx::PxRevoluteJoint* native = nativeJoint->is<physx::PxRevoluteJoint>();
  101. AZ_Assert(native, "It is not PxRevoluteJoint");
  102. m_nativeJoint = native;
  103. }
  104. float HingeJointComponent::GetPosition() const
  105. {
  106. return m_nativeJoint->getAngle();
  107. }
  108. float HingeJointComponent::GetVelocity() const
  109. {
  110. return m_nativeJoint->getVelocity();
  111. }
  112. AZStd::pair<float, float> HingeJointComponent::GetLimits() const
  113. {
  114. auto limit = m_nativeJoint->getLimit();
  115. return AZStd::pair<float, float>(limit.lower, limit.upper);
  116. }
  117. AZ::Transform HingeJointComponent::GetTransform() const
  118. {
  119. const auto worldFromLocal = m_nativeJoint->getRelativeTransform();
  120. return PxMathConvert(worldFromLocal);
  121. }
  122. void HingeJointComponent::SetVelocity(float velocity)
  123. {
  124. m_nativeJoint->setDriveVelocity(velocity, true);
  125. }
  126. void HingeJointComponent::SetMaximumForce(float force)
  127. {
  128. m_nativeJoint->setDriveForceLimit(force);
  129. }
  130. } // namespace PhysX