Exemplo n.º 1
0
        public static CSGPlane TransformPlane(Matrix4x4 matrix, CSGPlane plane)
        {
            var dstMatrix = Matrix4x4.Transpose(Matrix4x4.Inverse(matrix));
            var dstPlaneV = dstMatrix * new Vector4(plane.a, plane.b, plane.c, -plane.d);

            return(new CSGPlane(dstPlaneV.x, dstPlaneV.y, dstPlaneV.z, -dstPlaneV.w));
        }
Exemplo n.º 2
0
 public void ProjectShapeOnBuildPlane(CSGPlane plane)
 {
     for (int i = 0; i < vertices.Length; i++)
     {
         vertices[i] = plane.Project(vertices[i]);
     }
 }
Exemplo n.º 3
0
        public static bool SetupRayWorkPlane(Vector3 worldOrigin, Vector3 worldDirection, ref CSGPlane outWorkPlane)
        {
            var camera = Camera.current;

            if (camera == null || !camera)
            {
                return(false);
            }

            Vector3 tangent, normal;
            var     cameraBackwards      = -camera.transform.forward;
            var     closestAxisForward   = GeometryUtility.SnapToClosestAxis(cameraBackwards);
            var     closestAxisDirection = GeometryUtility.SnapToClosestAxis(worldDirection);

            if (Vector3.Dot(closestAxisForward, closestAxisDirection) != 0)
            {
                float dot1 = Mathf.Abs(Vector3.Dot(cameraBackwards, MathConstants.rightVector3));
                float dot2 = Mathf.Abs(Vector3.Dot(cameraBackwards, MathConstants.upVector3));
                float dot3 = Mathf.Abs(Vector3.Dot(cameraBackwards, MathConstants.forwardVector3));
                if (dot1 < dot2)
                {
                    if (dot1 < dot3)
                    {
                        tangent = MathConstants.rightVector3;
                    }
                    else
                    {
                        tangent = MathConstants.forwardVector3;
                    }
                }
                else
                {
                    if (dot2 < dot3)
                    {
                        tangent = MathConstants.upVector3;
                    }
                    else
                    {
                        tangent = MathConstants.forwardVector3;
                    }
                }
            }
            else
            {
                tangent = Vector3.Cross(worldDirection, closestAxisForward);
            }

            if (!camera.orthographic)
            {
                normal = Vector3.Cross(worldDirection, tangent);
            }
            else
            {
                normal = cameraBackwards;
            }

            outWorkPlane = new CSGPlane(GridUtility.CleanNormal(normal), worldOrigin);

            return(CSGGrid.SetForcedGrid(outWorkPlane));
        }
Exemplo n.º 4
0
		protected virtual bool StartEditMode(Camera camera)
		{
			if (editMode == EditMode.EditShape ||
				editMode == EditMode.ExtrudeShape)
			{
				return false;
			}

			Undo.RecordObject(this, "Created shape");
			if (GUIUtility.hotControl == shapeId)
			{
				GUIUtility.hotControl = 0;
				GUIUtility.keyboardControl = 0;
				EditorGUIUtility.SetWantsMouseJumping(0);
				EditorGUIUtility.editingTextField = false;
			}
			
			CalculateWorldSpaceTangents(camera);
			brushPosition = buildPlane.Project(ShapeSettings.GetCenter(buildPlane));
			editMode = EditMode.EditShape;

			CSGPlane newPlane = buildPlane;
			ShapeSettings.CalculatePlane(ref newPlane);
			if (newPlane.normal.sqrMagnitude != 0)
				buildPlane = newPlane;

            if (ModelTraits.IsModelEditable(geometryModel))
                SelectionUtility.LastUsedModel = geometryModel;

			UpdateBaseShape();

			//StartExtrudeMode();
			//GrabHeightHandle(ignoreFirstMouseUp: true);
			return true;
		}
Exemplo n.º 5
0
        public static bool SetupWorkPlane(Camera camera, Vector3 worldCenterPoint, Vector3 worldDirection, ref CSGPlane workPlane)
        {
            if (camera == null || !camera)
            {
                return(false);
            }

            if (camera.orthographic)
            {
                CSGGrid.ForceGrid = false;
                workPlane         = CSGGrid.CurrentWorkGridPlane;
                return(true);
            }

            var normal = worldDirection;

            /*
             * if (YMoveModeActive)
             * {
             *      var forward = camera.transform.forward;
             *      Vector3 tangent, binormal;
             *      GeometryUtility.CalculateTangents(normal, out tangent, out binormal);
             *      if (Mathf.Abs(Vector3.Dot(forward, tangent)) > Mathf.Abs(Vector3.Dot(forward, binormal)))
             *              normal = tangent;
             *      else
             *              normal = binormal;
             * }*/

            workPlane = new CSGPlane(GridUtility.CleanNormal(normal), worldCenterPoint);
            return(CSGGrid.SetForcedGrid(camera, workPlane));
        }
        public static Vector3 SnapPointToGrid(Vector3 point, CSGPlane plane, ref List <Vector3> snappingEdges, out CSGBrush snappedOnBrush, CSGBrush[] ignoreBrushes, bool ignoreAllBrushes = false)
        {
            snappedOnBrush = null;
            var toggleSnapping = SelectionUtility.IsSnappingToggled;
            var doSnapping     = RealtimeCSG.CSGSettings.SnapToGrid ^ toggleSnapping;

            var snappedPoint = point;

            if (doSnapping)
            {
                snappedPoint = snappedPoint + RealtimeCSG.Grid.ForceSnapDeltaToGrid(MathConstants.zeroVector3, snappedPoint);
                snappedPoint = RealtimeCSG.Grid.PointFromGridSpace(RealtimeCSG.Grid.CubeProject(RealtimeCSG.Grid.PlaneToGridSpace(plane), RealtimeCSG.Grid.PointToGridSpace(snappedPoint)));

                // snap twice to get rid of some tiny movements caused by the projection in depth
                snappedPoint = snappedPoint + RealtimeCSG.Grid.ForceSnapDeltaToGrid(MathConstants.zeroVector3, snappedPoint);
                snappedPoint = RealtimeCSG.Grid.PointFromGridSpace(RealtimeCSG.Grid.CubeProject(RealtimeCSG.Grid.PlaneToGridSpace(plane), RealtimeCSG.Grid.PointToGridSpace(snappedPoint)));
            }
            else
            {
                snappedPoint = GeometryUtility.ProjectPointOnPlane(plane, snappedPoint);
            }

            //GeometryUtility.ProjectPointOnPlane(plane, snappedPoint);
            if (doSnapping && !ignoreAllBrushes)
            {
                return(GridUtility.SnapToWorld(plane, point, snappedPoint, ref snappingEdges, out snappedOnBrush, ignoreBrushes));
            }

            return(snappedPoint);
        }
Exemplo n.º 7
0
        public static bool IntersectsWithShapePolygon(ShapePolygon shapePolygon, CSGPlane polygonPlane, Ray ray)
        {
            var intersection = polygonPlane.Intersection(ray);
            var vertices     = shapePolygon.Vertices;

            for (int v0 = vertices.Length - 1, v1 = 0; v1 < vertices.Length; v0 = v1, v1++)
            {
                var vertex0 = vertices[v0];
                var vertex1 = vertices[v1];
                var delta   = (vertex1 - vertex0);
                var length  = delta.sqrMagnitude;
                if (length <= MathConstants.EqualityEpsilonSqr)
                {
                    continue;
                }

                var tangent = delta / Mathf.Sqrt(length);
                var normal  = Vector3.Cross(polygonPlane.normal, tangent);
                var plane   = new CSGPlane(normal, vertex0);
                if (plane.Distance(intersection) < MathConstants.DistanceEpsilon)
                {
                    return(false);
                }
            }
            return(true);
        }
Exemplo n.º 8
0
        public static bool SetForcedGrid(Camera camera, CSGPlane plane)
        {
            if (float.IsNaN(plane.a) || float.IsInfinity(plane.a) ||
                float.IsNaN(plane.b) || float.IsInfinity(plane.b) ||
                float.IsNaN(plane.c) || float.IsInfinity(plane.c) ||
                float.IsNaN(plane.d) || float.IsInfinity(plane.d) ||
                plane.normal.sqrMagnitude < MathConstants.NormalEpsilon)
            {
                Debug.LogWarning("Invalid plane passed to SetForcedGrid");
                return(false);
            }

            // cube-project the center of the grid so that it lies on the plane

            UpdateGridOrientation(camera);
            var center = CubeProject(camera, plane, gridOrientation.gridCenter);

            var normal = Quaternion.Inverse(gridOrientation.gridRotation) * plane.normal;

            if (normal.sqrMagnitude < MathConstants.NormalEpsilon)
            {
                return(false);
            }
            var        tangent = Vector3.Cross(normal, Vector3.Cross(normal, GeometryUtility.CalculateTangent(normal)).normalized).normalized;
            Quaternion q       = gridOrientation.gridRotation * Quaternion.LookRotation(tangent, normal);

            CSGGrid.ForceGrid          = true;
            CSGGrid.ForcedGridCenter   = center;
            CSGGrid.ForcedGridRotation = q;
            return(true);
        }
Exemplo n.º 9
0
        public static List <ShapePolygon> CreateCleanPolygonsFromVertices(Vector3[]       vertices,
                                                                          Vector3 origin,
                                                                          CSGPlane buildPlane,
                                                                          out Vector3[] projectedVertices)
        {
            if (vertices.Length < 3)
            {
                projectedVertices = null;
                return(null);
            }
            var m          = Matrix4x4.TRS(-origin, Quaternion.identity, Vector3.one);
            var vertices2d = GeometryUtility.RotatePlaneTo2D(m, vertices, buildPlane);

            /*
             * for (int i0 = vertices2d.Length - 1, i1 = 0; i1 < vertices2d.Length; i1++)
             * {
             *      reset_loop:;
             *      var vertex_i0 = vertices2d[i0];
             *      var vertex_i1 = vertices2d[i1];
             *      for (int j0 = i1 + 1, j1 = i1 + 2; j1 < vertices2d.Length; j1++)
             *      {
             *              if ((i1 == j0 && j1 == i0) ||
             *                      i0 == j0)
             *                      continue;
             *
             *              var vertex_j0 = vertices2d[j0];
             *              var vertex_j1 = vertices2d[j1];
             *              if (i1 == j0)
             *              {
             *
             *              } else
             *              if (j1 == i0)
             *              {
             *
             *              } else
             *              {
             *                      if (!GeometryUtility.Intersects(vertex_i0, vertex_i1, vertex_j0, vertex_j1))
             *                              continue;
             *
             *                      Vector2 intersection;
             *                      if (!GeometryUtility.TryIntersection(vertex_i0, vertex_i1, vertex_j0, vertex_j1, out intersection))
             *                              continue;
             *
             *                      if (i1 > j1)
             *                      {
             *                              ArrayUtility.Insert(ref vertices2d, i1, intersection);
             *                              ArrayUtility.Insert(ref vertices2d, j1, intersection);
             *                      } else
             *                      {
             *                              ArrayUtility.Insert(ref vertices2d, j1, intersection);
             *                              ArrayUtility.Insert(ref vertices2d, i1, intersection);
             *                      }
             *                      goto reset_loop;
             *              }
             *      }
             * }
             */
            projectedVertices = GeometryUtility.ToVector3XZ(vertices2d);
            return(CreateCleanSubPolygonsFromVertices(vertices2d, buildPlane));
        }
Exemplo n.º 10
0
        public Vector3 GetCenter(CSGPlane plane)
        {
            var vertices2d = GeometryUtility.RotatePlaneTo2D(curve.Points, plane);
            var centroid2d = Centroid(vertices2d);

            return(plane.Project(GeometryUtility.Rotate2DToPlane(new Vector2[] { centroid2d }, plane)[0]));
        }
Exemplo n.º 11
0
		void CreateSnappedPlanes()
		{
			firstSnappedPlanes = new CSGPlane[firstSnappedEdges.Length / 2];

			for (int i = 0; i < firstSnappedEdges.Length; i += 2)
			{
				var point0 = firstSnappedEdges[i + 0];
				var point1 = firstSnappedEdges[i + 1];

				var binormal = (point1 - point0).normalized;
				var tangent  = buildPlane.normal;
				var normal	 = Vector3.Cross(binormal, tangent);

				var worldPlane	= new CSGPlane(normal, point0);
				// note, we use 'inverse' of the worldToLocalMatrix because to transform a plane we'd need to do an inverse, 
				// and using the already inversed matrix we don't need to do a costly inverse.
				var localPlane		= GeometryUtility.InverseTransformPlane(firstSnappedBrush.transform.localToWorldMatrix, worldPlane);
				var	vertices		= firstSnappedBrush.ControlMesh.Vertices;
				var planeIsInversed	= false;
				for (int v = 0; v < vertices.Length; v++)
				{
					if (localPlane.Distance(vertices[v]) > MathConstants.DistanceEpsilon)
					{
						planeIsInversed = true;
						break;
					}
				}
				if (planeIsInversed)
					firstSnappedPlanes[i / 2] = worldPlane.Negated();
				else
					firstSnappedPlanes[i / 2] = worldPlane;
			}
		}
Exemplo n.º 12
0
        public static Vector3 Rotate2DToPlane(Vector2 point2D, CSGPlane plane)
        {
            var mat   = Rotate2DToPlaneMatrix(plane);
            var input = new Vector3(point2D.x, 0, point2D.y);
            var point = mat.MultiplyPoint(input);

            return(ProjectPointOnPlane(plane, point));
        }
        public static void GenerateFromSurface(CSGBrush cSGBrush, CSGPlane polygonPlane, Vector3 direction, Vector3[] points, int[] pointIndices, uint[] smoothingGroups, bool drag)
        {
            CSGBrushEditorManager.EditMode = ToolEditMode.Generate;
            UpdateTool();
            var generateBrushTool = brushTools[(int)ToolEditMode.Generate] as GenerateBrushTool;

            generateBrushTool.GenerateFromPolygon(cSGBrush, polygonPlane, direction, points, pointIndices, smoothingGroups, drag);
        }
    public CSGPolygon(List <CSGVertex> vertices, CSGShared shared)
    {
        this.vertices = vertices;

        this.shared = shared;

        this.plane = CSGPlane.fromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
    }
Exemplo n.º 15
0
        public static Quaternion GetOrientationForPlane(CSGPlane plane)
        {
            var        normal  = plane.normal;
            var        tangent = Vector3.Cross(normal, Vector3.Cross(normal, CalculateTangent(normal)).normalized).normalized;
            Quaternion q       = Quaternion.LookRotation(tangent, normal);

            return(q);
        }
    public CSGPolygon(CSGVertex[] verticesArray, CSGShared shared)
    {
        this.vertices = new List <CSGVertex>(verticesArray);

        this.shared = shared;

        this.plane = CSGPlane.fromPoints(vertices[0].pos, vertices[1].pos, vertices[2].pos);
    }
Exemplo n.º 17
0
        public static void GenerateFromSurface(CSGBrush cSGBrush, CSGPlane polygonPlane, Vector3 direction, Vector3[] points, int[] pointIndices, uint[] smoothingGroups, bool drag, CSGOperationType forceDragSource, bool autoCommitExtrusion)
        {
            EditModeManager.EditMode = ToolEditMode.Generate;
            UpdateTool();
            var generateBrushTool = brushTools[(int)ToolEditMode.Generate] as EditModeGenerate;

            generateBrushTool.GenerateFromPolygon(cSGBrush, polygonPlane, direction, points, pointIndices, smoothingGroups, drag, forceDragSource, autoCommitExtrusion);
        }
Exemplo n.º 18
0
 private static extern bool RayCastIntoBrush(Int32 brushID,
                                             Int32 texGenID,
                                             [In] ref Vector3 rayStart,
                                             [In] ref Vector3 rayEnd,
                                             out Int32 surfaceIndex,
                                             out Vector2 surfaceIntersection,
                                             out Vector3 worldIntersection,
                                             out bool surfaceInverted,
                                             out CSGPlane plane);
        Vector3 GetHeightHandlePosition(SceneView sceneView, Vector3 point)
        {
            var mouseRay      = HandleUtility.GUIPointToWorldRay(heightPosition);
            var alignedPlane  = new CSGPlane(sceneView.camera.transform.forward, point);
            var planePosition = alignedPlane.RayIntersection(mouseRay);                  // buildPlane.Project() - grabOffset;
            var worldPosition = GeometryUtility.ProjectPointOnInfiniteLine(planePosition, brushPosition, movePolygonDirection);

            return(worldPosition);
        }
Exemplo n.º 20
0
 public static List <ShapePolygon> CreateCleanPolygonsFromVertices(Vector3[]  vertices,
                                                                   Vector3 origin,
                                                                   CSGPlane buildPlane)
 {
     Vector3[] projectedVertices;
     return(CreateCleanPolygonsFromVertices(vertices,
                                            origin,
                                            buildPlane,
                                            out projectedVertices));
 }
Exemplo n.º 21
0
        public void SetPointConstaintSide(CSGPlane buildPlane, int pointIndex, int side, HandleConstraints state)
        {
            if (curveTangentHandles[(pointIndex * 2) + side].Constraint == state)
            {
                return;
            }

            curveTangentHandles[(pointIndex * 2) + side].Constraint = state;
            if (state != HandleConstraints.Straight &&
                curveTangentHandles[(pointIndex * 2) + (1 - side)].Constraint != HandleConstraints.Straight)
            {
                if (state == HandleConstraints.Broken &&
                    curveTangentHandles[(pointIndex * 2) + (1 - side)].Constraint == HandleConstraints.Mirrored)
                {
                    curveTangentHandles[(pointIndex * 2) + (1 - side)].Constraint = HandleConstraints.Broken;
                }

                curvePointHandles[pointIndex].Tangent           = true;
                curve.Tangents[(pointIndex * 2) + side].Tangent = -curve.Tangents[(pointIndex * 2) + (1 - side)].Tangent;
                return;
            }

            switch (state)
            {
            case HandleConstraints.Broken:
            case HandleConstraints.Mirrored:
            {
                if (curvePointHandles[pointIndex].Tangent)
                {
                    break;
                }
                var count   = curve.Points.Length;
                var prev    = (pointIndex + count - 1) % count;
                var curr    = pointIndex;
                var next    = (pointIndex + count + 1) % count;
                var vertex0 = curve.Points[prev];
                var vertex1 = curve.Points[curr];
                var vertex2 = curve.Points[next];

                var centerA = (vertex0 + vertex1 + vertex2) / 3;

                var deltaA = (centerA - vertex1);

                var tangentA = Vector3.Cross(buildPlane.normal, deltaA);
                if (side == 0)
                {
                    tangentA = -tangentA;
                }

                curvePointHandles[pointIndex].Tangent           = true;
                curve.Tangents[(pointIndex * 2) + side].Tangent = tangentA;
                break;
            }
            }
        }
        static float GetSegmentLength(Vector3 point1, Vector3 point2, Vector3 direction)
        {
            var height   = (point1 - point2).magnitude;
            var distance = new CSGPlane(direction, point1).Distance(point2);

            if (float.IsInfinity(distance) || float.IsNaN(distance))
            {
                distance = 1.0f;
            }
            height *= Mathf.Sign(distance);
            return(GeometryUtility.CleanLength(height));
        }
Exemplo n.º 23
0
        public static Vector3[] Rotate2DToPlane(Vector2[] points2D, CSGPlane plane)
        {
            var mat    = Rotate2DToPlaneMatrix(plane);
            var points = new Vector3[points2D.Length];

            for (var i = 0; i < points2D.Length; i++)
            {
                var input = new Vector3(points2D[i].x, 0, points2D[i].y);
                var point = mat.MultiplyPoint(input);
                points[i] = ProjectPointOnPlane(plane, point);
            }
            return(points);
        }
Exemplo n.º 24
0
        public static Vector2[] RotatePlaneTo2D(Vector3[] points, CSGPlane plane)
        {
            var mat = RotatePlaneTo2DMatrix(plane);

            var points2D = new Vector2[points.Length];

            for (var i = 0; i < points2D.Length; i++)
            {
                var point = mat.MultiplyPoint(points[i]);
                points2D[i].x = point.x;
                points2D[i].y = point.z;
            }
            return(points2D);
        }
Exemplo n.º 25
0
        public static Vector3 CubeProject(Camera camera, CSGPlane plane, Vector3 pos)
        {
            UpdateGridOrientation(camera);
            var closest_axis = GeometryUtility.SnapToClosestAxis(plane.normal);
            var intersection = plane.LineIntersection(pos, pos + closest_axis);

            if (float.IsNaN(intersection.x) || float.IsInfinity(intersection.x) ||
                float.IsNaN(intersection.y) || float.IsInfinity(intersection.y) ||
                float.IsNaN(intersection.z) || float.IsInfinity(intersection.z))
            {
                // should never happen, but if all else fails just do a projection ..
                intersection = plane.Project(pos);
            }
            return(intersection);
        }
Exemplo n.º 26
0
        public static List <ShapePolygon> CreateCleanPolygonsFromVertices(Vector3[]       vertices,
                                                                          Vector3 origin,
                                                                          CSGPlane buildPlane,
                                                                          out Vector3[] projectedVertices)
        {
            if (vertices.Length < 3)
            {
                projectedVertices = null;
                return(null);
            }
            var m          = Matrix4x4.TRS(-origin, Quaternion.identity, Vector3.one);
            var vertices2d = GeometryUtility.RotatePlaneTo2D(m, vertices, buildPlane);

            projectedVertices = GeometryUtility.ToVector3XZ(vertices2d);
            return(CreateCleanSubPolygonsFromVertices(vertices2d, buildPlane));
        }
        protected void CenterExtrusionPoints(CSGPlane buildPlane)
        {
            if (!HaveHeight)
            {
                return;
            }

            var center = GetShapeBounds().Center;

            brushPosition = buildPlane.Project(center);
            var height0 = buildPlane.Distance(extrusionPoints[0].Position);
            var height1 = buildPlane.Distance(extrusionPoints[1].Position);

            extrusionPoints[0].Position = brushPosition + (buildPlane.normal * height0);
            extrusionPoints[1].Position = brushPosition + (buildPlane.normal * height1);
        }
Exemplo n.º 28
0
        public Vector3[] GetCurvedVertices(CSGPlane buildPlane, uint curveSides, out int[][] curvedEdges)
        {
            if (curve.Points.Length < 3)
            {
                curvedEdges = null;
                return(GetVertices());
            }
            var vertices3d = CurvedEdges(curveSides, out curvedEdges);
            var vertices2d = GeometryUtility.RotatePlaneTo2D(vertices3d, buildPlane);

            if ((vertices2d[0] - vertices2d[vertices2d.Length - 1]).sqrMagnitude < MathConstants.EqualityEpsilonSqr)
            {
                if (vertices2d.Length == 3)
                {
                    curvedEdges = null;
                    return(GetVertices());
                }
            }

            /*
             * Vector2 intersection;
             * for (int a1i = vertices2d.Length - 1, a2i = 0; a1i >= 0; a2i = a1i, a1i--)
             * {
             *      TryAgain:
             *      var A1 = vertices2d[a1i];
             *      var A2 = vertices2d[a2i];
             *      for (int b1i = a1i - 1, b2i = a1i; b1i >= 0; b2i = b1i, b1i--)
             *      {
             *              var B1 = vertices2d[b1i];
             *              var B2 = vertices2d[b2i];
             *              if (GeometryUtility.TryIntersection(A1, A2,
             *                                                                                      B1, B2,
             *                                                                                      out intersection))
             *              {
             *                      ArrayUtility.Insert(ref vertices2d, a2i, intersection);
             *                      ArrayUtility.Insert(ref vertices2d, b2i, intersection);
             *                      a1i++;
             *                      a2i++;
             *                      goto TryAgain;
             *              }
             *      }
             * }
             */

            return(GeometryUtility.Rotate2DToPlane(vertices2d, buildPlane));
        }
Exemplo n.º 29
0
        public static float DistanceToLine(CSGPlane cameraPlane, Vector2 mousePoint, Vector3 point1, Vector3 point2)
        {
            var dist1 = cameraPlane.Distance(point1);
            var dist2 = cameraPlane.Distance(point2);

            if (dist1 < 0 && dist2 > 0)
            {
                point1 = cameraPlane.Intersection(point1, point2);
            }
            else
            if (dist2 < 0 && dist1 > 0)
            {
                point2 = cameraPlane.Intersection(point1, point2);
            }

            return(DistanceToLine(mousePoint, point1, point2) * 0.5f);
        }
Exemplo n.º 30
0
        public float GetClosestEdgeDistance(CSGPlane cameraPlane, int pointIndex0, int pointIndex1)
        {
            if (pointIndex0 < 0 || pointIndex0 >= WorldPoints.Length ||
                pointIndex1 < 0 || pointIndex1 >= WorldPoints.Length)
            {
                return(float.PositiveInfinity);
            }

            var point0 = WorldPoints[pointIndex0];
            var point1 = WorldPoints[pointIndex1];

            var mousePoint  = Event.current.mousePosition;
            var minDistance = CameraUtility.DistanceToLine(cameraPlane, mousePoint, point0, point1) * 3.0f;

            if (!(Mathf.Abs(minDistance) < 4.0f))
            {
                return(minDistance);
            }

            var surfaceIndex1 = EdgeSurfaces[pointIndex0];
            var surfaceIndex2 = EdgeSurfaces[pointIndex1];

            for (var p = 0; p < PolygonCenterPoints.Length; p++)
            {
                if (p != surfaceIndex1 &&
                    p != surfaceIndex2)
                {
                    continue;
                }

                var polygonCenterPoint       = PolygonCenterPoints[p];
                var polygonCenterPointOnLine = GeometryUtility.ProjectPointOnInfiniteLine(PolygonCenterPoints[p], point0, (point1 - point0).normalized);
                var direction = (polygonCenterPointOnLine - polygonCenterPoint).normalized;

                var nudgedPoint0 = point0 - (direction * 0.05f);
                var nudgedPoint1 = point1 - (direction * 0.05f);

                var otherDistance = CameraUtility.DistanceToLine(cameraPlane, mousePoint, nudgedPoint0, nudgedPoint1);
                if (otherDistance < minDistance)
                {
                    minDistance = otherDistance;
                }
            }

            return(minDistance);
        }