// Copyright Epic Games, Inc. All Rights Reserved. #include "Drawing/MeshDebugDrawing.h" #include "DynamicMesh/DynamicMesh3.h" #include "FrameTypes.h" #include "ToolSceneQueriesUtil.h" #include "MathUtil.h" #include "SceneManagement.h" // FPrimitiveDrawInterface using namespace UE::Geometry; void MeshDebugDraw::DrawNormals( const FDynamicMeshNormalOverlay* Overlay, float Length, FColor Color, float Thickness, bool bScreenSpace, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { const FDynamicMesh3* Mesh = Overlay->GetParentMesh(); for (int ElementID : Overlay->ElementIndicesItr()) { FVector3f Normal = Overlay->GetElement(ElementID); int ParentVID = Overlay->GetParentVertex(ElementID); FVector3f ParentPos = (FVector3f)Mesh->GetVertex(ParentVID); FVector A = (FVector)ParentPos, B = (FVector)(ParentPos + Length * Normal); PDI->DrawLine(Transform.TransformPosition(A), Transform.TransformPosition(B), Color, 0, Thickness, 0, bScreenSpace); } } void MeshDebugDraw::DrawVertices( const FDynamicMesh3* Mesh, const TArray& Indices, float PointSize, FColor Color, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { for (int VertID : Indices) { FVector3d Pos = Mesh->GetVertex(VertID); PDI->DrawPoint(Transform.TransformPosition((FVector)Pos), Color, PointSize, SDPG_World); } } void MeshDebugDraw::DrawVertices( const FDynamicMesh3* Mesh, const TSet& Indices, float PointSize, FColor Color, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { for (int VertID : Indices) { FVector3d Pos = Mesh->GetVertex(VertID); PDI->DrawPoint(Transform.TransformPosition((FVector)Pos), Color, PointSize, SDPG_World); } } void MeshDebugDraw::DrawTriCentroids( const FDynamicMesh3* Mesh, const TArray& Indices, float PointSize, FColor Color, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { for (int TriID : Indices) { FVector3d Pos = Mesh->GetTriCentroid(TriID); PDI->DrawPoint(Transform.TransformPosition((FVector)Pos), Color, PointSize, SDPG_World); } } void MeshDebugDraw::DrawSimpleGrid( const FFrame3f& LocalFrame, int GridLines, float GridLineSpacing, float LineWidth, FColor Color, bool bDepthTested, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { ESceneDepthPriorityGroup DepthPriority = (bDepthTested) ? SDPG_World : SDPG_Foreground; FFrame3f WorldFrame = LocalFrame; WorldFrame.Transform(Transform); float Width = (float)(GridLines-1) * GridLineSpacing; float Extent = Width * 0.5; FVector3f Origin = WorldFrame.Origin; FVector3f X = WorldFrame.X(); FVector3f Y = WorldFrame.Y(); FVector3f A, B; int LineSteps = GridLines / 2; for (int i = 0; i < LineSteps; i++) { float dx = (float)i * GridLineSpacing; A = Origin - Extent * Y - dx * X; B = Origin + Extent * Y - dx * X; PDI->DrawLine((FVector)A, (FVector)B, Color, DepthPriority, LineWidth, 0, true); A = Origin - Extent * Y + dx * X; B = Origin + Extent * Y + dx * X; PDI->DrawLine((FVector)A, (FVector)B, Color, DepthPriority, LineWidth, 0, true); A = Origin - Extent * X - dx * Y; B = Origin + Extent * X - dx * Y; PDI->DrawLine((FVector)A, (FVector)B, Color, DepthPriority, LineWidth, 0, true); A = Origin - Extent * X + dx * Y; B = Origin + Extent * X + dx * Y; PDI->DrawLine((FVector)A, (FVector)B, Color, DepthPriority, LineWidth, 0, true); } } void MeshDebugDraw::DrawSimpleFixedScreenAreaGrid( const FViewCameraState& CameraState, const FFrame3f& LocalFrame, int32 NumGridLines, float VisualAngleSpan, float LineWidth, FColor Color, bool bDepthTested, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { FVector WorldOrigin = Transform.TransformPosition((FVector)LocalFrame.Origin); float GridWidth = ToolSceneQueriesUtil::CalculateDimensionFromVisualAngleD(CameraState, (FVector3d)WorldOrigin, VisualAngleSpan); float GridLineSpacing = GridWidth / (float)NumGridLines; DrawSimpleGrid(LocalFrame, NumGridLines, GridLineSpacing, LineWidth, Color, bDepthTested, PDI, Transform); } void MeshDebugDraw::DrawHierarchicalGrid( float BaseScale, float GridZoomFactor, int32 MaxLevelDensity, const FVector& WorldMaxBounds, const FVector& WorldMinBounds, int32 Levels, int32 Subdivisions, TArray& Colors, const FFrame3f& LocalFrame, float LineWidth, bool bDepthTested, FPrimitiveDrawInterface* PDI, const FTransform& Transform) { // Determine the logrithmic scaling factor based on linear zoom factor. // This allows us to track and discretely shift grid resolutions at certain zoom levels. // This code assumes that we want the grid to remain stable with one logrithmic "unit" // around the base zoom factor of 1.0 float LogZoom = FMath::LogX(Subdivisions, GridZoomFactor ); float LogZoomDirection = FMath::Sign(LogZoom); LogZoom = FMath::Abs(LogZoom); LogZoom = FMathf::Floor(LogZoom); LogZoom = LogZoomDirection * LogZoom; // Adjust grid scales based on current zoom levels TArray GridScales; GridScales.SetNum(Levels); for (int32 Level = 0; Level < Levels; ++Level) { GridScales[Level] = BaseScale * FMathf::Pow(Subdivisions, LogZoom - Level); ensure(!FMath::IsNearlyZero(GridScales[Level])); } //Determine the center of the drawing area for the grid, snapping to grid positions FVector3f GridOrigin( FMath::GridSnap(LocalFrame.Origin.X, GridScales[0]), FMath::GridSnap(LocalFrame.Origin.Y, GridScales[0]), LocalFrame.Origin.Z); UE::Geometry::FFrame3f GridFrame(GridOrigin); // Draw each level of the grid for (int32 Level = 0; Level < Levels; ++Level) { // We automatically adjust down each level's thickness by half each time float AdjustedLineWidth = LineWidth * FMathf::Pow(2, -Level); // Compute the number of needed grid lines based on the coarsest grid's scale, this way we never "run out" of lines as we pan about int32 GridLines = FMathf::Ceil(FMathf::Max(((WorldMaxBounds.X - WorldMinBounds.X + GridScales[0]*2) / GridScales[Level]), ((WorldMaxBounds.Y - WorldMinBounds.Y + GridScales[0]*2) / GridScales[Level]))); // If we ever have too many lines to draw, just bail. This preserves performance for large, deep grids. if (GridLines > MaxLevelDensity) { break; } // Select our color, using the last grid color over again if we don't have enough. FColor GridColor = Colors.Num() - 1 > Level ? Colors[Level] : Colors.Last(); // Finally draw one grid level. MeshDebugDraw::DrawSimpleGrid(GridFrame, GridLines, GridScales[Level], AdjustedLineWidth, GridColor, bDepthTested, PDI, Transform); } }