Browse Source

Added collider and character controller gizmo drawing

BearishSun 9 years ago
parent
commit
efb4a11f1f

+ 1 - 1
BansheeCore/Include/BsCPlaneCollider.h

@@ -54,7 +54,7 @@ namespace BansheeEngine
 		bool isValidParent(const HRigidbody& parent) const override;
 
     protected:
-		Vector3 mNormal = Vector3::UNIT_Y;
+		Vector3 mNormal = Vector3::UNIT_X;
 		float mDistance = 0.0f;
 
 		/************************************************************************/

+ 11 - 0
BansheeEditor/Include/BsGizmoManager.h

@@ -95,6 +95,15 @@ namespace BansheeEngine
 		 */
 		void drawWireSphere(const Vector3& position, float radius);
 
+		/**
+		 * Draws a wireframe capsule.
+		 *
+		 * @param[in]	position	World coordinates of the center of the capsule.
+		 * @param[in]	height		Distance between the centers of the capsule's hemispheres.
+		 * @param[in]	radius		Distance of each point from the capsule's center-line.
+		 */
+		void drawWireCapsule(const Vector3& position, float height, float radius);
+
 		/**
 		 * Draws a line between two points.
 		 *
@@ -367,6 +376,8 @@ namespace BansheeEngine
 		HSceneObject mActiveSO;
 		bool mPickable;
 		UINT32 mCurrentIdx;
+		bool mTransformDirty;
+		bool mColorDirty;
 
 		DrawHelper* mDrawHelper;
 		DrawHelper* mPickingDrawHelper;

+ 52 - 1
BansheeEditor/Source/BsGizmoManager.cpp

@@ -33,7 +33,9 @@ namespace BansheeEngine
 	const float GizmoManager::ICON_TEXEL_WORLD_SIZE = 0.05f;
 
 	GizmoManager::GizmoManager()
-		:mPickable(false), mDrawHelper(nullptr), mPickingDrawHelper(nullptr), mCore(nullptr), mCurrentIdx(0)
+		: mPickable(false), mCurrentIdx(0), mTransformDirty(false), mColorDirty(false), mDrawHelper(nullptr)
+		, mPickingDrawHelper(nullptr), mCore(nullptr)
+		
 	{
 		mTransform = Matrix4::IDENTITY;
 		mDrawHelper = bs_new<DrawHelper>();
@@ -95,6 +97,18 @@ namespace BansheeEngine
 	void GizmoManager::startGizmo(const HSceneObject& gizmoParent)
 	{
 		mActiveSO = gizmoParent;
+
+		if(mTransformDirty)
+		{
+			mTransform = Matrix4::IDENTITY;
+			mTransformDirty = false;
+		}
+
+		if(mColorDirty)
+		{
+			mColor = Color();
+			mColorDirty = false;
+		}
 	}
 
 	void GizmoManager::endGizmo()
@@ -106,12 +120,16 @@ namespace BansheeEngine
 	{
 		mDrawHelper->setColor(color);
 		mColor = color;
+
+		mColorDirty = true;
 	}
 
 	void GizmoManager::setTransform(const Matrix4& transform)
 	{
 		mDrawHelper->setTransform(transform);
 		mTransform = transform;
+
+		mTransformDirty = true;
 	}
 
 	void GizmoManager::drawCube(const Vector3& position, const Vector3& extents)
@@ -182,6 +200,39 @@ namespace BansheeEngine
 		mIdxToSceneObjectMap[sphereData.idx] = mActiveSO;
 	}
 
+	void GizmoManager::drawWireCapsule(const Vector3& position, float height, float radius)
+	{
+		float halfHeight = height * 0.5f;
+
+		// Draw capsule sides
+		Vector3 sideNegXBottom = position + Vector3(-radius, -halfHeight, 0.0f);
+		Vector3 sideNegXTop = position + Vector3(-radius, halfHeight, 0.0f);
+
+		Vector3 sidePosXBottom = position + Vector3(radius, -halfHeight, 0.0f);
+		Vector3 sidePosXTop = position + Vector3(radius, halfHeight, 0.0f);
+
+		Vector3 sideNegZBottom = position + Vector3(0.0f, -halfHeight, -radius);
+		Vector3 sideNegZTop = position + Vector3(0.0f, halfHeight, -radius);
+
+		Vector3 sidePosZBottom = position + Vector3(0.0f, -halfHeight, radius);
+		Vector3 sidePosZTop = position + Vector3(0.0f, halfHeight, radius);
+
+		drawLine(sideNegXBottom, sideNegXTop);
+		drawLine(sidePosXBottom, sidePosXTop);
+		drawLine(sideNegZBottom, sideNegZTop);
+		drawLine(sidePosZBottom, sidePosZTop);
+
+		// Draw capsule caps
+		Vector3 topHemisphere = position + Vector3(0.0f, halfHeight, 0.0f);
+		Vector3 botHemisphere = position + Vector3(0.0f, -halfHeight, 0.0f);
+
+		drawWireArc(topHemisphere, Vector3::UNIT_X, radius, Degree(0.0f), Degree(180.0f));
+		drawWireArc(topHemisphere, Vector3::UNIT_Z, radius, Degree(0.0f), Degree(180.0f));
+
+		drawWireArc(botHemisphere, Vector3::UNIT_X, radius, Degree(180.0f), Degree(180.0f));
+		drawWireArc(botHemisphere, Vector3::UNIT_Z, radius, Degree(180.0f), Degree(180.0f));
+	}
+
 	void GizmoManager::drawLine(const Vector3& start, const Vector3& end)
 	{
 		mLineData.push_back(LineData());

+ 3 - 1
MBansheeEditor/MBansheeEditor.csproj

@@ -152,7 +152,9 @@
     <Compile Include="ProjectSettings.cs" />
     <Compile Include="Library\LibraryWindow.cs" />
     <Compile Include="ProjectWindow.cs" />
-    <Compile Include="Scene\LightGizmos.cs" />
+    <Compile Include="Scene\Gizmos\CharacterControllerGizmo.cs" />
+    <Compile Include="Scene\Gizmos\ColliderGizmos.cs" />
+    <Compile Include="Scene\Gizmos\LightGizmos.cs" />
     <Compile Include="Scene\SceneAxesGUI.cs" />
     <Compile Include="Scene\SceneAxesHandle.cs" />
     <Compile Include="Scene\SceneCamera.cs" />

+ 1 - 1
MBansheeEditor/Scene/DrawGizmo.cs

@@ -1,7 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 using System;
-using BansheeEngine;
 
 namespace BansheeEditor
 {
@@ -9,6 +8,7 @@ namespace BansheeEditor
     /// Controls when a gizmo is displayed and whether it can be interacted with. These flags can be combined to achieve
     /// different effect.
     /// </summary>
+    [Flags]
     public enum DrawGizmoFlags // Note: Must match the C++ enum DrawGizmoFlags
     {
         /// <summary>Gizmo is only displayed when its scene object is selected.</summary>

+ 14 - 0
MBansheeEditor/Scene/Gizmos.cs

@@ -88,6 +88,17 @@ namespace BansheeEditor
             Internal_DrawWireSphere(ref position, radius);
         }
 
+        /// <summary>
+        /// Draws a wireframe capsule. Capsule is assumed to be extending along the Y axis.
+        /// </summary>
+        /// <param name="position">World coordinates of the center of the capsule.</param>
+        /// <param name="height">Distance between the centers of the capsule's hemispheres.</param>
+        /// <param name="radius">Distance of each point from the capsule's center-line.</param>
+        public static void DrawWireCapsule(Vector3 position, float height, float radius)
+        {
+            Internal_DrawWireCapsule(ref position, height, radius);
+        }
+
         /// <summary>
         /// Draws a 3D line.
         /// </summary>
@@ -196,6 +207,9 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_DrawWireSphere(ref Vector3 position, float radius);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_DrawWireCapsule(ref Vector3 position, float height, float radius);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_DrawLine(ref Vector3 start, ref Vector3 end);
 

+ 30 - 0
MBansheeEditor/Scene/Gizmos/CharacterControllerGizmo.cs

@@ -0,0 +1,30 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Handles drawing of gizmos for the <see cref="CharacterController"/> component.
+    /// </summary>
+    internal class CharacterControllerGizmo
+    {
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="controller">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected)]
+        private static void Draw(CharacterController controller)
+        {
+            SceneObject so = controller.SceneObject;
+
+            Vector3 offset = so.Position;
+            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, controller.Up);
+            Gizmos.Transform = Matrix4.TRS(-offset, rotation, Vector3.One);
+
+            Gizmos.Color = Color.Green;
+
+            Gizmos.DrawWireCapsule(offset, controller.Height, controller.Radius);
+        }
+    }
+}

+ 149 - 0
MBansheeEditor/Scene/Gizmos/ColliderGizmos.cs

@@ -0,0 +1,149 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Handles drawing of gizmos for all the types of <see cref="Collider"/> component.
+    /// </summary>
+    internal class ColliderGizmos
+    {
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawBoxCollider(BoxCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+            Vector3 scaledExtents = collider.Extents*so.Scale;
+
+            Gizmos.DrawWireCube(so.WorldTransform.MultiplyAffine(collider.Center), scaledExtents);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawSphereCollider(SphereCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+
+            Vector3 scale = so.Scale;
+            float scaledRadius = collider.Radius * MathEx.Max(scale.x, scale.y, scale.z);
+
+            Gizmos.DrawWireSphere(so.WorldTransform.MultiplyAffine(collider.Center), scaledRadius);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawCapsuleCollider(CapsuleCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Vector3 offset = so.WorldTransform.MultiplyAffine(collider.Center);
+            Quaternion rotation = Quaternion.FromToRotation(Vector3.YAxis, collider.Normal);
+            Gizmos.Transform = Matrix4.TRS(-offset, rotation, Vector3.One);
+
+            Gizmos.Color = Color.Green;
+
+            Vector3 scale = so.Scale;
+            float scaledHeight = collider.HalfHeight*2.0f*scale.y;
+            float scaledRadius = collider.Radius*MathEx.Max(scale.x, scale.z);
+
+            Gizmos.DrawWireCapsule(offset, scaledHeight, scaledRadius);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawMeshCollider(MeshCollider collider)
+        {
+            PhysicsMesh mesh = collider.Mesh;
+            if (mesh == null)
+                return;
+
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Transform = so.WorldTransform;
+            Gizmos.Color = Color.Green;
+
+            MeshData meshData = mesh.MeshData;
+
+            int numTriangles = meshData.IndexCount/3;
+            int[] indices = meshData.Indices;
+            Vector3[] vertices = meshData.Positions;
+            Vector3[] linePoints = new Vector3[numTriangles*6];
+
+            for (int i = 0; i < numTriangles; i++)
+            {
+                int lineIdx = i*6;
+
+                linePoints[lineIdx + 0] = vertices[indices[i * 3 + 0]];
+                linePoints[lineIdx + 1] = vertices[indices[i * 3 + 1]];
+
+                linePoints[lineIdx + 2] = vertices[indices[i * 3 + 1]];
+                linePoints[lineIdx + 3] = vertices[indices[i * 3 + 2]];
+
+                linePoints[lineIdx + 4] = vertices[indices[i * 3 + 2]];
+                linePoints[lineIdx + 5] = vertices[indices[i * 3 + 0]];
+            }
+
+            Gizmos.DrawLineList(linePoints);
+        }
+
+        /// <summary>
+        /// Method called by the runtime when gizmos are meant to be drawn.
+        /// </summary>
+        /// <param name="collider">Collider to draw gizmos for.</param>
+        [DrawGizmo(DrawGizmoFlags.Selected | DrawGizmoFlags.ParentSelected)]
+        private static void DrawPlaneCollider(PlaneCollider collider)
+        {
+            SceneObject so = collider.SceneObject;
+
+            Gizmos.Color = Color.Green;
+
+            Vector3 localNormal = collider.Normal;
+            Vector3 localCenter = localNormal * collider.Distance;
+
+            Vector3 bottomLeft = new Vector3(0.0f, -0.5f, -0.5f);
+            Vector3 topLeft = new Vector3(0.0f, 0.5f, -0.5f);
+            Vector3 topRight = new Vector3(0.0f, 0.5f, 0.5f);
+            Vector3 bottomRight = new Vector3(0.0f, -0.5f, 0.5f);
+
+            bottomLeft += localCenter;
+            topLeft += localCenter;
+            topRight += localCenter;
+            bottomRight += localCenter;
+
+            bottomLeft = so.WorldTransform.MultiplyAffine(bottomLeft);
+            topLeft = so.WorldTransform.MultiplyAffine(topLeft);
+            topRight = so.WorldTransform.MultiplyAffine(topRight);
+            bottomRight = so.WorldTransform.MultiplyAffine(bottomRight);
+
+            Vector3 center = so.WorldTransform.MultiplyAffine(localCenter);
+            Vector3 normal = localNormal;
+            normal = so.WorldTransform.MultiplyDirection(normal);
+
+            // Draw sides
+            Gizmos.DrawLine(bottomLeft, topLeft);
+            Gizmos.DrawLine(topLeft, topRight);
+            Gizmos.DrawLine(topRight, bottomRight);
+            Gizmos.DrawLine(bottomRight, bottomLeft);
+
+            // Draw normal
+            Gizmos.DrawLine(center, center + normal*0.5f);
+        }
+    }
+}

+ 0 - 0
MBansheeEditor/Scene/LightGizmos.cs → MBansheeEditor/Scene/Gizmos/LightGizmos.cs


+ 1 - 1
MBansheeEngine/Physics/PlaneCollider.cs

@@ -11,7 +11,7 @@ namespace BansheeEngine
         private float distance;
 
         [SerializeField]
-        private Vector3 normal;
+        private Vector3 normal = new Vector3(1.0f, 0.0f, 0.0f);
 
         /// <summary>
         /// Distance of the plane from the local origin, along its normal vector.

+ 2 - 2
SBansheeEditor/Include/BsScriptGizmoManager.h

@@ -19,8 +19,8 @@ namespace BansheeEngine
 		Pickable = 0x08 /**< Gizmo can be clicked on in scene view, which will select its scene object. */
 	};
 
-	/**
-	 * @brief	Manages all active managed gizmo methods.
+	/** 
+	 * Manages all active managed gizmo methods. Finds all gizmos methods in loaded assemblies, and calls them every frame. 
 	 */
 	class BS_SCR_BED_EXPORT ScriptGizmoManager : public Module<ScriptGizmoManager>
 	{

+ 1 - 0
SBansheeEditor/Include/BsScriptGizmos.h

@@ -30,6 +30,7 @@ namespace BansheeEngine
 		static void internal_DrawSphere(Vector3* position, float radius);
 		static void internal_DrawWireCube(Vector3* position, Vector3* extents);
 		static void internal_DrawWireSphere(Vector3* position, float radius);
+		static void internal_DrawWireCapsule(Vector3* position, float height, float radius);
 		static void internal_DrawLine(Vector3* start, Vector3* end);
 		static void internal_DrawLineList(MonoArray* linePoints);
 		static void internal_DrawWireDisc(Vector3* position, Vector3* normal, float radius);

+ 6 - 0
SBansheeEditor/Source/BsScriptGizmos.cpp

@@ -20,6 +20,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_DrawSphere", &ScriptGizmos::internal_DrawSphere);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireCube", &ScriptGizmos::internal_DrawWireCube);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireSphere", &ScriptGizmos::internal_DrawWireSphere);
+		metaData.scriptClass->addInternalCall("Internal_DrawWireCapsule", &ScriptGizmos::internal_DrawWireCapsule);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireDisc", &ScriptGizmos::internal_DrawWireDisc);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireArc", &ScriptGizmos::internal_DrawWireArc);
 		metaData.scriptClass->addInternalCall("Internal_DrawLine", &ScriptGizmos::internal_DrawLine);
@@ -69,6 +70,11 @@ namespace BansheeEngine
 		GizmoManager::instance().drawWireSphere(*position, radius);
 	}
 
+	void ScriptGizmos::internal_DrawWireCapsule(Vector3* position, float height, float radius)
+	{
+		GizmoManager::instance().drawWireCapsule(*position, height, radius);
+	}
+
 	void ScriptGizmos::internal_DrawLine(Vector3* start, Vector3* end)
 	{
 		GizmoManager::instance().drawLine(*start, *end);