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)); }
public void ProjectShapeOnBuildPlane(CSGPlane plane) { for (int i = 0; i < vertices.Length; i++) { vertices[i] = plane.Project(vertices[i]); } }
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)); }
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; }
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); }
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); }
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); }
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)); }
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])); }
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; } }
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); }
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); }
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); }
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); }
public static List <ShapePolygon> CreateCleanPolygonsFromVertices(Vector3[] vertices, Vector3 origin, CSGPlane buildPlane) { Vector3[] projectedVertices; return(CreateCleanPolygonsFromVertices(vertices, origin, buildPlane, out projectedVertices)); }
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)); }
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); }
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); }
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); }
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); }
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)); }
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); }
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); }