summaryrefslogtreecommitdiff
path: root/Runtime/Dynamics/HingeJoint.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Dynamics/HingeJoint.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Dynamics/HingeJoint.cpp')
-rw-r--r--Runtime/Dynamics/HingeJoint.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/Runtime/Dynamics/HingeJoint.cpp b/Runtime/Dynamics/HingeJoint.cpp
new file mode 100644
index 0000000..9494960
--- /dev/null
+++ b/Runtime/Dynamics/HingeJoint.cpp
@@ -0,0 +1,280 @@
+#include "UnityPrefix.h"
+#if ENABLE_PHYSICS
+#include "Runtime/Utilities/StaticAssert.h"
+#include "HingeJoint.h"
+#include "Runtime/Misc/BuildSettings.h"
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "PhysicsManager.h"
+
+#include "External/PhysX/builds/SDKs/Physics/include/NxPhysics.h"
+
+using namespace std;
+
+namespace Unity
+{
+
+#define GET_JOINT() static_cast<NxRevoluteJoint*> (m_Joint)
+
+/*
+- We awake the hingejoint only once. (AwakeFromLoad)
+ At this point we setup the axes. They are never changed afterwards
+ -> The perfect solution remembers the old position/rotation of the rigid bodies.
+ Then when changing axis/anchor is changed it generates axes that are rleative to the old position/rotation state!
+*/
+
+HingeJoint::HingeJoint (MemLabelId label, ObjectCreationMode mode)
+: Super(label, mode)
+{
+ InitJointLimits (m_Limits);
+ InitJointSpring (m_Spring);
+ InitJointMotor (m_Motor);
+
+ m_UseLimits = false;
+ m_UseMotor = false;
+ m_UseSpring = false;
+
+ CompileTimeAssert(sizeof(JointMotor) == sizeof(NxMotorDesc), "Unity JointMotor type has different size from physx one");
+ CompileTimeAssert(sizeof(JointSpring) == sizeof(NxSpringDesc), "Unity JointSpring type has different size from physx one");
+ CompileTimeAssert(sizeof(JointLimits) == sizeof(NxJointLimitPairDesc), "Unity JointLimits type has different size from physx one");
+}
+
+HingeJoint::~HingeJoint ()
+{
+}
+
+inline NxSpringDesc ToNovodex (const JointSpring& spring)
+{
+ JointSpring desc = spring;
+ desc.targetPosition = Deg2Rad (desc.targetPosition);
+ return (const NxSpringDesc&)desc;
+}
+
+inline NxMotorDesc ToNovodex (const JointMotor& motor)
+{
+ JointMotor desc = motor;
+ desc.targetVelocity = Deg2Rad (desc.targetVelocity);
+ return (const NxMotorDesc&)desc;
+}
+
+#define kHingeJointLimitError "Joint limits for hinge joint out of bounds. Limits need to be between -360 and 360 degrees."
+inline NxJointLimitPairDesc ToNovodex (const JointLimits& limits)
+{
+ NxJointLimitPairDesc l = (const NxJointLimitPairDesc&)limits;
+ if(IS_CONTENT_NEWER_OR_SAME(kUnityVersion4_2_a1))
+ {
+ // PhysX specs limit hinge joints to [-180,180] degress. But it seems 360 works fine
+ // and is very useful in practice. Higher numbers produce broken results (case 492847)
+ if (l.low.value < -360)
+ {
+ l.low.value = -360;
+ ErrorString (kHingeJointLimitError);
+ }
+ if (l.low.value > 360)
+ {
+ l.low.value = 360;
+ ErrorString (kHingeJointLimitError);
+ }
+ if (l.high.value < -360)
+ {
+ l.high.value = -360;
+ ErrorString (kHingeJointLimitError);
+ }
+ if (l.high.value > 360)
+ {
+ l.high.value = 360;
+ ErrorString (kHingeJointLimitError);
+ }
+ }
+ l.low.value = Deg2Rad (l.low.value);
+ l.high.value = Deg2Rad (l.high.value);
+
+ /// DO SOME SPECIAL HANDLING WHEN LOW IS LARGER THAN HIGH!!!!!
+ /// MAKE IT MORE INTUITIVE
+
+ if (l.low.value > l.high.value)
+ swap (l.low, l.high);
+
+ return l;
+}
+
+void HingeJoint::SetUseMotor (bool enable)
+{
+ SetDirty ();
+ m_UseMotor = enable;
+ if (m_Joint)
+ {
+ UInt32 flags = GET_JOINT()->getFlags ();
+ if (enable)
+ flags |= NX_RJF_MOTOR_ENABLED;
+ else
+ flags &= ~NX_RJF_MOTOR_ENABLED;
+ GET_JOINT()->setFlags (flags);
+ }
+}
+
+bool HingeJoint::GetUseMotor () const
+{
+ return m_UseMotor;
+}
+
+void HingeJoint::SetUseLimits (bool enable)
+{
+ SetDirty ();
+ m_UseLimits = enable;
+ if (m_Joint)
+ {
+ UInt32 flags = GET_JOINT()->getFlags ();
+ if (enable)
+ flags |= NX_RJF_LIMIT_ENABLED;
+ else
+ flags &= ~NX_RJF_LIMIT_ENABLED;
+ GET_JOINT()->setFlags (flags);
+ }
+}
+
+bool HingeJoint::GetUseLimits () const
+{
+ return m_UseLimits;
+}
+
+void HingeJoint::SetUseSpring (bool enable)
+{
+ SetDirty ();
+ m_UseSpring = enable;
+ if (m_Joint)
+ {
+ UInt32 flags = GET_JOINT()->getFlags ();
+ if (enable)
+ flags |= NX_RJF_SPRING_ENABLED;
+ else
+ flags &= ~NX_RJF_SPRING_ENABLED;
+ GET_JOINT()->setFlags (flags);
+ }
+}
+
+bool HingeJoint::GetUseSpring () const
+{
+ return m_UseSpring;
+}
+
+JointMotor HingeJoint::GetMotor () const
+{
+ return m_Motor;
+}
+
+void HingeJoint::SetMotor (const JointMotor& motor)
+{
+ SetDirty ();
+ m_Motor = motor;
+ if (m_Joint)
+ {
+ GET_JOINT()->setMotor (ToNovodex (motor));
+ }
+}
+
+JointSpring HingeJoint::GetSpring () const
+{
+ return m_Spring;
+}
+
+void HingeJoint::SetSpring (const JointSpring& spring)
+{
+ SetDirty ();
+ m_Spring = spring;
+ if (m_Joint)
+ GET_JOINT()->setSpring (ToNovodex (spring));
+}
+
+JointLimits HingeJoint::GetLimits () const
+{
+ return m_Limits;
+}
+
+void HingeJoint::SetLimits (const JointLimits& limits)
+{
+ SetDirty ();
+ m_Limits = limits;
+ if (m_Joint)
+ {
+ GET_JOINT()->setLimits (ToNovodex (limits));
+
+ // Novodex seems to have a bug that it will not update HingeJoints when only the limits are changed.
+ // Also call setMotor to force it to update.
+ GET_JOINT()->setMotor (ToNovodex (m_Motor));
+ }
+}
+
+float HingeJoint::GetVelocity () const
+{
+ if (m_Joint)
+ return Rad2Deg (GET_JOINT()->getVelocity ());
+ else
+ return 0.0F;
+}
+
+float HingeJoint::GetAngle () const
+{
+ if (m_Joint)
+ return Rad2Deg (GET_JOINT()->getAngle ());
+ else
+ return 0.0F;
+}
+
+/*
+- When the rigid body which is attached with the hinge joint is activated after the joint is loaded
+ It will not be connected with the joint!
+*/
+
+template<class TransferFunction>
+void HingeJoint::Transfer (TransferFunction& transfer)
+{
+ JointTransferPre (transfer);
+
+ TRANSFER (m_UseSpring);
+ transfer.Align();
+ TRANSFER (m_Spring);
+
+ TRANSFER (m_UseMotor);
+ transfer.Align();
+ TRANSFER (m_Motor);
+
+ TRANSFER (m_UseLimits);
+ transfer.Align();
+ TRANSFER (m_Limits);
+
+ JointTransferPost (transfer);
+}
+
+void HingeJoint::Create ()
+{
+ AssertIf (!IsActive ());
+
+ NxRevoluteJointDesc desc;
+
+ if (m_Joint && m_Joint->getState () == NX_JS_SIMULATING)
+ GET_JOINT()->saveToDesc (desc);
+
+ desc.motor = ToNovodex (m_Motor);
+ desc.limit = ToNovodex (m_Limits);
+ desc.spring = ToNovodex (m_Spring);
+
+ desc.flags = 0;
+ if (m_UseMotor)
+ desc.flags |= NX_RJF_MOTOR_ENABLED;
+ if (m_UseLimits)
+ desc.flags |= NX_RJF_LIMIT_ENABLED;
+ if (m_UseSpring)
+ desc.flags |= NX_RJF_SPRING_ENABLED;
+
+ FINALIZE_CREATE (desc, NxRevoluteJoint);
+}
+
+IMPLEMENT_AXIS_ANCHOR(HingeJoint,NxRevoluteJointDesc)
+
+}
+
+IMPLEMENT_CLASS (HingeJoint)
+IMPLEMENT_OBJECT_SERIALIZE (HingeJoint)
+
+#undef GET_JOINT
+#endif //ENABLE_PHSYICS