Преглед на файлове

Added C# components for joints

BearishSun преди 9 години
родител
ревизия
591db84a1e

+ 1 - 1
BansheeCore/Include/BsCD6Joint.h

@@ -95,7 +95,7 @@ namespace BansheeEngine
 		/** @copydoc CJoint::createInternal */
 		SPtr<Joint> createInternal() override;
 
-		D6Joint::Motion mMotion[(UINT32)D6Joint::Motion::Count];
+		D6Joint::Motion mMotion[(UINT32)D6Joint::Axis::Count];
 		D6Joint::Drive mDrive[(UINT32)D6Joint::DriveType::Count];
 		LimitLinear mLimitLinear;
 		LimitAngularRange mLimitTwist;

+ 3 - 3
BansheeCore/Include/BsD6Joint.h

@@ -98,7 +98,7 @@ namespace BansheeEngine
 		virtual ~D6Joint() { }
 
 		/** 
-		 * Returns motion constrain for the specified axis. 
+		 * Returns motion constraint for the specified axis. 
 		 *
 		 * @see	setMotion
 		 */
@@ -144,10 +144,10 @@ namespace BansheeEngine
 		/** Sets the angular limit used for constraining the twist (rotation around X) degree of freedom. */
 		virtual void setLimitTwist(const LimitAngularRange& limit) = 0;
 
-		/** Returns the angular limit used for constraining the swing (rotation around Y and Z) degree of freedom. */
+		/** Returns the cone limit used for constraining the swing (rotation around Y and Z) degree of freedom. */
 		virtual LimitConeRange getLimitSwing() const = 0;
 
-		/** Sets the angular limit used for constraining the swing (rotation around Y and Z) degree of freedom. */
+		/** Sets the cone limit used for constraining the swing (rotation around Y and Z) degree of freedom. */
 		virtual void setLimitSwing(const LimitConeRange& limit) = 0;
 	
 		/**

+ 4 - 4
BansheeCore/Include/BsHingeJoint.h

@@ -73,16 +73,16 @@ namespace BansheeEngine
 		virtual void setLimit(const LimitAngularRange& limit) = 0;
 
 		/** 
-		 * Returns the drive of the joint. It drives the joint's angular velocity towards a particular value. You must
-		 * enable the drive flag on the joint in order for this to be recognized. 
+		 * Returns the drive properties of the joint. It drives the joint's angular velocity towards a particular value. You
+		 * must enable the drive flag on the joint in order for the drive to be active.
 		 *
 		 * @see HingeJoint::Drive
 		 */
 		virtual Drive getDrive() const = 0;
 
 		/** 
-		 * Sets the drive of the joint. It drives the joint's angular velocity towards a particular value. You must enable
-		 * the drive flag on the joint in order for this to be recognized. 
+		 * Sets the drive properties of the joint. It drives the joint's angular velocity towards a particular value. You 
+		 * must enable the drive flag on the joint in order for the drive to be active.
 		 *
 		 * @see HingeJoint::Drive
 		 */

+ 4 - 4
BansheeCore/Include/BsSliderJoint.h

@@ -33,16 +33,16 @@ namespace BansheeEngine
 		virtual float getSpeed() const = 0;
 
 		/** 
-		 * Returns a limit that allows you to constrain the movement of the joint to a specific minimum and maximum 
-		 * distance. You must enable the limit flag on the joint in order for this to be recognized. 
+		 * Returns a limit that constrains the movement of the joint to a specific minimum and maximum distance. You must
+		 * enable the limit flag on the joint in order for this to be recognized. 
 		 *
 		 * @see LimitLinearRange
 		 */
 		virtual LimitLinearRange getLimit() const = 0;
 
 		/** 
-		 * Sets a limit that allows you to constrain the movement of the joint to a specific minimum and maximum 
-		 * distance. You must enable the limit flag on the joint in order for this to be recognized. 
+		 * Sets a limit that constrains the movement of the joint to a specific minimum and maximum distance. You must
+		 * enable the limit flag on the joint in order for this to be recognized. 
 		 *
 		 * @see LimitLinearRange
 		 */

+ 6 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -113,6 +113,10 @@
     <Compile Include="Physics\CapsuleCollider.cs" />
     <Compile Include="Physics\CharacterController.cs" />
     <Compile Include="Physics\Collider.cs" />
+    <Compile Include="Physics\D6Joint.cs" />
+    <Compile Include="Physics\DistanceJoint.cs" />
+    <Compile Include="Physics\FixedJoint.cs" />
+    <Compile Include="Physics\HingeJoint.cs" />
     <Compile Include="Physics\Joint.cs" />
     <Compile Include="Physics\MeshCollider.cs" />
     <Compile Include="Physics\NativeBoxCollider.cs" />
@@ -136,7 +140,9 @@
     <Compile Include="Physics\PhysicsCommon.cs" />
     <Compile Include="Physics\PlaneCollider.cs" />
     <Compile Include="Physics\Rigidbody.cs" />
+    <Compile Include="Physics\SliderJoint.cs" />
     <Compile Include="Physics\SphereCollider.cs" />
+    <Compile Include="Physics\SphericalJoint.cs" />
     <Compile Include="PixelData.cs" />
     <Compile Include="PixelUtility.cs" />
     <Compile Include="PlainText.cs" />

+ 300 - 0
MBansheeEngine/Physics/D6Joint.cs

@@ -0,0 +1,300 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Represents the most customizable type of joint. This joint type can be used to create all other built-in joint 
+    /// types, and to design your own custom ones, but is less intuitive to use.Allows a specification of a linear
+    /// constraint (e.g. for slider), twist constraint(rotating around X) and swing constraint(rotating around Y and Z).
+    /// It also allows you to constrain limits to only specific axes or completely lock specific axes.
+    /// </summary>
+    public sealed class D6Joint : Joint
+    {
+        [SerializeField]
+        private LimitLinear linearLimit = new LimitLinear();
+        [SerializeField]
+        private LimitAngularRange twistLimit = new LimitAngularRange();
+        [SerializeField]
+        private LimitConeRange swingLimit = new LimitConeRange();
+        [SerializeField]
+        private D6JointMotion[] motion = new D6JointMotion[(int)D6JointAxis.Count];
+        [SerializeField]
+        private D6JointDrive[] drives = new D6JointDrive[(int)D6JointDriveType.Count];
+        [SerializeField]
+        private Vector3 drivePosition;
+        [SerializeField]
+        private Quaternion driveRotation;
+        [SerializeField]
+        private Vector3 driveLinearVelocity;
+        [SerializeField]
+        private Vector3 driveAngularVelocity;
+
+        /// <summary>
+        /// Returns the current rotation of the joint around the X axis.
+        /// </summary>
+        public Radian Twist
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.Twist;
+
+                return new Radian(0.0f);
+            }
+        }
+
+        /// <summary>
+        /// Returns the current rotation of the joint around the Y axis.
+        /// </summary>
+        public Radian SwingY
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.SwingY;
+
+                return new Radian(0.0f);
+            }
+        }
+
+        /// <summary>
+        /// Returns the current rotation of the joint around the Z axis.
+        /// </summary>
+        public Radian SwingZ
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.SwingZ;
+
+                return new Radian(0.0f);
+            }
+        }
+
+        /// <summary>
+        /// Linear limit used for constraining translation degrees of freedom.
+        /// </summary>
+        public LimitLinear LimitLinear
+        {
+            get { return linearLimit; }
+            set
+            {
+                if (linearLimit == value)
+                    return;
+
+                linearLimit = value;
+
+                if (Native != null)
+                    Native.LimitLinear = value;
+            }
+        }
+
+        /// <summary>
+        /// Angular limit used for constraining the twist (rotation around X) degree of freedom.
+        /// </summary>
+        public LimitAngularRange LimitTwist
+        {
+            get { return twistLimit; }
+            set
+            {
+                if (twistLimit == value)
+                    return;
+
+                twistLimit = value;
+
+                if (Native != null)
+                    Native.LimitTwist = value;
+            }
+        }
+
+        /// <summary>
+        /// Cone limit used for constraining the swing (rotation around Y and Z) degree of freedom.
+        /// </summary>
+        public LimitConeRange LimitSwing
+        {
+            get { return swingLimit; }
+            set
+            {
+                if (swingLimit == value)
+                    return;
+
+                swingLimit = value;
+
+                if (Native != null)
+                    Native.LimitSwing = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive's target position relative to the joint's first body. This is the position the drive will
+        /// attempt to reach if enabled.
+        /// </summary>
+        public Vector3 DrivePosition
+        {
+            get { return drivePosition; }
+            set
+            {
+                if (drivePosition == value)
+                    return;
+
+                drivePosition = value;
+
+                if (Native != null)
+                    Native.DrivePosition = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive's target orientation relative to the joint's first body. This is the orientation the drive
+        /// will attempt to reach if enabled.
+        /// </summary>
+        public Quaternion DriveRotation
+        {
+            get { return driveRotation; }
+            set
+            {
+                if (driveRotation == value)
+                    return;
+
+                driveRotation = value;
+
+                if (Native != null)
+                    Native.DriveRotation = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive's target linear velocity. This is the velocity the drive will attempt to reach if enabled.
+        /// </summary>
+        public Vector3 DriveLinearVelocity
+        {
+            get { return driveLinearVelocity; }
+            set
+            {
+                if (driveLinearVelocity == value)
+                    return;
+
+                driveLinearVelocity = value;
+
+                if (Native != null)
+                    Native.DriveLinearVelocity = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive's target angular velocity. This is the velocity the drive will attempt to reach if enabled.
+        /// </summary>
+        public Vector3 DriveAngularVelocity
+        {
+            get { return driveAngularVelocity; }
+            set
+            {
+                if (driveAngularVelocity == value)
+                    return;
+
+                driveAngularVelocity = value;
+
+                if (Native != null)
+                    Native.DriveAngularVelocity = value;
+            }
+        }
+
+        /// <summary>
+        /// Returns the type of motion constrain for the specified axis.
+        /// </summary>
+        /// <param name="axis">Axis to retrieve the motion constrain for.</param>
+        /// <returns>Motion constrain type for the axis.</returns>
+        public D6JointMotion GetMotion(D6JointAxis axis)
+        {
+            return motion[(int) axis];
+        }
+
+        /// <summary>
+        /// Allows you to constrain motion of the specified axis. Be aware that when setting drives for a specific axis
+        ///  you must also take care not to constrain its motion in a conflicting way(e.g.you cannot add a drive that
+        /// moves the joint on X axis, and then lock the X axis).
+        /// 
+        /// Unlocking translations degrees of freedom allows the bodies to move along the subset of the unlocked axes.
+        /// (e.g.unlocking just one translational axis is the equivalent of a slider joint.)
+        /// 
+        /// Angular degrees of freedom are partitioned as twist(around X axis) and swing(around Y and Z axes). Different
+        /// effects can be achieves by unlocking their various combinations: 
+        ///  - If a single degree of angular freedom is unlocked it should be the twist degree as it has extra options for
+        ///    that case (e.g. for a hinge joint).
+        ///  - If both swing degrees are unlocked but twist is locked the result is a zero-twist joint.
+        ///  - If one swing and one twist degree of freedom are unlocked the result is a zero-swing joint (e.g.an arm
+        ///    attached at the elbow)
+        ///  - If all angular degrees of freedom are unlocked the result is the same as the spherical joint.
+        /// </summary>
+        /// <param name="axis">Axis to change the motion type for.</param>
+        /// <param name="motion">Type of motion for the axis.</param>
+        public void SetMotion(D6JointAxis axis, D6JointMotion motion)
+        {
+            if (this.motion[(int)axis] == motion)
+                return;
+
+            this.motion[(int)axis] = motion;
+
+            if (Native != null)
+                Native.SetMotion(axis, motion);
+        }
+
+        /// <summary>
+        /// Returns properties for the specified drive type.
+        /// </summary>
+        /// <param name="type">Type of drive to retrieve properties for.</param>
+        /// <returns>Properties for the requested drive type.</returns>
+        public D6JointDrive GetDrive(D6JointDriveType type)
+        {
+            return drives[(int) type];
+        }
+
+        /// <summary>
+        /// Sets a drive that will attempt to move the specified degree(s) of freedom to the wanted position and velocity. 
+        /// </summary>
+        /// <param name="type">Type of the drive.</param>
+        /// <param name="drive">Drive properties.</param>
+        public void SetDrive(D6JointDriveType type, D6JointDrive drive)
+        {
+            if (this.drives[(int)type] == drive)
+                return;
+
+            this.drives[(int)type] = drive;
+
+            if (Native != null)
+                Native.SetDrive(type, drive);
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeD6Joint Native
+        {
+            get { return (NativeD6Joint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeD6Joint joint = new NativeD6Joint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.LimitLinear = linearLimit;
+            joint.LimitTwist = twistLimit;
+            joint.LimitSwing = swingLimit;
+
+            for (int i = 0; i < (int) D6JointAxis.Count; i++)
+                joint.SetMotion((D6JointAxis) i, motion[i]);
+
+            for (int i = 0; i < (int)D6JointDriveType.Count; i++)
+                joint.SetDrive((D6JointDriveType)i, drives[i]);
+
+            joint.DrivePosition = drivePosition;
+            joint.DriveRotation = driveRotation;
+            joint.DriveLinearVelocity = driveLinearVelocity;
+            joint.DriveAngularVelocity = driveAngularVelocity;
+
+            return joint;
+        }
+    }
+}

+ 219 - 0
MBansheeEngine/Physics/DistanceJoint.cs

@@ -0,0 +1,219 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// A joint that maintains an upper or lower (or both) bound on the distance between two bodies.
+    /// </summary>
+    public sealed class DistanceJoint : Joint
+    {
+        /// <summary>
+        /// Flags to control distance joint behaviour.
+        /// </summary>
+        [Flags]
+        private enum Flag
+        {
+            MinDistanceLimit = 0x01,
+            MaxDistanceLimit = 0x02,
+            Spring = 0x04
+        }
+
+        [SerializeField]
+        private float minDistance = 0.0f;
+        [SerializeField]
+        private float maxDistance = 0.0f;
+        [SerializeField]
+        private float tolerance = 0.25f;
+        [SerializeField]
+        private Spring spring;
+        [SerializeField]
+        private Flag flags = 0;
+
+        /// <summary>
+        /// Returns the current distance between the two joint bodies.
+        /// </summary>
+        public float Distance
+        {
+            get
+            {
+                if(Native != null)
+                    return Native.Distance;
+
+                return 0.0f;
+            }
+        }
+
+        /// <summary>
+        /// Determines the minimum distance the bodies are allowed to be at, they will get no closer. You must enable
+        /// <see cref="EnableMinDistanceLimit"/> in order for this to be enforced.
+        /// </summary>
+        public float MinDistance
+        {
+            get { return minDistance; }
+            set
+            {
+                if (minDistance == value)
+                    return;
+
+                minDistance = value;
+
+                if (Native != null)
+                    Native.MinDistance = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the maximum distance the bodies are allowed to be at, they will get no further. You must enable
+        /// <see cref="EnableMaxDistanceLimit"/> in order for this to be enforced.
+        /// </summary>
+        public float MaxDistance
+        {
+            get { return maxDistance; }
+            set
+            {
+                if (maxDistance == value)
+                    return;
+
+                maxDistance = value;
+
+                if (Native != null)
+                    Native.MaxDistance = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the error tolerance of the joint at which the joint becomes active. This value slightly extends the
+        /// lower and upper limit for precision reasons.
+        /// </summary>
+        public float Tolerance
+        {
+            get { return tolerance; }
+            set
+            {
+                if (tolerance == value)
+                    return;
+
+                tolerance = value;
+
+                if (Native != null)
+                    Native.Tolerance = value;
+            }
+        }
+
+        /// <summary>
+        /// Returns a spring that controls how the joint responds when a limit is reached. You must enable 
+        /// <see cref="EnableSpring"/> in order for the spring to be applied.
+        /// </summary>
+        public Spring Spring
+        {
+            get { return spring; }
+            set
+            {
+                if (spring == value)
+                    return;
+
+                spring = value;
+
+                if (Native != null)
+                    Native.Spring = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables the limit that causes joint objects to maintain a minimum distance between themselves.
+        /// </summary>
+        public bool EnableMinDistanceLimit
+        {
+            get { return (flags & Flag.MinDistanceLimit) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.MinDistanceLimit, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableMinDistanceLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables the limit that causes joint objects to maintain a maximum distance between themselves.
+        /// </summary>
+        public bool EnableMaxDistanceLimit
+        {
+            get { return (flags & Flag.MaxDistanceLimit) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.MaxDistanceLimit, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableMinDistanceLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables the spring that controls how the joint reacts when the limit is reached.
+        /// </summary>
+        public bool EnableSpring
+        {
+            get { return (flags & Flag.Spring) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.Spring, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableSpring = value;
+            }
+        }
+
+        /// <summary>
+        /// Toggles a specific distance joint flag on or off.
+        /// </summary>
+        /// <param name="flag">Flag to toggle.</param>
+        /// <param name="enabled">Should the flag be turned on or off.</param>
+        /// <returns>True if the new newly set flag state was different from the previous one.</returns>
+        private bool SetFlag(Flag flag, bool enabled)
+        {
+            Flag newFlags = flags;
+
+            if (enabled)
+                newFlags |= flag;
+            else
+                newFlags &= ~flag;
+
+            if (newFlags == flags)
+                return false;
+
+            flags = newFlags;
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeDistanceJoint Native
+        {
+            get { return (NativeDistanceJoint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeDistanceJoint joint = new NativeDistanceJoint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.MinDistance = minDistance;
+            joint.MaxDistance = maxDistance;
+            joint.Tolerance = tolerance;
+            joint.Spring = spring;
+            joint.EnableMinDistanceLimit = EnableMinDistanceLimit;
+            joint.EnableMaxDistanceLimit = EnableMaxDistanceLimit;
+            joint.EnableSpring = EnableSpring;
+
+            return joint;
+        }
+    }
+}

+ 18 - 0
MBansheeEngine/Physics/FixedJoint.cs

@@ -0,0 +1,18 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Physics joint that will maintain a fixed distance and orientation between its two attached bodies.
+    /// </summary>
+    public sealed class FixedJoint : Joint
+    {
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeFixedJoint joint = new NativeFixedJoint();
+
+            return joint;
+        }
+    }
+}

+ 171 - 0
MBansheeEngine/Physics/HingeJoint.cs

@@ -0,0 +1,171 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Hinge joint removes all but a single rotation degree of freedom from its two attached bodies (e.g. a door hinge).
+    /// </summary>
+    public sealed class HingeJoint : Joint
+    {
+        /// <summary>
+        /// Flags to control hinge joint behaviour.
+        /// </summary>
+        [Flags]
+        private enum Flag
+        {
+            Limit = 0x01,
+            Drive = 0x02,
+        }
+
+        [SerializeField]
+        private LimitAngularRange limit = new LimitAngularRange();
+        [SerializeField]
+        private HingeJointDrive drive = new HingeJointDrive();
+        [SerializeField]
+        private Flag flags = 0;
+
+        /// <summary>
+        /// Returns the current angle between the two attached bodes.
+        /// </summary>
+        public Radian Angle
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.Angle;
+
+                return 0.0f;
+            }
+        }
+
+        /// <summary>
+        /// Returns the current angular speed of the joint.
+        /// </summary>
+        public float Speed
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.Speed;
+
+                return 0.0f;
+            }
+        }
+
+        /// <summary>
+        /// Determines the limit of the joint. Limit constrains the motion to the specified angle range. You must enable
+        /// <see cref="EnableLimit"/> for this to be enforced.
+        /// </summary>
+        public LimitAngularRange Limit
+        {
+            get { return limit; }
+            set
+            {
+                if (limit == value)
+                    return;
+
+                limit = value;
+
+                if (Native != null)
+                    Native.Limit = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive properties of the joint. It drives the joint's angular velocity towards a particular value.
+        /// You must enable <see cref="EnableDrive"/> for this to be applied.
+        /// </summary>
+        public HingeJointDrive Drive
+        {
+            get { return drive; }
+            set
+            {
+                if (drive == value)
+                    return;
+
+                drive = value;
+
+                if (Native != null)
+                    Native.Drive = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables a limit that contrains the joint's motion to a specified angle range.
+        /// </summary>
+        public bool EnableLimit
+        {
+            get { return (flags & Flag.Limit) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.Limit, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables a drive that drives the joint's angular velocity towards a particular value.
+        /// </summary>
+        public bool EnableDrive
+        {
+            get { return (flags & Flag.Drive) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.Drive, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableDrive = value;
+            }
+        }
+
+        /// <summary>
+        /// Toggles a specific distance joint flag on or off.
+        /// </summary>
+        /// <param name="flag">Flag to toggle.</param>
+        /// <param name="enabled">Should the flag be turned on or off.</param>
+        /// <returns>True if the new newly set flag state was different from the previous one.</returns>
+        private bool SetFlag(Flag flag, bool enabled)
+        {
+            Flag newFlags = flags;
+
+            if (enabled)
+                newFlags |= flag;
+            else
+                newFlags &= ~flag;
+
+            if (newFlags == flags)
+                return false;
+
+            flags = newFlags;
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeHingeJoint Native
+        {
+            get { return (NativeHingeJoint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeHingeJoint joint = new NativeHingeJoint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.Limit = limit;
+            joint.Drive = drive;
+            joint.EnableLimit = EnableLimit;
+            joint.EnableDrive = EnableDrive;
+
+            return joint;
+        }
+    }
+}

+ 180 - 2
MBansheeEngine/Physics/Joint.cs

@@ -354,6 +354,28 @@ namespace BansheeEngine
             this.damping = damping;
         }
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is Spring)
+            {
+                Spring other = (Spring)rhs;
+                return stiffness == other.stiffness && damping == other.damping;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(Spring a, Spring b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(Spring a, Spring b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Spring strength. Force proportional to the position error.
         /// </summary>
@@ -488,6 +510,29 @@ namespace BansheeEngine
         /// </summary>
         public bool acceleration = false;
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is D6JointDrive)
+            {
+                D6JointDrive other = (D6JointDrive)rhs;
+                return stiffness == other.stiffness && damping == other.damping && forceLimit == other.forceLimit 
+                    && acceleration == other.acceleration;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(D6JointDrive a, D6JointDrive b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(D6JointDrive a, D6JointDrive b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Used for accessing drive data from native code.
         /// </summary>
@@ -527,6 +572,29 @@ namespace BansheeEngine
         /// </summary>
         public bool freeSpin = false;
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is HingeJointDrive)
+            {
+                HingeJointDrive other = (HingeJointDrive)rhs;
+                return speed == other.speed && gearRatio == other.gearRatio && forceLimit == other.forceLimit
+                    && freeSpin == other.freeSpin;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(HingeJointDrive a, HingeJointDrive b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(HingeJointDrive a, HingeJointDrive b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Used for accessing drive data from native code.
         /// </summary>
@@ -560,6 +628,28 @@ namespace BansheeEngine
             this.spring = spring;
         }
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is LimitCommon)
+            {
+                LimitCommon other = (LimitCommon)rhs;
+                return contactDist == other.contactDist && restitution == other.restitution && spring == other.spring;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(LimitCommon a, LimitCommon b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(LimitCommon a, LimitCommon b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is
         /// reached to avoid breaking the limit.
@@ -624,10 +714,32 @@ namespace BansheeEngine
             this.upper = upper;
         }
 
-		/// <summary>
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is LimitLinearRange)
+            {
+                LimitLinearRange other = (LimitLinearRange)rhs;
+                return base.Equals(rhs) && lower == other.lower && upper == other.upper;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(LimitLinearRange a, LimitLinearRange b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(LimitLinearRange a, LimitLinearRange b)
+        {
+            return !(a == b);
+        }
+
+        /// <summary>
         /// Lower distance of the limit. Must be less than #upper.
         /// </summary>
-		public float lower;
+        public float lower;
 
         /// <summary>
         /// Upper distance of the limit. Must be more than #lower.
@@ -689,6 +801,28 @@ namespace BansheeEngine
             this.extent = extent;
         }
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is LimitLinear)
+            {
+                LimitLinear other = (LimitLinear)rhs;
+                return base.Equals(rhs) && extent == other.extent;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(LimitLinear a, LimitLinear b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(LimitLinear a, LimitLinear b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Distance at which the limit becomes active.
         /// </summary>
@@ -752,6 +886,28 @@ namespace BansheeEngine
             this.upper = upper;
         }
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is LimitAngularRange)
+            {
+                LimitAngularRange other = (LimitAngularRange)rhs;
+                return base.Equals(rhs) && lower == other.lower && upper == other.upper;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(LimitAngularRange a, LimitAngularRange b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(LimitAngularRange a, LimitAngularRange b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Lower angle of the limit. Must be less than #upper.
         /// </summary>
@@ -825,6 +981,28 @@ namespace BansheeEngine
             this.zLimitAngle = zLimitAngle;
         }
 
+        /// <inheritdoc/>
+        public override bool Equals(object rhs)
+        {
+            if (rhs is LimitConeRange)
+            {
+                LimitConeRange other = (LimitConeRange)rhs;
+                return base.Equals(rhs) && yLimitAngle == other.yLimitAngle && zLimitAngle == other.zLimitAngle;
+            }
+
+            return false;
+        }
+
+        public static bool operator ==(LimitConeRange a, LimitConeRange b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(LimitConeRange a, LimitConeRange b)
+        {
+            return !(a == b);
+        }
+
         /// <summary>
         /// Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis.
         /// </summary>

+ 72 - 0
MBansheeEngine/Physics/SliderJoint.cs

@@ -0,0 +1,72 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Joint that removes all but a single translational degree of freedom. Bodies are allowed to move along a single axis.
+    /// </summary>
+    public sealed class SliderJoint : Joint
+    {
+        [SerializeField]
+        private LimitLinearRange limit = new LimitLinearRange();
+        [SerializeField]
+        private bool enableLimit;
+
+        /// <summary>
+        /// Determines the limit that constrains the movement of the joint to a specific minimum and maximum distance. You
+        /// must enable <see cref="EnableLimit"/> for this to be enforced.
+        /// </summary>
+        public LimitLinearRange Limit
+        {
+            get { return limit; }
+            set
+            {
+                if (limit == value)
+                    return;
+
+                limit = value;
+
+                if (Native != null)
+                    Native.Limit = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables the limit that clamps the movement of the joint.
+        /// </summary>
+        public bool EnableLimit
+        {
+            get { return enableLimit; }
+            set
+            {
+                if (enableLimit == value)
+                    return;
+
+                enableLimit = value;
+
+                if (Native != null)
+                    Native.EnableLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeSliderJoint Native
+        {
+            get { return (NativeSliderJoint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeSliderJoint joint = new NativeSliderJoint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.Limit = limit;
+            joint.EnableLimit = enableLimit;
+
+            return joint;
+        }
+    }
+}

+ 76 - 0
MBansheeEngine/Physics/SphericalJoint.cs

@@ -0,0 +1,76 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// A spherical joint removes all translational degrees of freedom but allows all rotational degrees of freedom. 
+    /// Essentially this ensures that the anchor points of the two bodies are always coincident. Bodies are allowed to
+    /// rotate around the anchor points, and their rotatation can be limited by an elliptical cone.
+    /// </summary>
+    public sealed class SphericalJoint : Joint
+    {
+        [SerializeField]
+        private LimitConeRange limit = new LimitConeRange();
+        [SerializeField]
+        private bool enableLimit;
+        
+        /// <summary>
+        /// Determines the limit that clamps the rotation of the joint inside an eliptical angular cone. You must enable 
+        /// <see cref="EnableLimit"/> for this to be enforced.
+        /// </summary>
+        public LimitConeRange Limit
+        {
+            get { return limit; }
+            set
+            {
+                if (limit == value)
+                    return;
+
+                limit = value;
+
+                if (Native != null)
+                    Native.Limit = value;
+            }
+        }
+        
+        /// <summary>
+        /// Enables or disables the limit that clamps the rotation of the joint.
+        /// </summary>
+        public bool EnableLimit
+        {
+            get { return enableLimit; }
+            set
+            {
+                if (enableLimit == value)
+                    return;
+
+                enableLimit = value;
+
+                if (Native != null)
+                    Native.EnableLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeSphericalJoint Native
+        {
+            get { return (NativeSphericalJoint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeSphericalJoint joint = new NativeSphericalJoint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.Limit = limit;
+            joint.EnableLimit = enableLimit;
+
+            return joint;
+        }
+    }
+}