예제 #1
1
	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
	{
		QUICK_SCOPE_CYCLE_COUNTER( STAT_LineBatcherSceneProxy_GetDynamicMeshElements );

		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
		{
			if (VisibilityMap & (1 << ViewIndex))
			{
				const FSceneView* View = Views[ViewIndex];
				FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);

				for (int32 i = 0; i < Lines.Num(); i++)
				{
					PDI->DrawLine(Lines[i].Start, Lines[i].End, Lines[i].Color, Lines[i].DepthPriority, Lines[i].Thickness);
				}

				for (int32 i = 0; i < Points.Num(); i++)
				{
					PDI->DrawPoint(Points[i].Position, Points[i].Color, Points[i].PointSize, Points[i].DepthPriority);
				}

				for (int32 i = 0; i < Meshes.Num(); i++)
				{
					static FVector const PosX(1.f,0,0);
					static FVector const PosY(0,1.f,0);
					static FVector const PosZ(0,0,1.f);

					FBatchedMesh const& M = Meshes[i];

					// this seems far from optimal in terms of perf, but it's for debugging
					FDynamicMeshBuilder MeshBuilder;

					// set up geometry
					for (int32 VertIdx=0; VertIdx < M.MeshVerts.Num(); ++VertIdx)
					{
						MeshBuilder.AddVertex( M.MeshVerts[VertIdx], FVector2D::ZeroVector, PosX, PosY, PosZ, FColor::White );
					}
					//MeshBuilder.AddTriangles(M.MeshIndices);
					for (int32 Idx=0; Idx < M.MeshIndices.Num(); Idx+=3)
					{
						MeshBuilder.AddTriangle( M.MeshIndices[Idx], M.MeshIndices[Idx+1], M.MeshIndices[Idx+2] );
					}

					FMaterialRenderProxy* const MaterialRenderProxy = new(FMemStack::Get()) FColoredMaterialRenderProxy(GEngine->DebugMeshMaterial->GetRenderProxy(false), M.Color);
					MeshBuilder.GetMesh(FMatrix::Identity, MaterialRenderProxy, M.DepthPriority, false, false, ViewIndex, Collector);
				}
			}
		}
	}
void FSpriteGeometryEditingHelper::DrawGeometry(const FSceneView& View, FPrimitiveDrawInterface& PDI, const FLinearColor& GeometryVertexColor, const FLinearColor& NegativeGeometryVertexColor)
{
	if (GeometryBeingEdited == nullptr)
	{
		return;
	}

	FSpriteGeometryCollection& Geometry = GetGeometryChecked();
	const bool bIsHitTesting = PDI.IsHitTesting();
	const float UnitsPerPixel = EditorContext->SelectedItemGetUnitsPerPixel();

	// Run thru the geometry shapes and draw hit proxies for them
	for (int32 ShapeIndex = 0; ShapeIndex < Geometry.Shapes.Num(); ++ShapeIndex)
	{
		const FSpriteGeometryShape& Shape = Geometry.Shapes[ShapeIndex];

		const bool bIsShapeSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, INDEX_NONE));
		const FLinearColor LineColorRaw = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor;
		const FLinearColor VertexColor = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor;

		const FLinearColor LineColor = Shape.IsShapeValid() ? LineColorRaw : FMath::Lerp(LineColorRaw, FLinearColor::Red, 0.8f);

		// Draw the interior (allowing selection of the whole shape)
		if (bIsHitTesting)
		{
			TSharedPtr<FSpriteSelectedShape> Data = MakeShareable(new FSpriteSelectedShape(EditorContext, Geometry, ShapeIndex, /*bIsBackground=*/ true));
			PDI.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data));
		}

		FColor BackgroundColor(bIsShapeSelected ? SpriteEditingConstantsEX::GeometrySelectedColor : LineColor);
		BackgroundColor.A = 4;
		FMaterialRenderProxy* ShapeMaterialProxy = WidgetVertexColorMaterial->GetRenderProxy(bIsShapeSelected);

		if (Shape.ShapeType == ESpriteShapeType::Circle)
		{
			//@TODO: This is going to have issues if we ever support ellipses
			const FVector2D PixelSpaceRadius = Shape.BoxSize * 0.5f;
			const float WorldSpaceRadius = PixelSpaceRadius.X * UnitsPerPixel;

			const FVector CircleCenterWorldPos = EditorContext->TextureSpaceToWorldSpace(Shape.BoxPosition);

			DrawDisc(&PDI, CircleCenterWorldPos, PaperAxisX, PaperAxisY, BackgroundColor, WorldSpaceRadius, SpriteEditingConstantsEX::CircleShapeNumSides, ShapeMaterialProxy, SDPG_Foreground);
		}
		else
		{
			TArray<FVector2D> SourceTextureSpaceVertices;
			Shape.GetTextureSpaceVertices(/*out*/ SourceTextureSpaceVertices);

			TArray<FVector2D> TriangulatedPolygonVertices;
			PaperGeomTools::TriangulatePoly(/*out*/ TriangulatedPolygonVertices, SourceTextureSpaceVertices, /*bKeepColinearVertices=*/ true);

			if (((TriangulatedPolygonVertices.Num() % 3) == 0) && (TriangulatedPolygonVertices.Num() > 0))
			{
				FDynamicMeshBuilder MeshBuilder;

				FDynamicMeshVertex MeshVertex;
				MeshVertex.Color = BackgroundColor;
				MeshVertex.TextureCoordinate = FVector2D::ZeroVector;
				MeshVertex.SetTangents(PaperAxisX, PaperAxisY, PaperAxisZ);

				for (const FVector2D& SrcTriangleVertex : TriangulatedPolygonVertices)
				{
					MeshVertex.Position = EditorContext->TextureSpaceToWorldSpace(SrcTriangleVertex);
					MeshBuilder.AddVertex(MeshVertex);
				}

				for (int32 TriangleIndex = 0; TriangleIndex < TriangulatedPolygonVertices.Num(); TriangleIndex += 3)
				{
					MeshBuilder.AddTriangle(TriangleIndex, TriangleIndex + 1, TriangleIndex + 2);
				}

				MeshBuilder.Draw(&PDI, FMatrix::Identity, ShapeMaterialProxy, SDPG_Foreground);
			}
		}

		if (bIsHitTesting)
		{
			PDI.SetHitProxy(nullptr);
		}
	}
}
void FPaperTileMapRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_FPaperTileMapRenderSceneProxy_GetDynamicMeshElements);
	checkSlow(IsInRenderingThread());

	// Slight depth bias so that the wireframe grid overlay doesn't z-fight with the tiles themselves
	const float DepthBias = 0.0001f;

	for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
	{
		if (VisibilityMap & (1 << ViewIndex))
		{
			const FSceneView* View = Views[ViewIndex];
			FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);

			// Draw the tile maps
			//@TODO: RenderThread race condition
			if (TileMap != nullptr)
			{
				FColor WireframeColor = FColor(0, 255, 255, 255);

				if ((View->Family->EngineShowFlags.Collision /*@TODO: && bIsCollisionEnabled*/) && AllowDebugViewmodes())
				{
					if (UBodySetup2D* BodySetup2D = Cast<UBodySetup2D>(TileMap->BodySetup))
					{
						//@TODO: Draw 2D debugging geometry
					}
					else if (UBodySetup* BodySetup = TileMap->BodySetup)
					{
						if (FMath::Abs(GetLocalToWorld().Determinant()) < SMALL_NUMBER)
						{
							// Catch this here or otherwise GeomTransform below will assert
							// This spams so commented out
							//UE_LOG(LogStaticMesh, Log, TEXT("Zero scaling not supported (%s)"), *StaticMesh->GetPathName());
						}
						else
						{
							// Make a material for drawing solid collision stuff
							const UMaterial* LevelColorationMaterial = View->Family->EngineShowFlags.Lighting
								? GEngine->ShadedLevelColorationLitMaterial : GEngine->ShadedLevelColorationUnlitMaterial;

							auto CollisionMaterialInstance = new FColoredMaterialRenderProxy(
								LevelColorationMaterial->GetRenderProxy(IsSelected(), IsHovered()),
								WireframeColor
								);

							// Draw the static mesh's body setup.

							// Get transform without scaling.
							FTransform GeomTransform(GetLocalToWorld());

							// In old wireframe collision mode, always draw the wireframe highlighted (selected or not).
							bool bDrawWireSelected = IsSelected();
							if (View->Family->EngineShowFlags.Collision)
							{
								bDrawWireSelected = true;
							}

							// Differentiate the color based on bBlockNonZeroExtent.  Helps greatly with skimming a level for optimization opportunities.
							FColor CollisionColor = FColor(157, 149, 223, 255);

							const bool bPerHullColor = false;
							const bool bDrawSimpleSolid = false;
							BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(CollisionColor, bDrawWireSelected, IsHovered()), CollisionMaterialInstance, bPerHullColor, bDrawSimpleSolid, UseEditorDepthTest(), ViewIndex, Collector);
						}
					}
				}

				// Draw the bounds
				RenderBounds(PDI, View->Family->EngineShowFlags, GetBounds(), IsSelected());

#if WITH_EDITOR
				// Draw the debug outline
				if (View->Family->EngineShowFlags.Grid)
				{
					const uint8 DPG = SDPG_Foreground;//GetDepthPriorityGroup(View);

					// Draw separation wires if selected
					FLinearColor OverrideColor;
					bool bUseOverrideColor = false;

					const bool bShowAsSelected = !(GIsEditor && View->Family->EngineShowFlags.Selection) || IsSelected();
					if (bShowAsSelected || IsHovered())
					{
						bUseOverrideColor = true;
						OverrideColor = GetSelectionColor(FLinearColor::White, bShowAsSelected, IsHovered());
					}

					FTransform LocalToWorld(GetLocalToWorld());

					if (bUseOverrideColor)
					{
						const int32 SelectedLayerIndex = TileMap->SelectedLayerIndex;

						// Draw a bound for any invisible layers
						for (int32 LayerIndex = 0; LayerIndex < TileMap->TileLayers.Num(); ++LayerIndex)
						{
							if (LayerIndex != SelectedLayerIndex)
							{
								const FVector TL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, 0, LayerIndex)));
								const FVector TR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, 0, LayerIndex)));
								const FVector BL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, TileMap->MapHeight, LayerIndex)));
								const FVector BR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, TileMap->MapHeight, LayerIndex)));

								PDI->DrawLine(TL, TR, OverrideColor, DPG, 0.0f, DepthBias);
								PDI->DrawLine(TR, BR, OverrideColor, DPG, 0.0f, DepthBias);
								PDI->DrawLine(BR, BL, OverrideColor, DPG, 0.0f, DepthBias);
								PDI->DrawLine(BL, TL, OverrideColor, DPG, 0.0f, DepthBias);
							}
						}

						if (SelectedLayerIndex != INDEX_NONE)
						{
							// Draw horizontal lines on the selection
							for (int32 Y = 0; Y <= TileMap->MapHeight; ++Y)
							{
								int32 X = 0;
								const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex));

								X = TileMap->MapWidth;
								const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex));

								PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias);
							}

							// Draw vertical lines
							for (int32 X = 0; X <= TileMap->MapWidth; ++X)
							{
								int32 Y = 0;
								const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex));

								Y = TileMap->MapHeight;
								const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex));

								PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias);
							}
						}
					}
				}
#endif
			}
		}
	}

	// Draw all of the queued up sprites
	FPaperRenderSceneProxy::GetDynamicMeshElements(Views, ViewFamily, VisibilityMap, Collector);
}
	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
	{
		QUICK_SCOPE_CYCLE_COUNTER( STAT_DrawFrustumSceneProxy_DrawDynamicElements );

		FVector Direction(1,0,0);
		FVector LeftVector(0,1,0);
		FVector UpVector(0,0,1);

		FVector Verts[8];

		// FOVAngle controls the horizontal angle.
		const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f);

		float HozLength = 0.0f;
		float VertLength = 0.0f;
		
		if (FrustumAngle > 0.0f)
		{
			HozLength = FrustumStartDist * FMath::Tan(HozHalfAngleInRadians);
			VertLength = HozLength / FrustumAspectRatio;
		}
		else
		{
			const float OrthoWidth = (FrustumAngle == 0.0f) ? 1000.0f : -FrustumAngle;
			HozLength = OrthoWidth * 0.5f;
			VertLength = HozLength / FrustumAspectRatio;
		}

		// near plane verts
		Verts[0] = (Direction * FrustumStartDist) + (UpVector * VertLength) + (LeftVector * HozLength);
		Verts[1] = (Direction * FrustumStartDist) + (UpVector * VertLength) - (LeftVector * HozLength);
		Verts[2] = (Direction * FrustumStartDist) - (UpVector * VertLength) - (LeftVector * HozLength);
		Verts[3] = (Direction * FrustumStartDist) - (UpVector * VertLength) + (LeftVector * HozLength);

		if (FrustumAngle > 0.0f)
		{
			HozLength = FrustumEndDist * FMath::Tan(HozHalfAngleInRadians);
			VertLength = HozLength / FrustumAspectRatio;
		}

		// far plane verts
		Verts[4] = (Direction * FrustumEndDist) + (UpVector * VertLength) + (LeftVector * HozLength);
		Verts[5] = (Direction * FrustumEndDist) + (UpVector * VertLength) - (LeftVector * HozLength);
		Verts[6] = (Direction * FrustumEndDist) - (UpVector * VertLength) - (LeftVector * HozLength);
		Verts[7] = (Direction * FrustumEndDist) - (UpVector * VertLength) + (LeftVector * HozLength);

		for (int32 X = 0; X < 8; ++X)
		{
			Verts[X] = GetLocalToWorld().TransformPosition(Verts[X]);
		}

		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
		{
			if (VisibilityMap & (1 << ViewIndex))
			{
				FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
				const FSceneView* View = Views[ViewIndex];

				const uint8 DepthPriorityGroup = GetDepthPriorityGroup(View);
				PDI->DrawLine( Verts[0], Verts[1], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[1], Verts[2], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[2], Verts[3], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[3], Verts[0], FrustumColor, DepthPriorityGroup );

				PDI->DrawLine( Verts[4], Verts[5], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[5], Verts[6], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[6], Verts[7], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[7], Verts[4], FrustumColor, DepthPriorityGroup );

				PDI->DrawLine( Verts[0], Verts[4], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[1], Verts[5], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[2], Verts[6], FrustumColor, DepthPriorityGroup );
				PDI->DrawLine( Verts[3], Verts[7], FrustumColor, DepthPriorityGroup );
			}
		}
	}
void FDebugRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const 
{
	QUICK_SCOPE_CYCLE_COUNTER( STAT_DebugRenderSceneProxy_GetDynamicMeshElements );

	// Draw solid spheres
	struct FMaterialCache
	{
		FMaterialCache() : bUseFakeLight(false) {}

		FMaterialRenderProxy* operator[](FLinearColor Color)
		{
			FMaterialRenderProxy* MeshColor = NULL;
			const uint32 HashKey = GetTypeHash(Color);
			if (MeshColorInstances.Contains(HashKey))
			{
				MeshColor = *MeshColorInstances.Find(HashKey);
			}
			else
			{
				if (bUseFakeLight && SolidMeshMaterial.IsValid())
				{
					
					MeshColor = new(FMemStack::Get())  FColoredMaterialRenderProxy(
						SolidMeshMaterial->GetRenderProxy(false, false),
						Color,
						"GizmoColor"
						);
				}
				else
				{
					MeshColor = new(FMemStack::Get()) FColoredMaterialRenderProxy(GEngine->DebugMeshMaterial->GetRenderProxy(false, false), Color);
				}

				MeshColorInstances.Add(HashKey, MeshColor);
			}

			return MeshColor;
		}

		void UseFakeLight(bool UseLight, class UMaterial* InMaterial) { bUseFakeLight = UseLight; SolidMeshMaterial = InMaterial; }

		TMap<uint32, FMaterialRenderProxy*> MeshColorInstances;
		TWeakObjectPtr<class UMaterial> SolidMeshMaterial;
		bool bUseFakeLight;
	};

	FMaterialCache MaterialCache[2];
	MaterialCache[1].UseFakeLight(true, SolidMeshMaterial.Get());

	for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
	{
		if (VisibilityMap & (1 << ViewIndex))
		{
			const FSceneView* View = Views[ViewIndex];
			FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);

			// Draw Lines
			const int32 LinesNum = Lines.Num();
			PDI->AddReserveLines(SDPG_World, LinesNum, false, false);
			for (const auto& CurrentLine : Lines)
			{
				PDI->DrawLine(CurrentLine.Start, CurrentLine.End, CurrentLine.Color, SDPG_World, CurrentLine.Thickness, 0, CurrentLine.Thickness > 0);
			}

			// Draw Dashed Lines
			for(int32 DashIdx=0; DashIdx<DashedLines.Num(); DashIdx++)
			{
				const FDashedLine& Dash = DashedLines[DashIdx];

				DrawDashedLine(PDI, Dash.Start, Dash.End, Dash.Color, Dash.DashSize, SDPG_World);
			}

			// Draw Arrows
			const uint32 ArrowsNum = ArrowLines.Num();
			PDI->AddReserveLines(SDPG_World, 5 * ArrowsNum, false, false);
			for (const auto& CurrentArrow : ArrowLines)
			{
				DrawLineArrow(PDI, CurrentArrow.Start, CurrentArrow.End, CurrentArrow.Color, 8.0f);
			}

			// Draw Stars
			for(int32 StarIdx=0; StarIdx<Stars.Num(); StarIdx++)
			{
				const FWireStar& Star = Stars[StarIdx];

				DrawWireStar(PDI, Star.Position, Star.Size, Star.Color, SDPG_World);
			}

			// Draw Cylinders
			for(const auto& Cylinder : Cylinders)
			{
				if (DrawType == SolidAndWireMeshes || DrawType == WireMesh)
				{
					DrawWireCylinder(PDI, Cylinder.Base, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Cylinder.Color, Cylinder.Radius, Cylinder.HalfHeight, (DrawType == SolidAndWireMeshes) ? 9 : 16, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true);
				}

				if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh)
				{
					GetCylinderMesh(Cylinder.Base, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Cylinder.Radius, Cylinder.HalfHeight, 16, MaterialCache[0][Cylinder.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector);
				}
			}

			// Draw Boxes
			for(const auto& Box :  Boxes)
			{
				if (DrawType == SolidAndWireMeshes || DrawType == WireMesh)
				{
					DrawWireBox(PDI, Box.Transform.ToMatrixWithScale(), Box.Box, Box.Color, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true);
				}
				if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh)
				{
					GetBoxMesh(FTransform(Box.Box.GetCenter()).ToMatrixNoScale() * Box.Transform.ToMatrixWithScale(), Box.Box.GetExtent(), MaterialCache[0][Box.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector);
				}
			}

			// Draw Boxes
			TArray<FVector> Verts;
			for (auto& CurrentCone : Cones)
			{
				if (DrawType == SolidAndWireMeshes || DrawType == WireMesh)
				{
					DrawWireCone(PDI, Verts, CurrentCone.ConeToWorld, 1, CurrentCone.Angle2, (DrawType == SolidAndWireMeshes) ? 9 : 16, CurrentCone.Color, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true);
				}
				if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh)
				{
					GetConeMesh(CurrentCone.ConeToWorld, CurrentCone.Angle1, CurrentCone.Angle2, 16, MaterialCache[0][CurrentCone.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector);
				}
			}

			for (auto It = Spheres.CreateConstIterator(); It; ++It)
			{
				if (PointInView(It->Location, View))
				{
					if (DrawType == SolidAndWireMeshes || DrawType == WireMesh)
					{
						DrawWireSphere(PDI, It->Location, It->Color.WithAlpha(255), It->Radius, 20, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true);
					}
					if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh)
					{
						GetSphereMesh(It->Location, FVector(It->Radius), 20, 7, MaterialCache[0][It->Color.WithAlpha(DrawAlpha)], SDPG_World, false, ViewIndex, Collector);
					}
				}
			}

			for (auto It = Capsles.CreateConstIterator(); It; ++It)
			{
				if (PointInView(It->Location, View))
				{
					if (DrawType == SolidAndWireMeshes || DrawType == WireMesh)
					{
						const float HalfAxis = FMath::Max<float>(It->HalfHeight - It->Radius, 1.f);
						const FVector BottomEnd = It->Location + It->Radius * It->Z;
						const FVector TopEnd = BottomEnd + (2 * HalfAxis) * It->Z;
						const float CylinderHalfHeight = (TopEnd - BottomEnd).Size() * 0.5;
						const FVector CylinderLocation = BottomEnd + CylinderHalfHeight * It->Z;
						DrawWireCapsule(PDI, CylinderLocation, It->X, It->Y, It->Z, It->Color, It->Radius, It->HalfHeight, (DrawType == SolidAndWireMeshes) ? 9 : 16, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true);
					}
					if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh)
					{
						GetCapsuleMesh(It->Location, It->X, It->Y, It->Z, It->Color, It->Radius, It->HalfHeight, 16, MaterialCache[0][It->Color.WithAlpha(DrawAlpha)], SDPG_World, false, ViewIndex, Collector);
					}
				}
			}

			for (const auto& Mesh : Meshes)
			{
				FDynamicMeshBuilder MeshBuilder;
				MeshBuilder.AddVertices(Mesh.Vertices);
				MeshBuilder.AddTriangles(Mesh.Indices);

				MeshBuilder.GetMesh(FMatrix::Identity, MaterialCache[Mesh.Color.A == 255 ? 1 : 0][Mesh.Color.WithAlpha(DrawAlpha)], SDPG_World, false, false, ViewIndex, Collector);
			}

		}
	}
}