浏览代码

More tweaks to joint visualizations and transforms in order to make them more intuitive
Minor fixes to docs

BearishSun 9 年之前
父节点
当前提交
bbfbc8ba37

+ 1 - 1
Documentation/Manuals/Native/gpuPrograms.md

@@ -39,7 +39,7 @@ Instead @ref BansheeEngine::GpuProgram::createParameters "GpuProgram::createPara
 
 
 For example to assign a texture and a 2D vector as input to the program we created earlier:
 For example to assign a texture and a 2D vector as input to the program we created earlier:
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
-GpuParamsPtr params = myProgram->createParameters();
+SPtr<GpuParams> params = myProgram->createParameters();
 
 
 // Retrieve GPU params we can then read/write to
 // Retrieve GPU params we can then read/write to
 GpuParamVec2 myVectorParam;
 GpuParamVec2 myVectorParam;

+ 2 - 2
Documentation/Manuals/Native/utilities.md

@@ -54,7 +54,7 @@ The @ref BansheeEngine::FileSystem "FileSystem" module allows you to open and cr
 An example creating a folder and a file:
 An example creating a folder and a file:
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
 FileSystem::createDir("C:\\Path\\To\\");
 FileSystem::createDir("C:\\Path\\To\\");
-SPtr<DataStreamPtr> fileStream = FileSystem::createAndOpenFile("C:\\Path\\To\\File.txt");
+SPtr<DataStream> fileStream = FileSystem::createAndOpenFile("C:\\Path\\To\\File.txt");
 ... write to data stream...
 ... write to data stream...
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
 # Data streams {#utilities_d}
 # Data streams {#utilities_d}
@@ -64,7 +64,7 @@ You create memory streams by providing them with a pointer and size of a memory
 
 
 Once you have a stream you can seek to a position within a stream and read/write to it. For example:
 Once you have a stream you can seek to a position within a stream and read/write to it. For example:
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
-SPtr<DataStreamPtr> fileStream = FileSystem::createAndOpenFile("C:\\Path\\To\\File.txt");
+SPtr<DataStream> fileStream = FileSystem::createAndOpenFile("C:\\Path\\To\\File.txt");
 // Write some string data
 // Write some string data
 fileStream.writeString("Writing to a file");
 fileStream.writeString("Writing to a file");
 // Write some binary data
 // Write some binary data

+ 2 - 2
README.md

@@ -1,11 +1,11 @@
 # What is Banshee?
 # What is Banshee?
 A high quality modern game development toolkit. It provides a **high performance multi-threaded game engine** written in C++14 that runs 2D and 3D games. The engine offers a wide variety of high level systems needed for game development, ranging from math and utility libraries, to DirectX 11 and OpenGL support all the way to input, GUI, physics, scripting and support for many popular resource formats (e.g. FBX, PNG, PSD, TTF).
 A high quality modern game development toolkit. It provides a **high performance multi-threaded game engine** written in C++14 that runs 2D and 3D games. The engine offers a wide variety of high level systems needed for game development, ranging from math and utility libraries, to DirectX 11 and OpenGL support all the way to input, GUI, physics, scripting and support for many popular resource formats (e.g. FBX, PNG, PSD, TTF).
 
 
-On top of the engine Banshee also provides a highly intuitive and customizable **editor** that is easy to use by artists, designers and programmers alike. The editor allows you to manage all your project's assets, build levels, compile scripts, test and publish your game. Editor is also fully extensible via scripting to ensure developers can easily customize it for their own needs.
+On top of the engine Banshee also provides a highly intuitive and customizable **editor** that is easy to use by artists, designers and programmers alike. The editor allows you to manage all your project's assets, build levels, compile scripts, test and publish your game. Editor is also fully extensible via scripting to ensure developers can easily customize for the exact needs of their projects.
 
 
 The scripting system supports C# and comes with an extensive API ensuring you can complete your game without ever touching the C++ engine core. **C# scripting** makes your development easier by giving you access to the entire .NET library and a wide variety of pre-existing managed libraries. Integration of the scripting system with the editor and external tools like Visual Studio, as well as fast compilation times ensures that iteration times between coding and testing are minimized.
 The scripting system supports C# and comes with an extensive API ensuring you can complete your game without ever touching the C++ engine core. **C# scripting** makes your development easier by giving you access to the entire .NET library and a wide variety of pre-existing managed libraries. Integration of the scripting system with the editor and external tools like Visual Studio, as well as fast compilation times ensures that iteration times between coding and testing are minimized.
 
 
-Aside from being a fully featured game engine and toolkit, Banshee also aims to provide a **high quality foundation**, so others may build and improve upon it. This is reflected in Banshee's architecture which is split into multiple layers allowing developers to use only the functionality they needed, as well as its plugin oriented nature which allows developers to fully remove or replace major engine systems. You will find that Banshee's code is modern, with clean interfaces that make it easy to learn and maintain. Platform specific functionality is kept at a minimum making porting as easy as possible. Additionally its codebase is fully documented with an extensive API reference, as well as a set of manuals introducing you to most major systems.
+Aside from being a fully featured game engine and toolkit, Banshee also aims to provide a **high quality foundation**, so others may build and improve upon it. This is reflected in Banshee's architecture which is split into multiple layers allowing developers to use only the functionality they need, as well as its plugin oriented nature which allows developers to fully remove or replace major engine systems. You will find that Banshee's code is modern, with clean interfaces that make it easy to learn and maintain. Platform specific functionality is kept at a minimum making porting as easy as possible. Additionally its codebase is fully documented with an extensive API reference, as well as a set of manuals introducing you to most major systems.
 
 
 # Features
 # Features
 * [Features](Documentation/GitHub/features.md) - A list of all currently available features.
 * [Features](Documentation/GitHub/features.md) - A list of all currently available features.

+ 3 - 0
Source/BansheeCore/Include/BsCFixedJoint.h

@@ -41,6 +41,9 @@ namespace BansheeEngine
 		/** @copydoc CJoint::createInternal */
 		/** @copydoc CJoint::createInternal */
 		SPtr<Joint> createInternal() override;
 		SPtr<Joint> createInternal() override;
 
 
+		/** @copydoc CJoint::getLocalTransform */
+		void getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation) override;
+
 		FIXED_JOINT_DESC mDesc;
 		FIXED_JOINT_DESC mDesc;
 
 
 		/************************************************************************/
 		/************************************************************************/

+ 3 - 3
Source/BansheeCore/Include/BsCJoint.h

@@ -99,6 +99,9 @@ namespace BansheeEngine
 		/** Creates the internal representation of the Joint and restores the values saved by the Component. */
 		/** Creates the internal representation of the Joint and restores the values saved by the Component. */
 		virtual void restoreInternal();
 		virtual void restoreInternal();
 
 
+		/** Calculates the local position/rotation that needs to be applied to the particular joint body. */
+		virtual void getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation);
+
 		/** Destroys the internal joint representation. */
 		/** Destroys the internal joint representation. */
 		void destroyInternal();
 		void destroyInternal();
 
 
@@ -108,9 +111,6 @@ namespace BansheeEngine
 		/** Checks can the provided rigidbody be used for initializing the joint. */
 		/** Checks can the provided rigidbody be used for initializing the joint. */
 		bool isBodyValid(const HRigidbody& body);
 		bool isBodyValid(const HRigidbody& body);
 
 
-		/** Calculates the local position/rotation that needs to be applied to the particular joint body. */
-		void getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation);
-
 		/** Updates the local transform for the specified body attached to the joint. */
 		/** Updates the local transform for the specified body attached to the joint. */
 		void updateTransform(JointBody body);
 		void updateTransform(JointBody body);
 
 

+ 3 - 0
Source/BansheeCore/Include/BsCSliderJoint.h

@@ -58,6 +58,9 @@ namespace BansheeEngine
 		/** @copydoc CJoint::createInternal */
 		/** @copydoc CJoint::createInternal */
 		SPtr<Joint> createInternal() override;
 		SPtr<Joint> createInternal() override;
 
 
+		/** @copydoc CJoint::getLocalTransform */
+		void getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation) override;
+
 		SLIDER_JOINT_DESC mDesc;
 		SLIDER_JOINT_DESC mDesc;
 
 
 		/************************************************************************/
 		/************************************************************************/

+ 29 - 0
Source/BansheeCore/Source/BsCFixedJoint.cpp

@@ -25,6 +25,35 @@ namespace BansheeEngine
 		return joint;
 		return joint;
 	}
 	}
 
 
+	void CFixedJoint::getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation)
+	{
+		position = mPositions[(int)body];
+		rotation = mRotations[(int)body];
+
+		HRigidbody rigidbody = mBodies[(int)body];
+		if (rigidbody == nullptr) // Get world space transform if no relative to any body
+		{
+			Quaternion worldRot = SO()->getWorldRotation();
+
+			rotation = worldRot*rotation;
+			position = worldRot.rotate(position) + SO()->getWorldPosition();
+		}
+		else
+		{
+			// Find world space transform
+			Quaternion worldRot = rigidbody->SO()->getWorldRotation();
+
+			rotation = worldRot * rotation;
+			position = worldRot.rotate(position) + rigidbody->SO()->getWorldPosition();
+
+			// Get transform of the joint local to the object
+			Quaternion invRotation = rotation.inverse();
+
+			position = invRotation.rotate(SO()->getWorldPosition() - position);
+			rotation = invRotation * SO()->getWorldRotation();
+		}
+	}
+
 	RTTITypeBase* CFixedJoint::getRTTIStatic()
 	RTTITypeBase* CFixedJoint::getRTTIStatic()
 	{
 	{
 		return CFixedJointRTTI::instance();
 		return CFixedJointRTTI::instance();

+ 24 - 0
Source/BansheeCore/Source/BsCSliderJoint.cpp

@@ -2,6 +2,7 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsCSliderJoint.h"
 #include "BsCSliderJoint.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
+#include "BsCRigidbody.h"
 #include "BsCSliderJointRTTI.h"
 #include "BsCSliderJointRTTI.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -76,6 +77,29 @@ namespace BansheeEngine
 		return joint;
 		return joint;
 	}
 	}
 
 
+	void CSliderJoint::getLocalTransform(JointBody body, Vector3& position, Quaternion& rotation)
+	{
+		position = mPositions[(int)body];
+		rotation = mRotations[(int)body];
+
+		HRigidbody rigidbody = mBodies[(int)body];
+		if (rigidbody == nullptr) // Get world space transform if no relative to any body
+		{
+			Quaternion worldRot = SO()->getWorldRotation();
+
+			rotation = worldRot*rotation;
+			position = worldRot.rotate(position) + SO()->getWorldPosition();
+		}
+		else
+		{
+			// Use only the offset for positioning, but for rotation use both the offset and target SO rotation.
+			// (Needed because we need to rotate the joint SO in order to orient the slider direction, so we need an
+			// additional transform that allows us to orient the object)
+			position = rotation.rotate(position);
+			rotation = (rigidbody->SO()->getWorldRotation()*rotation).inverse()*SO()->getWorldRotation();
+		}
+	}
+
 	RTTITypeBase* CSliderJoint::getRTTIStatic()
 	RTTITypeBase* CSliderJoint::getRTTIStatic()
 	{
 	{
 		return CSliderJointRTTI::instance();
 		return CSliderJointRTTI::instance();

+ 1 - 1
Source/MBansheeEditor/Inspectors/D6JointInspector.cs

@@ -195,7 +195,7 @@ namespace BansheeEditor
             swingLimitLayout.Active = Persistent.GetBool("swingLimit_Expanded");
             swingLimitLayout.Active = Persistent.GetBool("swingLimit_Expanded");
             driveLayout.Active = Persistent.GetBool("drive_Expanded");
             driveLayout.Active = Persistent.GetBool("drive_Expanded");
 
 
-            base.BuildGUI(joint);
+            base.BuildGUI(joint, true);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
Source/MBansheeEditor/Inspectors/DistanceJointInspector.cs

@@ -121,7 +121,7 @@ namespace BansheeEditor
             maxLimitField.Active = joint.EnableMaxDistanceLimit;
             maxLimitField.Active = joint.EnableMaxDistanceLimit;
             springLayout.Active = joint.EnableSpring;
             springLayout.Active = joint.EnableSpring;
 
 
-            base.BuildGUI(joint);
+            base.BuildGUI(joint, true);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
Source/MBansheeEditor/Inspectors/FixedJointInspector.cs

@@ -20,7 +20,7 @@ namespace BansheeEditor
             FixedJoint joint = InspectedObject as FixedJoint;
             FixedJoint joint = InspectedObject as FixedJoint;
 
 
             if (joint != null)
             if (joint != null)
-                BuildGUI(joint);
+                BuildGUI(joint, false);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>

+ 1 - 1
Source/MBansheeEditor/Inspectors/HingeJointInspector.cs

@@ -148,7 +148,7 @@ namespace BansheeEditor
             ToggleLimitFields(joint.EnableLimit);
             ToggleLimitFields(joint.EnableLimit);
             ToggleDriveFields(joint.EnableDrive);
             ToggleDriveFields(joint.EnableDrive);
 
 
-            base.BuildGUI(joint);
+            base.BuildGUI(joint, true);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 46 - 21
Source/MBansheeEditor/Inspectors/JointInspector.cs

@@ -13,16 +13,17 @@ namespace BansheeEditor
     /// </summary>
     /// </summary>
     internal abstract class JointInspector : Inspector
     internal abstract class JointInspector : Inspector
     {
     {
-        private GUIGameObjectField targetField = new GUIGameObjectField(typeof(Rigidbody), new LocEdString("Target"));
-        private GUIVector3Field targetOffsetField = new GUIVector3Field(new LocEdString("Target offset"));
+        private GUIGameObjectField targetField;
+        private GUIVector3Field targetOffsetField;
 
 
-        private GUIGameObjectField anchorField = new GUIGameObjectField(typeof(Rigidbody), new LocEdString("Anchor"));
-        private GUIVector3Field anchorOffsetField = new GUIVector3Field(new LocEdString("Anchor offset"));
+        private GUIGameObjectField anchorField;
+        private GUIVector3Field anchorOffsetField;
 
 
-        private GUIFloatField breakForceField = new GUIFloatField(new LocEdString("Break force"));
-        private GUIFloatField breakTorqueField = new GUIFloatField(new LocEdString("Break torque"));
-        private GUIToggleField collisionField = new GUIToggleField(new LocEdString("Enable collision"));
-        
+        private GUIFloatField breakForceField;
+        private GUIFloatField breakTorqueField;
+        private GUIToggleField collisionField;
+
+        private bool showOffsets;
         protected InspectableState modifyState;
         protected InspectableState modifyState;
 
 
         /// <summary>
         /// <summary>
@@ -32,10 +33,13 @@ namespace BansheeEditor
         protected virtual void Refresh(Joint joint)
         protected virtual void Refresh(Joint joint)
         {
         {
             targetField.Value = joint.GetRigidbody(JointBody.Target);
             targetField.Value = joint.GetRigidbody(JointBody.Target);
-            targetOffsetField.Value = joint.GetPosition(JointBody.Target);
-
             anchorField.Value = joint.GetRigidbody(JointBody.Anchor);
             anchorField.Value = joint.GetRigidbody(JointBody.Anchor);
-            anchorOffsetField.Value = joint.GetPosition(JointBody.Anchor);
+
+            if (showOffsets)
+            {
+                targetOffsetField.Value = joint.GetPosition(JointBody.Target);
+                anchorOffsetField.Value = joint.GetPosition(JointBody.Anchor);
+            }
 
 
             breakForceField.Value = joint.BreakForce;
             breakForceField.Value = joint.BreakForce;
             breakTorqueField.Value = joint.BreakTorque;
             breakTorqueField.Value = joint.BreakTorque;
@@ -45,17 +49,36 @@ namespace BansheeEditor
         /// <summary>
         /// <summary>
         /// Creates GUI elements for fields common to all joints.
         /// Creates GUI elements for fields common to all joints.
         /// </summary>
         /// </summary>
-        protected virtual void BuildGUI(Joint joint)
+        protected virtual void BuildGUI(Joint joint, bool showOffsets)
         {
         {
-            targetField.OnChanged += x => { joint.SetRigidbody(JointBody.Target, (Rigidbody)x); MarkAsModified(); ConfirmModify(); };
-            targetOffsetField.OnChanged += x => { joint.SetPosition(JointBody.Target, x); MarkAsModified(); };
-            targetOffsetField.OnFocusLost += ConfirmModify;
-            targetOffsetField.OnConfirmed += ConfirmModify;
+            this.showOffsets = showOffsets;
+
+            targetField = new GUIGameObjectField(typeof(Rigidbody), new LocEdString("Target"));
+            anchorField = new GUIGameObjectField(typeof(Rigidbody), new LocEdString("Anchor"));
+            
+            if (showOffsets)
+            {
+                targetOffsetField = new GUIVector3Field(new LocEdString("Target offset"));
+                anchorOffsetField = new GUIVector3Field(new LocEdString("Anchor offset"));
+            }
+
+            breakForceField = new GUIFloatField(new LocEdString("Break force"));
+            breakTorqueField = new GUIFloatField(new LocEdString("Break torque"));
+            collisionField = new GUIToggleField(new LocEdString("Enable collision"));
 
 
+            targetField.OnChanged += x => { joint.SetRigidbody(JointBody.Target, (Rigidbody)x); MarkAsModified(); ConfirmModify(); };
             anchorField.OnChanged += x => { joint.SetRigidbody(JointBody.Anchor, (Rigidbody)x); MarkAsModified(); ConfirmModify(); };
             anchorField.OnChanged += x => { joint.SetRigidbody(JointBody.Anchor, (Rigidbody)x); MarkAsModified(); ConfirmModify(); };
-            anchorOffsetField.OnChanged += x => { joint.SetPosition(JointBody.Anchor, x); MarkAsModified(); };
-            anchorOffsetField.OnFocusLost += ConfirmModify;
-            anchorOffsetField.OnConfirmed += ConfirmModify;
+
+            if(showOffsets)
+            { 
+                targetOffsetField.OnChanged += x => { joint.SetPosition(JointBody.Target, x); MarkAsModified(); };
+                targetOffsetField.OnFocusLost += ConfirmModify;
+                targetOffsetField.OnConfirmed += ConfirmModify;
+
+                anchorOffsetField.OnChanged += x => { joint.SetPosition(JointBody.Anchor, x); MarkAsModified(); };
+                anchorOffsetField.OnFocusLost += ConfirmModify;
+                anchorOffsetField.OnConfirmed += ConfirmModify;
+            }
 
 
             breakForceField.OnChanged += x => { joint.BreakForce = x; MarkAsModified(); };
             breakForceField.OnChanged += x => { joint.BreakForce = x; MarkAsModified(); };
             breakForceField.OnFocusLost += ConfirmModify;
             breakForceField.OnFocusLost += ConfirmModify;
@@ -68,9 +91,11 @@ namespace BansheeEditor
             collisionField.OnChanged += x => { joint.EnableCollision = x; MarkAsModified(); ConfirmModify(); };
             collisionField.OnChanged += x => { joint.EnableCollision = x; MarkAsModified(); ConfirmModify(); };
             
             
             Layout.AddElement(targetField);
             Layout.AddElement(targetField);
-            Layout.AddElement(targetOffsetField);
+            if(showOffsets)
+                Layout.AddElement(targetOffsetField);
             Layout.AddElement(anchorField);
             Layout.AddElement(anchorField);
-            Layout.AddElement(anchorOffsetField);
+            if(showOffsets)
+                Layout.AddElement(anchorOffsetField);
             Layout.AddElement(breakForceField);
             Layout.AddElement(breakForceField);
             Layout.AddElement(breakTorqueField);
             Layout.AddElement(breakTorqueField);
             Layout.AddElement(collisionField);
             Layout.AddElement(collisionField);

+ 1 - 1
Source/MBansheeEditor/Inspectors/SliderJointInspector.cs

@@ -76,7 +76,7 @@ namespace BansheeEditor
             
             
             ToggleLimitFields(joint.EnableLimit);
             ToggleLimitFields(joint.EnableLimit);
 
 
-            base.BuildGUI(joint);
+            base.BuildGUI(joint, true);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
Source/MBansheeEditor/Inspectors/SphericalJointInspector.cs

@@ -76,7 +76,7 @@ namespace BansheeEditor
 
 
             ToggleLimitFields(joint.EnableLimit);
             ToggleLimitFields(joint.EnableLimit);
 
 
-            base.BuildGUI(joint);
+            base.BuildGUI(joint, true);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 3 - 11
Source/MBansheeEditor/Windows/Scene/Gizmos/JointGizmos.cs

@@ -49,21 +49,13 @@ namespace BansheeEditor
         {
         {
             Vector3 target = GetAnchor(joint, JointBody.Target);
             Vector3 target = GetAnchor(joint, JointBody.Target);
             Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
             Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
-            Vector3 center = target;
-
-            Rigidbody rigidbody = joint.GetRigidbody(JointBody.Target);
-            if (rigidbody != null)
-                center = rigidbody.SceneObject.Position;
 
 
             Gizmos.Color = Color.White;
             Gizmos.Color = Color.White;
-            Gizmos.DrawSphere(center, 0.05f);
-
-            Gizmos.Color = Color.Yellow;
             Gizmos.DrawSphere(target, 0.05f);
             Gizmos.DrawSphere(target, 0.05f);
             Gizmos.DrawSphere(anchor, 0.05f);
             Gizmos.DrawSphere(anchor, 0.05f);
 
 
             Gizmos.Color = Color.Green;
             Gizmos.Color = Color.Green;
-            Gizmos.DrawLine(target, center);
+            Gizmos.DrawLine(target, anchor);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -179,8 +171,8 @@ namespace BansheeEditor
             {
             {
                 LimitConeRange limit = joint.Limit;
                 LimitConeRange limit = joint.Limit;
 
 
-                Radian zAngle = MathEx.Min(new Degree(360), limit.ZLimitAngle*2.0f);
-                Radian yAngle = MathEx.Min(new Degree(360), limit.YLimitAngle*2.0f);
+                Radian zAngle = MathEx.Min(new Degree(360), limit.ZLimitAngle * 2.0f);
+                Radian yAngle = MathEx.Min(new Degree(360), limit.YLimitAngle * 2.0f);
 
 
                 Gizmos.Transform = joint.SceneObject.WorldTransform;
                 Gizmos.Transform = joint.SceneObject.WorldTransform;
                 Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * -0.5f + new Degree(90), zAngle);
                 Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * -0.5f + new Degree(90), zAngle);

+ 30 - 0
Source/MBansheeEngine/Physics/FixedJoint.cs

@@ -11,6 +11,36 @@ namespace BansheeEngine
     /// </summary>
     /// </summary>
     public sealed class FixedJoint : Joint
     public sealed class FixedJoint : Joint
     {
     {
+        /// <inheritdoc/>
+        protected override void GetLocalTransform(JointBody body, out Vector3 position, out Quaternion rotation)
+        {
+            position = commonData.positions[(int)body];
+            rotation = commonData.rotations[(int)body];
+
+            Rigidbody rigidbody = commonData.bodies[(int)body];
+            if (rigidbody == null) // Get world space transform if not relative to any body
+            {
+                Quaternion worldRot = SceneObject.Rotation;
+
+                rotation = worldRot * rotation;
+                position = worldRot.Rotate(position) + SceneObject.Position;
+            }
+            else // Get transform of the object relative to the joint
+            {
+                // Find world space transform
+                Quaternion worldRot = rigidbody.SceneObject.Rotation;
+
+                rotation = worldRot * rotation;
+                position = worldRot.Rotate(position) + rigidbody.SceneObject.Position;
+
+                // Get transform of the joint local to the object
+                Quaternion invRotation = rotation.Inverse;
+
+                position = invRotation.Rotate(SceneObject.Position - position);
+                rotation = invRotation * SceneObject.Rotation;
+            }
+        }
+
         /// <inheritdoc/>
         /// <inheritdoc/>
         internal override NativeJoint CreateNative()
         internal override NativeJoint CreateNative()
         {
         {

+ 8 - 8
Source/MBansheeEngine/Physics/HingeJoint.cs

@@ -125,6 +125,14 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeHingeJoint Native
+        {
+            get { return (NativeHingeJoint)native; }
+        }
+
         /// <summary>
         /// <summary>
         /// Toggles a specific distance joint flag on or off.
         /// Toggles a specific distance joint flag on or off.
         /// </summary>
         /// </summary>
@@ -147,14 +155,6 @@ namespace BansheeEngine
             return true;
             return true;
         }
         }
 
 
-        /// <summary>
-        /// Returns the native joint wrapped by this component.
-        /// </summary>
-        private NativeHingeJoint Native
-        {
-            get { return (NativeHingeJoint)native; }
-        }
-
         /// <inheritdoc/>
         /// <inheritdoc/>
         internal override NativeJoint CreateNative()
         internal override NativeJoint CreateNative()
         {
         {

+ 3 - 3
Source/MBansheeEngine/Physics/Joint.cs

@@ -325,17 +325,17 @@ namespace BansheeEngine
         /// <param name="body">Body to calculate the transform for.</param>
         /// <param name="body">Body to calculate the transform for.</param>
         /// <param name="position">Output position for the body.</param>
         /// <param name="position">Output position for the body.</param>
         /// <param name="rotation">Output rotation for the body.</param>
         /// <param name="rotation">Output rotation for the body.</param>
-        private void GetLocalTransform(JointBody body, out Vector3 position, out Quaternion rotation)
+        protected virtual void GetLocalTransform(JointBody body, out Vector3 position, out Quaternion rotation)
         {
         {
             position = commonData.positions[(int)body];
             position = commonData.positions[(int)body];
             rotation = commonData.rotations[(int)body];
             rotation = commonData.rotations[(int)body];
 
 
             Rigidbody rigidbody = commonData.bodies[(int)body];
             Rigidbody rigidbody = commonData.bodies[(int)body];
-            if (rigidbody == null) // Get world space transform if no relative to any body
+            if (rigidbody == null) // Get world space transform if not relative to any body
             {
             {
                 Quaternion worldRot = SceneObject.Rotation;
                 Quaternion worldRot = SceneObject.Rotation;
 
 
-                rotation = worldRot*rotation;
+                rotation = worldRot * rotation;
                 position = worldRot.Rotate(position) + SceneObject.Position;
                 position = worldRot.Rotate(position) + SceneObject.Position;
             }
             }
             else
             else

+ 24 - 0
Source/MBansheeEngine/Physics/SliderJoint.cs

@@ -67,6 +67,30 @@ namespace BansheeEngine
             return joint;
             return joint;
         }
         }
 
 
+        /// <inheritdoc/>
+        protected override void GetLocalTransform(JointBody body, out Vector3 position, out Quaternion rotation)
+        {
+            position = commonData.positions[(int)body];
+            rotation = commonData.rotations[(int)body];
+
+            Rigidbody rigidbody = commonData.bodies[(int)body];
+            if (rigidbody == null) // Get world space transform if not relative to any body
+            {
+                Quaternion worldRot = SceneObject.Rotation;
+
+                rotation = worldRot * rotation;
+                position = worldRot.Rotate(position) + SceneObject.Position;
+            }
+            else
+            {
+                // Use only the offset for positioning, but for rotation use both the offset and target SO rotation.
+                // (Needed because we need to rotate the joint SO in order to orient the slider direction, so we need an
+                // additional transform that allows us to orient the object)
+                position = rotation.Rotate(position);
+                rotation = (rigidbody.SceneObject.Rotation*rotation).Inverse*SceneObject.Rotation;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Holds all data the joint component needs to persist through serialization.
         /// Holds all data the joint component needs to persist through serialization.
         /// </summary>
         /// </summary>