static void SnapToLines(int[] indices, Vector3[] localVertices, Matrix4x4 localToWorld, ref SnapData snapData) { if (indices == null || localVertices == null) { return; } var worldVertex3 = MathConstants.zeroVector3; for (int i = 0; i < indices.Length; i += 2) { var index1 = indices[i + 0]; var index2 = indices[i + 1]; var worldVertex1 = localToWorld.MultiplyPoint(localVertices[index1]); var worldVertex2 = localToWorld.MultiplyPoint(localVertices[index2]); if (!SnapToLine(snapData.worldPoint, worldVertex1, worldVertex2, snapData.snapPlane, out worldVertex3)) { continue; } if (snapData.snapPlane.HasValue && Mathf.Abs(snapData.snapPlane.Value.Distance(worldVertex3)) >= MathConstants.DistanceEpsilon) { continue; } var guiVertex2 = CameraUtility.WorldToGUIPoint(worldVertex3); var guiDistance = (guiVertex2 - snapData.guiPoint).sqrMagnitude * EdgeFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon >= snapData.closestDistanceSqr) { continue; } snapData.closestDistanceSqr = guiDistance; snapData.outEdge = new List <Vector3>() { worldVertex1, worldVertex2 }; snapData.snappedWorldPoint = worldVertex3; } }
static void SnapToLines(Vector3[] worldVertices, int vertexCount, ref SnapData snapData) { if (worldVertices == null) { return; } var worldVertex3 = MathConstants.zeroVector3; for (int i = 0; i < vertexCount; i += 2) { var worldVertex1 = worldVertices[i + 0]; var worldVertex2 = worldVertices[i + 1]; if (!SnapToLine(snapData.worldPoint, worldVertex1, worldVertex2, snapData.snapPlane, out worldVertex3)) { continue; } if (snapData.snapPlane.HasValue && Mathf.Abs(snapData.snapPlane.Value.Distance(worldVertex3)) >= MathConstants.DistanceEpsilon) { continue; } var guiVertex2 = CameraUtility.WorldToGUIPoint(worldVertex3); var guiDistance = (guiVertex2 - snapData.guiPoint).sqrMagnitude * EdgeFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon >= snapData.closestDistanceSqr) { continue; } snapData.closestDistanceSqr = guiDistance; snapData.outEdge = new List <Vector3>() { worldVertex1, worldVertex2 }; snapData.snappedWorldPoint = worldVertex3; } }
public static bool SnapToVertices(CSGBrush brush, CSGPlane?snapPlane, Vector3 worldPosition, out List <Vector3> outEdgePoints, out Vector3 outPosition, float closestDistance = float.PositiveInfinity) { outPosition = MathConstants.zeroVector3; outEdgePoints = null; if (!brush) { return(false); } var controlMesh = brush.ControlMesh; if (controlMesh == null) { return(false); } Vector3?outPoint = null; // Find an edge to snap against the point we're interested in var guiPoint = CameraUtility.WorldToGUIPoint(worldPosition); var closestDistanceSqr = closestDistance * closestDistance; /* * var points = controlMesh.vertices; * var edges = controlMesh.edges; * var polygons = controlMesh.polygons; * var localToWorld = brush.transform.localToWorldMatrix; * for(int p = 0; p < polygons.Length; p++) * { * var edgeIndices = polygons[p].edgeIndices; * for (int e = 0; e < edgeIndices.Length; e++) * { * var edgeIndex = edgeIndices[e]; * if (!edges[edgeIndex].hardEdge) * continue; * * var twinIndex = edges[edgeIndex].twinIndex; * * var vertexIndex1 = edges[edgeIndex].vertexIndex; * var vertexIndex2 = edges[twinIndex].vertexIndex; * * var vertex1 = localToWorld.MultiplyPoint(points[vertexIndex1]); * var vertex2 = localToWorld.MultiplyPoint(points[vertexIndex2]); * * if (!snapPlane.HasValue || * Mathf.Abs(snapPlane.Value.Distance(vertex1)) < Constants.DistanceEpsilon) * { * var guiVertex1 = (Vector3)CameraUtility.WorldToGUIPoint(vertex1); * var guiDistance = (guiVertex1 - guiPoint).magnitude * VertexFudgeFactor; * if (guiDistance + Constants.DistanceEpsilon < closestDistance) * { * closestDistance = guiDistance; * outPoint = vertex1; * } * } * * if (!snapPlane.HasValue || * Mathf.Abs(snapPlane.Value.Distance(vertex2)) < Constants.DistanceEpsilon) * { * var guiVertex2 = (Vector3)CameraUtility.WorldToGUIPoint(vertex2); * var guiDistance = (guiVertex2 - guiPoint).magnitude * VertexFudgeFactor; * if (guiDistance + Constants.DistanceEpsilon < closestDistance) * { * closestDistance = guiDistance; * outPoint = vertex2; * } * } * } * }*/ var outline = BrushOutlineManager.GetBrushOutline(brush.brushNodeID); if (outline != null) { var localToWorld = brush.transform.localToWorldMatrix; var indices = outline.visibleInnerLines; var vertices = outline.vertices; if (indices != null && vertices != null) { for (int i = 0; i < indices.Length; i += 2) { var index1 = indices[i + 0]; var index2 = indices[i + 1]; var vertex1 = localToWorld.MultiplyPoint(vertices[index1]); var vertex2 = localToWorld.MultiplyPoint(vertices[index2]); if (!snapPlane.HasValue || Mathf.Abs(snapPlane.Value.Distance(vertex1)) < MathConstants.DistanceEpsilon) { var guiVertex1 = CameraUtility.WorldToGUIPoint(vertex1); var guiDistance = (guiVertex1 - guiPoint).sqrMagnitude * VertexFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon < closestDistanceSqr) { closestDistanceSqr = guiDistance; outPoint = vertex1; continue; } } if (!snapPlane.HasValue || Mathf.Abs(snapPlane.Value.Distance(vertex2)) < MathConstants.DistanceEpsilon) { var guiVertex2 = CameraUtility.WorldToGUIPoint(vertex2); var guiDistance = (guiVertex2 - guiPoint).sqrMagnitude * VertexFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon < closestDistanceSqr) { closestDistanceSqr = guiDistance; outPoint = vertex2; continue; } } } } if ((RealtimeCSG.CSGSettings.VisibleHelperSurfaces & HelperSurfaceFlags.ShowCulledSurfaces) == HelperSurfaceFlags.ShowCulledSurfaces) { indices = outline.invisibleInnerLines; vertices = outline.vertices; if (indices != null && vertices != null) { for (int i = 0; i < indices.Length; i += 2) { var index1 = indices[i + 0]; var index2 = indices[i + 1]; var vertex1 = localToWorld.MultiplyPoint(vertices[index1]); var vertex2 = localToWorld.MultiplyPoint(vertices[index2]); if (!snapPlane.HasValue || Mathf.Abs(snapPlane.Value.Distance(vertex1)) < MathConstants.DistanceEpsilon) { var guiVertex1 = CameraUtility.WorldToGUIPoint(vertex1); var guiDistance = (guiVertex1 - guiPoint).sqrMagnitude * VertexFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon < closestDistanceSqr) { closestDistanceSqr = guiDistance; outPoint = vertex1; } } if (!snapPlane.HasValue || Mathf.Abs(snapPlane.Value.Distance(vertex1)) < MathConstants.DistanceEpsilon) { var guiVertex2 = CameraUtility.WorldToGUIPoint(vertex2); var guiDistance = (guiVertex2 - guiPoint).magnitude * VertexFudgeFactor; if (guiDistance + MathConstants.DistanceEpsilon < closestDistanceSqr) { closestDistanceSqr = guiDistance; outPoint = vertex2; } } } } } } if (!outPoint.HasValue || float.IsInfinity(closestDistance)) { return(false); } closestDistance = Mathf.Sqrt(closestDistanceSqr); outPosition = outPoint.Value; outEdgePoints = FindAllEdgesThatTouchPoint(brush, outPosition); return(true); }
public static bool SnapToEdge(Camera camera, CSGBrush brush, CSGPlane?_snapPlane, Vector3 _worldPoint, out List <Vector3> outEdgePoints, out Vector3 outPosition) //, float _closestDistance = float.PositiveInfinity) { outPosition = MathConstants.zeroVector3; outEdgePoints = null; if (!brush) { return(false); } var controlMesh = brush.ControlMesh; if (controlMesh == null || camera == null) { return(false); } var snapData = new SnapData { // Find an edge to snap against the point we're interested in worldPoint = _worldPoint, guiPoint = CameraUtility.WorldToGUIPoint(_worldPoint), closestDistance = float.PositiveInfinity, closestDistanceSqr = float.PositiveInfinity, snapPlane = _snapPlane, outEdge = null, snappedWorldPoint = MathConstants.PositiveInfinityVector3 }; var points = controlMesh.Vertices; var edges = controlMesh.Edges; var polygons = controlMesh.Polygons; var localToWorld = brush.transform.localToWorldMatrix; if (_internal_snapEdgesUsed == null || _internal_snapEdgesUsed.Length < edges.Length) { _internal_snapEdgesUsed = new bool[edges.Length]; _internal_snapVertices = new Vector3[edges.Length * 2]; } Array.Clear(_internal_snapEdgesUsed, 0, _internal_snapEdgesUsed.Length); _internal_snapVertexCount = 0; for (int p = 0; p < polygons.Length; p++) { var edgeIndices = polygons[p].EdgeIndices; for (int e = 0; e < edgeIndices.Length; e++) { var edgeIndex = edgeIndices[e]; if (!edges[edgeIndex].HardEdge) { continue; } if (_internal_snapEdgesUsed[edgeIndex]) { continue; } var twin = controlMesh.GetTwinEdgeIndex(edgeIndex); _internal_snapEdgesUsed[edgeIndex] = true; _internal_snapEdgesUsed[twin] = true; var twinIndex = edges[edgeIndex].TwinIndex; var vertexIndex1 = edges[edgeIndex].VertexIndex; var vertexIndex2 = edges[twinIndex].VertexIndex; _internal_snapVertices[_internal_snapVertexCount + 0] = localToWorld.MultiplyPoint(points[vertexIndex1]); _internal_snapVertices[_internal_snapVertexCount + 1] = localToWorld.MultiplyPoint(points[vertexIndex2]); _internal_snapVertexCount += 2; } } if (_internal_snapVertexCount > 0) { SnapToLines(_internal_snapVertices, _internal_snapVertexCount, ref snapData); } var outline = BrushOutlineManager.GetBrushOutline(brush.brushNodeID); if (outline != null) { var vertices = outline.vertices; var indices = outline.visibleInnerLines; SnapToLines(indices, vertices, localToWorld, ref snapData); if ((RealtimeCSG.CSGSettings.VisibleHelperSurfaces & HelperSurfaceFlags.ShowCulledSurfaces) == HelperSurfaceFlags.ShowCulledSurfaces) { indices = outline.invisibleInnerLines; SnapToLines(indices, vertices, localToWorld, ref snapData); } } if (snapData.outEdge == null || float.IsInfinity(snapData.closestDistanceSqr)) { return(false); } snapData.closestDistance = Mathf.Sqrt(snapData.closestDistanceSqr); outEdgePoints = snapData.outEdge; outPosition = snapData.snappedWorldPoint; return(true); }
public static Vector3 SnapToWorld(Camera camera, CSGPlane snapPlane, Vector3 unsnappedPosition, Vector3 snappedPosition, ref List <Vector3> snappingEdges, out CSGBrush snappedOnBrush, CSGBrush[] ignoreBrushes = null) { snappedOnBrush = null; test_points[0] = unsnappedPosition; test_points[1] = snappedPosition; worldIntersections.Clear(); for (int i = 0; i < test_points.Length; i++) { var test_point2D = CameraUtility.WorldToGUIPoint(test_points[i]); LegacyBrushIntersection intersection; if (SceneQueryUtility.FindWorldIntersection(camera, test_point2D, out intersection)) { if (intersection.brush && intersection.brush.ControlMesh != null) { intersection.worldIntersection = GeometryUtility.ProjectPointOnPlane(snapPlane, intersection.worldIntersection); worldIntersections.Add(intersection); } } } var old_difference = snappedPosition - unsnappedPosition; var old_difference_magnitude = old_difference.magnitude * 1.5f; Vector3 newSnappedPoint = snappedPosition; CSGPlane?snappingPlane = snapPlane; for (int i = 0; i < worldIntersections.Count; i++) { if (ignoreBrushes != null && ArrayUtility.Contains(ignoreBrushes, worldIntersections[i].brush)) { continue; } List <Vector3> outEdgePoints; Vector3 outPosition; if (GridUtility.SnapToVertices(worldIntersections[i].brush, snappingPlane, unsnappedPosition, out outEdgePoints, out outPosition)) { var new_difference = outPosition - unsnappedPosition; var new_difference_magnitude = new_difference.magnitude; if (new_difference_magnitude <= old_difference_magnitude + MathConstants.EqualityEpsilon) { old_difference_magnitude = new_difference_magnitude; newSnappedPoint = outPosition; snappingEdges = outEdgePoints; snappedOnBrush = worldIntersections[i].brush; } } if (GridUtility.SnapToEdge(camera, worldIntersections[i].brush, snappingPlane ?? worldIntersections[i].worldPlane, worldIntersections[i].worldIntersection, out outEdgePoints, out outPosition)) { var new_difference = outPosition - unsnappedPosition; var new_difference_magnitude = new_difference.magnitude * 1.1f; if (new_difference_magnitude <= old_difference_magnitude + MathConstants.EqualityEpsilon) { old_difference_magnitude = new_difference_magnitude; newSnappedPoint = outPosition; snappingEdges = outEdgePoints; snappedOnBrush = worldIntersections[i].brush; } } } //snappingEdges = FindAllEdgesThatTouchPoint(snappedOnBrush, newSnappedPoint); return(newSnappedPoint); }