Kaynağa Gözat

Extended gizmo drawing so it supports line lists

BearishSun 9 yıl önce
ebeveyn
işleme
9a7a80e9ae

+ 22 - 8
BansheeEditor/Include/BsGizmoManager.h

@@ -102,6 +102,13 @@ namespace BansheeEngine
 		 */
 		void drawLine(const Vector3& start, const Vector3& end);
 
+		/**
+		 * Draws a list of lines. Provided array must contain pairs of the line start point followed by an end point.
+		 *
+		 * @note	Must be called between startGizmo/endGizmo calls.
+		 */
+		void drawLineList(const Vector<Vector3>& linePoints);
+
 		/**
 		 * Draws a wireframe disc.
 		 *
@@ -217,28 +224,34 @@ namespace BansheeEngine
 		};
 
 		/**	Data required for rendering a cuboid gizmo. */
-		struct CubeData : public CommonData
+		struct CubeData : CommonData
 		{
 			Vector3 position;
 			Vector3 extents;
 		};
 
 		/**	Data required for rendering a sphere gizmo. */
-		struct SphereData : public CommonData
+		struct SphereData : CommonData
 		{
 			Vector3 position;
 			float radius;
 		};
 
 		/**	Data required for rendering a line gizmo. */
-		struct LineData : public CommonData
+		struct LineData : CommonData
 		{
 			Vector3 start;
 			Vector3 end;
 		};
 
+		/**	Data required for rendering a list of lines. */
+		struct LineListData : CommonData
+		{
+			Vector<Vector3> linePoints;
+		};
+
 		/**	Data required for rendering a wireframe disc gizmo. */
-		struct WireDiscData : public CommonData
+		struct WireDiscData : CommonData
 		{
 			Vector3 position;
 			Vector3 normal;
@@ -246,7 +259,7 @@ namespace BansheeEngine
 		};
 
 		/**	Data required for rendering a wireframe arc gizmo. */
-		struct WireArcData : public CommonData
+		struct WireArcData : CommonData
 		{
 			Vector3 position;
 			Vector3 normal;
@@ -256,7 +269,7 @@ namespace BansheeEngine
 		};
 
 		/**	Data required for rendering a frustum gizmo. */
-		struct FrustumData : public CommonData
+		struct FrustumData : CommonData
 		{
 			Vector3 position;
 			float aspect;
@@ -266,7 +279,7 @@ namespace BansheeEngine
 		};
 
 		/**	Data required for rendering an icon gizmo. */
-		struct IconData : public CommonData
+		struct IconData : CommonData
 		{
 			Vector3 position;
 			bool fixedScale;
@@ -274,7 +287,7 @@ namespace BansheeEngine
 		};
 
 		/**	Data required for rendering text. */
-		struct TextData : public CommonData
+		struct TextData : CommonData
 		{
 			Vector3 position;
 			WString text;
@@ -363,6 +376,7 @@ namespace BansheeEngine
 		Vector<SphereData> mSolidSphereData;
 		Vector<SphereData> mWireSphereData;
 		Vector<LineData> mLineData;
+		Vector<LineListData> mLineListData;
 		Vector<WireDiscData> mWireDiscData;
 		Vector<WireArcData> mWireArcData;
 		Vector<FrustumData> mFrustumData;

+ 28 - 0
BansheeEditor/Source/BsGizmoManager.cpp

@@ -199,6 +199,22 @@ namespace BansheeEngine
 		mIdxToSceneObjectMap[lineData.idx] = mActiveSO;
 	}
 
+	void GizmoManager::drawLineList(const Vector<Vector3>& linePoints)
+	{
+		mLineListData.push_back(LineListData());
+		LineListData& lineListData = mLineListData.back();
+
+		lineListData.idx = mCurrentIdx++;
+		lineListData.linePoints = linePoints;
+		lineListData.color = mColor;
+		lineListData.transform = mTransform;
+		lineListData.sceneObject = mActiveSO;
+		lineListData.pickable = mPickable;
+
+		mDrawHelper->lineList(linePoints);
+		mIdxToSceneObjectMap[lineListData.idx] = mActiveSO;
+	}
+
 	void GizmoManager::drawWireDisc(const Vector3& position, const Vector3& normal, float radius)
 	{
 		mWireDiscData.push_back(WireDiscData());
@@ -406,6 +422,17 @@ namespace BansheeEngine
 			mPickingDrawHelper->line(lineDataEntry.start, lineDataEntry.end);
 		}
 
+		for (auto& lineListDataEntry : mLineListData)
+		{
+			if (!lineListDataEntry.pickable)
+				continue;
+
+			mPickingDrawHelper->setColor(idxToColorCallback(lineListDataEntry.idx));
+			mPickingDrawHelper->setTransform(lineListDataEntry.transform);
+
+			mPickingDrawHelper->lineList(lineListDataEntry.linePoints);
+		}
+
 		for (auto& wireDiscDataEntry : mWireDiscData)
 		{
 			if (!wireDiscDataEntry.pickable)
@@ -508,6 +535,7 @@ namespace BansheeEngine
 		mSolidSphereData.clear();
 		mWireSphereData.clear();
 		mLineData.clear();
+		mLineListData.clear();
 		mWireDiscData.clear();
 		mWireArcData.clear();
 		mFrustumData.clear();

+ 21 - 9
BansheeEngine/Include/BsDrawHelper.h

@@ -67,6 +67,12 @@ namespace BansheeEngine
 		/**	Records a line with the specified properties in the internal draw queue. */
 		void line(const Vector3& start, const Vector3& end);
 
+		/**	
+		 * Records a list of lines in the internal draw queue. The list must contain lines as pair of vertices, starting
+		 * point followed by an end point, and so on.
+		 */
+		void lineList(const Vector<Vector3>& lines);
+
 		/**	Records a wireframe frustum with the specified properties in the internal draw queue. */
 		void frustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
 
@@ -134,31 +140,36 @@ namespace BansheeEngine
 			UINT64 layer;
 		};
 
-		struct CubeData : public CommonData
+		struct CubeData : CommonData
 		{
 			Vector3 position;
 			Vector3 extents;
 		};
 
-		struct SphereData : public CommonData
+		struct SphereData : CommonData
 		{
 			Vector3 position;
 			float radius;
 			UINT32 quality;
 		};
 
-		struct LineData : public CommonData
+		struct LineData : CommonData
 		{
 			Vector3 start;
 			Vector3 end;
 		};
 
-		struct Rect3Data : public CommonData
+		struct LineListData : CommonData
+		{
+			Vector<Vector3> lines;
+		};
+
+		struct Rect3Data : CommonData
 		{
 			Rect3 area;
 		};
 
-		struct FrustumData : public CommonData
+		struct FrustumData : CommonData
 		{
 			Vector3 position;
 			float aspect;
@@ -167,7 +178,7 @@ namespace BansheeEngine
 			float far;
 		};
 
-		struct ConeData : public CommonData
+		struct ConeData : CommonData
 		{
 			Vector3 base;
 			Vector3 normal;
@@ -176,7 +187,7 @@ namespace BansheeEngine
 			UINT32 quality;
 		};
 
-		struct DiscData : public CommonData
+		struct DiscData : CommonData
 		{
 			Vector3 position;
 			Vector3 normal;
@@ -184,7 +195,7 @@ namespace BansheeEngine
 			UINT32 quality;
 		};
 
-		struct ArcData : public CommonData
+		struct ArcData : CommonData
 		{
 			Vector3 position;
 			Vector3 normal;
@@ -194,7 +205,7 @@ namespace BansheeEngine
 			UINT32 quality;
 		};
 
-		struct Text2DData : public CommonData
+		struct Text2DData : CommonData
 		{
 			Vector3 position;
 			WString text;
@@ -214,6 +225,7 @@ namespace BansheeEngine
 		Vector<SphereData> mSolidSphereData;
 		Vector<SphereData> mWireSphereData;
 		Vector<LineData> mLineData;
+		Vector<LineListData> mLineListData;
 		Vector<Rect3Data> mRect3Data;
 		Vector<FrustumData> mFrustumData;
 		Vector<ConeData> mConeData;

+ 53 - 1
BansheeEngine/Source/BsDrawHelper.cpp

@@ -127,6 +127,25 @@ namespace BansheeEngine
 		lineData.center = mTransform.multiplyAffine((start + end) * 0.5f);
 	}
 
+	void DrawHelper::lineList(const Vector<Vector3>& lines)
+	{
+		if (lines.size() < 2)
+			return;
+
+		mLineListData.push_back(LineListData());
+		LineListData& lineListData = mLineListData.back();
+
+		Vector3 center;
+		for (auto& point : lines)
+			center += point;
+
+		lineListData.lines = lines;
+		lineListData.color = mColor;
+		lineListData.transform = mTransform;
+		lineListData.layer = mLayer;
+		lineListData.center = center / (UINT32)lines.size();;
+	}
+
 	void DrawHelper::frustum(const Vector3& position, float aspect, Degree FOV, float near, float far)
 	{
 		mFrustumData.push_back(FrustumData());
@@ -262,6 +281,7 @@ namespace BansheeEngine
 		mSolidSphereData.clear();
 		mWireSphereData.clear();
 		mLineData.clear();
+		mLineListData.clear();
 		mRect3Data.clear();
 		mFrustumData.clear();
 		mFrustumData.clear();
@@ -279,7 +299,7 @@ namespace BansheeEngine
 
 		enum class ShapeType
 		{
-			Cube, Sphere, WireCube, WireSphere, Line, Frustum, 
+			Cube, Sphere, WireCube, WireSphere, Line, LineList, Frustum, 
 			Cone, Disc, WireDisc, Arc, WireArc, Rectangle, Text
 		};
 
@@ -495,6 +515,28 @@ namespace BansheeEngine
 			rawData.numIndices = 2;
 		}
 
+		localIdx = 0;
+		for (auto& shapeData : mLineListData)
+		{
+			if ((shapeData.layer & layers) == 0)
+			{
+				localIdx++;
+				continue;
+			}
+
+			allShapes.push_back(RawData());
+			RawData& rawData = allShapes.back();
+
+			UINT32 numLines = (UINT32)shapeData.lines.size() / 2;
+			rawData.idx = localIdx++;
+			rawData.textIdx = 0;
+			rawData.meshType = MeshType::Wire;
+			rawData.shapeType = ShapeType::LineList;
+			rawData.distance = shapeData.center.distance(reference);
+			rawData.numVertices = numLines * 2;
+			rawData.numIndices = numLines * 2;
+		}
+
 		localIdx = 0;
 		for (auto& shapeData : mFrustumData)
 		{
@@ -855,6 +897,16 @@ namespace BansheeEngine
 						color = lineData.color.getAsRGBA();
 					}
 						break;
+					case ShapeType::LineList:
+					{
+						LineListData& lineListData = mLineListData[shapeData.idx];
+
+						ShapeMeshes3D::pixelLineList(lineListData.lines, meshData, curVertexOffset, curIndexOffet);
+
+						transform = &lineListData.transform;
+						color = lineListData.color.getAsRGBA();
+					}
+					break;
 					case ShapeType::Frustum:
 					{
 						FrustumData& frustumData = mFrustumData[shapeData.idx];

+ 13 - 13
BansheeEngine/Source/BsShapeMeshes3D.cpp

@@ -191,19 +191,6 @@ namespace BansheeEngine
 		pixelLine(a, b, positionData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
 	}
 
-	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, 
-		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
-	{
-		UINT32* indexData = meshData->getIndices32();
-		UINT8* positionData = meshData->getElementData(VES_POSITION);
-		UINT8* colorData = meshData->getElementData(VES_COLOR);
-
-		assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
-		assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
-
-		antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
-	}
-
 	void ShapeMeshes3D::pixelLineList(const Vector<Vector3>& linePoints, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
 	{
 		assert(linePoints.size() % 2 == 0);
@@ -227,6 +214,19 @@ namespace BansheeEngine
 		}
 	}
 
+	void ShapeMeshes3D::antialiasedLine(const Vector3& a, const Vector3& b, const Vector3& up, float width, float borderWidth, 
+		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
+	{
+		UINT32* indexData = meshData->getIndices32();
+		UINT8* positionData = meshData->getElementData(VES_POSITION);
+		UINT8* colorData = meshData->getElementData(VES_COLOR);
+
+		assert((vertexOffset + NUM_VERTICES_AA_LINE) <= meshData->getNumVertices());
+		assert((indexOffset + NUM_INDICES_AA_LINE) <= meshData->getNumIndices());
+
+		antialiasedLine(a, b, up, width, borderWidth, color, positionData, colorData, vertexOffset, meshData->getVertexDesc()->getVertexStride(), indexData, indexOffset);
+	}
+
 	void ShapeMeshes3D::antialiasedLineList(const Vector<Vector3>& linePoints, const Vector3& up, float width, float borderWidth, 
 		const Color& color, const MeshDataPtr& meshData, UINT32 vertexOffset, UINT32 indexOffset)
 	{

+ 12 - 0
MBansheeEditor/Scene/Gizmos.cs

@@ -98,6 +98,15 @@ namespace BansheeEditor
             Internal_DrawLine(ref start, ref end);
         }
 
+        /// <summary>
+        /// Draws a list of 3D lines.
+        /// </summary>
+        /// <param name="linePoints">A list of line point pairs, start point followed by end point, and so on.</param>
+        public static void DrawLineList(Vector3[] linePoints)
+        {
+            Internal_DrawLineList(linePoints);
+        }
+
         /// <summary>
         /// Draws a wireframe disc.
         /// </summary>
@@ -190,6 +199,9 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_DrawLine(ref Vector3 start, ref Vector3 end);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_DrawLineList(Vector3[] linePoints);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_DrawWireDisc(ref Vector3 position, ref Vector3 normal, float radius);
 

+ 1 - 0
SBansheeEditor/Include/BsScriptGizmos.h

@@ -31,6 +31,7 @@ namespace BansheeEngine
 		static void internal_DrawWireCube(Vector3* position, Vector3* extents);
 		static void internal_DrawWireSphere(Vector3* position, 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);
 		static void internal_DrawWireArc(Vector3* position, Vector3* normal, float radius, float startAngle, float amountAngle);
 		static void internal_DrawFrustum(Vector3* position, float aspect, Degree* FOV, float near, float far);

+ 13 - 0
SBansheeEditor/Source/BsScriptGizmos.cpp

@@ -23,6 +23,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_DrawWireDisc", &ScriptGizmos::internal_DrawWireDisc);
 		metaData.scriptClass->addInternalCall("Internal_DrawWireArc", &ScriptGizmos::internal_DrawWireArc);
 		metaData.scriptClass->addInternalCall("Internal_DrawLine", &ScriptGizmos::internal_DrawLine);
+		metaData.scriptClass->addInternalCall("Internal_DrawLineList", &ScriptGizmos::internal_DrawLineList);
 		metaData.scriptClass->addInternalCall("Internal_DrawFrustum", &ScriptGizmos::internal_DrawFrustum);
 		metaData.scriptClass->addInternalCall("Internal_DrawIcon", &ScriptGizmos::internal_DrawIcon);
 		metaData.scriptClass->addInternalCall("Internal_DrawText", &ScriptGizmos::internal_DrawText);
@@ -73,6 +74,18 @@ namespace BansheeEngine
 		GizmoManager::instance().drawLine(*start, *end);
 	}
 
+	void ScriptGizmos::internal_DrawLineList(MonoArray* linePoints)
+	{
+		ScriptArray lineArray(linePoints);
+
+		UINT32 numElements = lineArray.size();
+		Vector<Vector3> points(numElements);
+		for (UINT32 i = 0; i < numElements; i++)
+			points[i] = lineArray.get<Vector3>(i);
+
+		GizmoManager::instance().drawLineList(points);
+	}
+
 	void ScriptGizmos::internal_DrawWireDisc(Vector3* position, Vector3* normal, float radius)
 	{
 		GizmoManager::instance().drawWireDisc(*position, *normal, radius);