summaryrefslogtreecommitdiff
path: root/Runtime/Dynamics/ConfigurableJoint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Dynamics/ConfigurableJoint.cpp')
-rw-r--r--Runtime/Dynamics/ConfigurableJoint.cpp479
1 files changed, 479 insertions, 0 deletions
diff --git a/Runtime/Dynamics/ConfigurableJoint.cpp b/Runtime/Dynamics/ConfigurableJoint.cpp
new file mode 100644
index 0000000..b036e24
--- /dev/null
+++ b/Runtime/Dynamics/ConfigurableJoint.cpp
@@ -0,0 +1,479 @@
+#include "UnityPrefix.h"
+#if ENABLE_PHYSICS
+#include "ConfigurableJoint.h"
+#include "Runtime/Graphics/Transform.h"
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "Runtime/Serialize/TransferFunctions/TransferNameConversions.h"
+#include "PhysicsManager.h"
+#include "Runtime/Utilities/Utility.h"
+#include "Runtime/Misc/BuildSettings.h"
+#include "NxWrapperUtility.h"
+
+#include "External/PhysX/builds/SDKs/Physics/include/NxPhysics.h"
+
+using namespace std;
+
+namespace Unity
+{
+
+#define GET_JOINT() static_cast<NxD6Joint*> (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!
+*/
+
+void ConfigurableJoint::InitializeClass ()
+{
+ #if UNITY_EDITOR
+ // Only introduced during 2.0 alpha
+ RegisterAllowNameConversion (ConfigurableJoint::GetClassStringStatic(), "m_ConfigureInWorldSpace", "m_ConfiguredInWorldSpace");
+ #endif
+}
+
+
+
+ConfigurableJoint::ConfigurableJoint (MemLabelId label, ObjectCreationMode mode)
+: Super(label, mode)
+{
+}
+
+ConfigurableJoint::~ConfigurableJoint ()
+{
+}
+
+void ConfigurableJoint::CalculateGlobalHingeSpace (Vector3f& globalAnchor, Vector3f& globalAxis, Vector3f& globalNormal) const
+{
+ const Transform& transform = GetComponent (Transform);
+
+ Vector3f localAxis = m_Axis;
+ if (SqrMagnitude (localAxis) < Vector3f::epsilon)
+ localAxis = Vector3f (1.0F, 0.0F, 0.0F);
+ Vector3f localNormal = m_SecondaryAxis;
+
+ OrthoNormalize (&localAxis, &localNormal);
+
+ globalAnchor = transform.TransformPoint (m_Anchor);
+ //Vector3f globalRigidbodyPos = transform.GetPosition ();
+
+ if (m_ConfiguredInWorldSpace)
+ {
+ globalAxis = localAxis;
+ globalNormal = localNormal;
+ }
+ else
+ {
+ globalAxis = transform.TransformDirection (localAxis);
+ globalNormal = transform.TransformDirection (localNormal);
+ }
+// Matrix3x3f m;
+// m.SetOrthoNormalBasisInverse(globalAxis, globalNormal, Cross (globalAxis, globalNormal));
+// m.SetOrthoNormalBasisInverse(Vector3f::xAxis, globalNormal, Cross (globalAxis, globalNormal));
+// m.SetOrthoNormalBasisInverse(globalNormal, Cross (globalAxis, globalNormal), globalAxis);
+// OrthoNormalize(m);
+// Quaternionf q;
+// MatrixToQuaternion(m, q);
+// m_ConfigurationSpace = q * Inverse(transform.GetRotation ());
+}
+
+void ConfigurableJoint::Reset ()
+{
+ Super::Reset();
+
+ m_XMotion = NX_D6JOINT_MOTION_FREE;
+ m_YMotion = NX_D6JOINT_MOTION_FREE;
+ m_ZMotion = NX_D6JOINT_MOTION_FREE;
+
+ m_AngularXMotion = NX_D6JOINT_MOTION_FREE;
+ m_AngularYMotion = NX_D6JOINT_MOTION_FREE;
+ m_AngularZMotion = NX_D6JOINT_MOTION_FREE;
+
+ InitSoftJointLimit(m_LinearLimit);
+ InitSoftJointLimit(m_LowAngularXLimit);
+ InitSoftJointLimit(m_HighAngularXLimit);
+ InitSoftJointLimit(m_AngularYLimit);
+ InitSoftJointLimit(m_AngularZLimit);
+
+ InitJointDrive(m_XDrive);
+ InitJointDrive(m_YDrive);
+ InitJointDrive(m_ZDrive);
+ InitJointDrive(m_AngularXDrive);
+ InitJointDrive(m_AngularYZDrive);
+ InitJointDrive(m_SlerpDrive);
+
+ m_ProjectionMode = 0;
+ m_ProjectionDistance = 0.1F;
+ m_ProjectionAngle = 5.0F;
+// m_GearRatio = 1.0F;
+ m_RotationDriveMode = 0;
+// m_UseGear = false;
+ m_TargetAngularVelocity = m_TargetVelocity = m_TargetPosition = Vector3f(0.0F, 0.0F, 0.0F);
+ m_TargetRotation = Quaternionf::identity();
+ m_SecondaryAxis = Vector3f::yAxis;
+ m_ConfiguredInWorldSpace = false;
+ m_SwapBodies = false;
+}
+
+void ConfigurableJoint::CheckConsistency ()
+{
+ Super::CheckConsistency();
+}
+
+void ConfigurableJoint::SetXMotion (int motion)
+{
+ m_XMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetYMotion (int motion)
+{
+ m_YMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularXMotion (int motion)
+{
+ m_AngularXMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularYMotion (int motion)
+{
+ m_AngularYMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularZMotion (int motion)
+{
+ m_AngularZMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetZMotion (int motion)
+{
+ m_ZMotion = motion;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetLinearLimit (const SoftJointLimit& limit)
+{
+ m_LinearLimit = limit;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularZLimit (const SoftJointLimit& limit)
+{
+ m_AngularZLimit = limit;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularYLimit (const SoftJointLimit& limit)
+{
+ m_AngularYLimit = limit;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetLowAngularXLimit (const SoftJointLimit& limit)
+{
+ m_LowAngularXLimit = limit;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetHighAngularXLimit (const SoftJointLimit& limit)
+{
+ m_HighAngularXLimit = limit;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetXDrive (const JointDrive& drive)
+{
+ m_XDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetYDrive (const JointDrive& drive)
+{
+ m_YDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetZDrive (const JointDrive& drive)
+{
+ m_ZDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularXDrive (const JointDrive& drive)
+{
+ m_AngularXDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetAngularYZDrive (const JointDrive& drive)
+{
+ m_AngularYZDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetSlerpDrive (const JointDrive& drive)
+{
+ m_SlerpDrive = drive;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetRotationDriveMode (int mode)
+{
+ m_RotationDriveMode = mode;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetProjectionMode (int mode)
+{
+ m_ProjectionMode = mode;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetProjectionDistance (float dist)
+{
+ m_ProjectionDistance = dist;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetProjectionAngle (float angle)
+{
+ m_ProjectionAngle = angle;
+ ApplyKeepConfigurationSpace();
+}
+
+void ConfigurableJoint::SetConfiguredInWorldSpace (bool c)
+{
+ m_ConfiguredInWorldSpace = c;
+ ApplyRebuildConfigurationSpace();
+}
+
+void ConfigurableJoint::SetSwapBodies (bool c)
+{
+ m_SwapBodies = c;
+ ApplyRebuildConfigurationSpace();
+}
+
+void ConfigurableJoint::SetTargetPosition (const Vector3f& pos)
+{
+ m_TargetPosition = pos;
+ if (m_Joint)
+ GET_JOINT()->setDrivePosition(Vec3ToNx(pos));
+}
+
+void ConfigurableJoint::SetTargetRotation (const Quaternionf& rotation)
+{
+ m_TargetRotation = rotation;
+ if (m_Joint)
+ GET_JOINT()->setDriveOrientation((const NxQuat&)rotation);
+}
+
+void ConfigurableJoint::SetTargetVelocity (const Vector3f& vel)
+{
+ m_TargetVelocity = vel;
+ if (m_Joint)
+ GET_JOINT()->setDriveLinearVelocity(Vec3ToNx(vel));
+}
+
+void ConfigurableJoint::SetTargetAngularVelocity (const Vector3f& angular)
+{
+ m_TargetAngularVelocity = angular;
+ if (m_Joint)
+ GET_JOINT()->setDriveAngularVelocity(Vec3ToNx(angular));
+}
+
+/*
+- 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 ConfigurableJoint::Transfer (TransferFunction& transfer)
+{
+ JointTransferPre (transfer);
+ TRANSFER (m_SecondaryAxis);
+
+ TRANSFER(m_XMotion);
+ TRANSFER(m_YMotion);
+ TRANSFER(m_ZMotion);
+ TRANSFER(m_AngularXMotion);
+ TRANSFER(m_AngularYMotion);
+ TRANSFER(m_AngularZMotion);
+
+ TRANSFER(m_LinearLimit);
+ TRANSFER(m_LowAngularXLimit);
+ TRANSFER(m_HighAngularXLimit);
+ TRANSFER(m_AngularYLimit);
+ TRANSFER(m_AngularZLimit);
+
+ TRANSFER(m_TargetPosition);
+ TRANSFER(m_TargetVelocity);
+
+ TRANSFER(m_XDrive);
+ TRANSFER(m_YDrive);
+ TRANSFER(m_ZDrive);
+
+ TRANSFER(m_TargetRotation);
+ TRANSFER(m_TargetAngularVelocity);
+
+ TRANSFER(m_RotationDriveMode);
+
+ TRANSFER(m_AngularXDrive);
+ TRANSFER(m_AngularYZDrive);
+ TRANSFER(m_SlerpDrive);
+
+ TRANSFER(m_ProjectionMode);
+ TRANSFER(m_ProjectionDistance);
+ TRANSFER(m_ProjectionAngle);
+
+ TRANSFER(m_ConfiguredInWorldSpace);
+ TRANSFER(m_SwapBodies);
+ transfer.Align();
+
+ JointTransferPost (transfer);
+}
+
+void ConfigurableJoint::ApplyKeepConfigurationSpace()
+{
+ SetDirty();
+ if (m_Joint)
+ {
+ // Joint has NX_JS_UNBOUND state, when it's created, but physics aren't simulated yet.
+ // For ex., if you create ConfigurableJoint from a script, right after creation it will have such state.
+ if (m_Joint->getState () == NX_JS_SIMULATING || m_Joint->getState () == NX_JS_UNBOUND)
+ {
+ NxD6JointDesc desc;
+ GET_JOINT()->saveToDesc (desc);
+ SetupD6Desc(desc);
+ GET_JOINT()->loadFromDesc (desc);
+ }
+ }
+}
+
+void ConfigurableJoint::ApplyRebuildConfigurationSpace()
+{
+ SetDirty();
+ if (m_Joint)
+ {
+ GetDynamicsScene ().releaseJoint (*m_Joint);
+ m_Joint = NULL;
+ }
+ Create();
+}
+
+
+void ConfigurableJoint::SetupD6Desc (NxD6JointDesc& desc)
+{
+ desc.xMotion = (NxD6JointMotion)m_XMotion;
+ desc.yMotion = (NxD6JointMotion)m_YMotion;
+ desc.zMotion = (NxD6JointMotion)m_ZMotion;
+
+ desc.swing1Motion = (NxD6JointMotion)m_AngularYMotion;
+ desc.swing2Motion = (NxD6JointMotion)m_AngularZMotion;
+ desc.twistMotion = (NxD6JointMotion)m_AngularXMotion;
+
+ ConvertSoftLimitLinear(m_LinearLimit, desc.linearLimit);
+ ConvertSoftLimit(m_AngularYLimit, desc.swing1Limit);
+ ConvertSoftLimit(m_AngularZLimit, desc.swing2Limit);
+ ConvertSoftLimit(m_LowAngularXLimit, desc.twistLimit.low);
+ ConvertSoftLimit(m_HighAngularXLimit, desc.twistLimit.high);
+
+ if (desc.twistLimit.low.value > desc.twistLimit.high.value)
+ swap (desc.twistLimit.low, desc.twistLimit.high);
+
+ ConvertDrive(m_XDrive, desc.xDrive);
+ ConvertDrive(m_YDrive, desc.yDrive);
+ ConvertDrive(m_ZDrive, desc.zDrive);
+
+ ConvertDrive(m_AngularXDrive, desc.twistDrive);
+ ConvertDrive(m_AngularYZDrive, desc.swingDrive);
+ ConvertDrive(m_SlerpDrive, desc.slerpDrive);
+
+ desc.projectionMode = (NxJointProjectionMode)m_ProjectionMode;
+ desc.projectionDistance = m_ProjectionDistance;
+ desc.projectionAngle = Deg2Rad(m_ProjectionAngle);
+// desc.gearRatio = m_GearRatio;
+
+ desc.flags = 0;
+ if (m_RotationDriveMode)
+ desc.flags |= NX_D6JOINT_SLERP_DRIVE;
+
+// if (m_UseGear)
+// desc.flags |= NX_D6JOINT_GEAR_ENABLED;
+
+ desc.driveAngularVelocity = Vec3ToNx(m_TargetAngularVelocity);
+ desc.driveOrientation = (NxQuat&)m_TargetRotation;
+ desc.driveLinearVelocity = Vec3ToNx(m_TargetVelocity);
+ desc.drivePosition = Vec3ToNx(m_TargetPosition);
+}
+
+void ConfigurableJoint::Create ()
+{
+ AssertIf (!IsActive ());
+
+ NxD6JointDesc desc;
+
+ if (m_Joint && m_Joint->getState () == NX_JS_SIMULATING)
+ GET_JOINT()->saveToDesc (desc);
+
+ SetupD6Desc (desc);
+ FinalizeCreateD6 (desc);
+}
+
+void ConfigurableJoint::FinalizeCreateD6 (NxD6JointDesc& desc)
+{
+ bool swapBodies = m_SwapBodies || (m_ConfiguredInWorldSpace && !IS_CONTENT_NEWER_OR_SAME(kUnityVersion3_4_a1));
+ FinalizeCreateImpl (desc, swapBodies);
+ if (swapBodies)
+ {
+ swap(desc.localNormal[0], desc.localNormal[1]);
+ swap(desc.localAxis[0], desc.localAxis[1]);
+ swap(desc.localAnchor[0], desc.localAnchor[1]);
+ }
+
+ if (GET_JOINT ())
+ {
+ GET_JOINT ()->loadFromDesc (desc);
+
+ // When actors change, we can't use loadFromDesc on the same joint.
+ // Thus recreate the joint
+ if (m_Joint && m_Joint->getState () == NX_JS_BROKEN)
+ {
+ GetDynamicsScene ().releaseJoint (*m_Joint);
+ m_Joint = GetDynamicsScene ().createJoint (desc);
+ }
+ }
+ else
+ m_Joint = GetDynamicsScene ().createJoint (desc);
+}
+
+
+void ConfigurableJoint::SetSecondaryAxis (const Vector3f& axis)
+{
+ SetDirty ();
+ m_SecondaryAxis = axis;
+ if (IsActive () && GET_JOINT())
+ {
+ NxD6JointDesc desc;
+ AssertIf (m_Joint->getState () == NX_JS_BROKEN);
+ GET_JOINT()->saveToDesc (desc);
+
+ SetupAxes (desc, kChangeAxis);
+ GET_JOINT()->loadFromDesc (desc);
+ AssertIf (m_Joint->getState () == NX_JS_BROKEN);
+ }
+}
+
+IMPLEMENT_AXIS_ANCHOR(ConfigurableJoint,NxD6JointDesc)
+
+}
+
+IMPLEMENT_CLASS_HAS_INIT (ConfigurableJoint)
+IMPLEMENT_OBJECT_SERIALIZE (ConfigurableJoint)
+#endif //ENABLE_PHSYICS