/// <summary>Generate a <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair from the given planes (and optional other values)</summary> /// <remarks><note>Keep in mind that the planes encapsulate the geometry we're generating, so it can only be <i>convex</i>.</note></remarks> /// <param name="controlMesh">The generated <see cref="RealtimeCSG.Legacy.ControlMesh"/></param> /// <param name="shape">The generated <see cref="RealtimeCSG.Legacy.Shape"/></param> /// <param name="planes">The geometric planes of all the surfaces that define this convex shape</param> /// <param name="tangents">The tangents for each plane (optional)</param> /// <param name="binormals">The binormals for each plane (optional)</param> /// <param name="materials">The materials for each plane (optional)</param> /// <param name="textureMatrices">The texture matrices for each plane (optional)</param> /// <param name="textureMatrixSpace">The texture matrix space for each plane (optional)</param> /// <param name="smoothingGroups">The smoothing groups for each plane (optional)</param> /// <param name="texGenFlags">The <see cref="RealtimeCSG.Legacy.TexGenFlags"/> for each plane (optional)</param> /// <returns>*true* on success, *false* on failure</returns> public static bool CreateControlMeshFromPlanes(out ControlMesh controlMesh, out Shape shape, UnityEngine.Plane[] planes, UnityEngine.Vector3[] tangents = null, UnityEngine.Vector3[] binormals = null, UnityEngine.Material[] materials = null, UnityEngine.Matrix4x4[] textureMatrices = null, TextureMatrixSpace textureMatrixSpace = TextureMatrixSpace.WorldSpace, uint[] smoothingGroups = null, TexGenFlags[] texGenFlags = null) { controlMesh = null; shape = null; if (planes == null) { Debug.LogError("The planes array is not allowed to be null"); return(false); } if (planes.Length < 4) { Debug.LogError("The planes array must have at least 4 planes"); return(false); } if (materials == null) { materials = new Material[planes.Length]; for (int i = 0; i < materials.Length; i++) { materials[i] = CSGSettings.DefaultMaterial; } } if (planes.Length != materials.Length || (textureMatrices != null && planes.Length != textureMatrices.Length) || (tangents != null && tangents.Length != textureMatrices.Length) || (binormals != null && binormals.Length != textureMatrices.Length) || (smoothingGroups != null && smoothingGroups.Length != materials.Length)) { Debug.LogError("All non null arrays need to be of equal length"); return(false); } shape = new Shape(); shape.TexGenFlags = new TexGenFlags[planes.Length]; shape.Surfaces = new Surface[planes.Length]; shape.TexGens = new TexGen[planes.Length]; for (int i = 0; i < planes.Length; i++) { shape.Surfaces[i].Plane = new CSGPlane(planes[i].normal, -planes[i].distance); Vector3 tangent, binormal; if (tangents != null && binormals != null) { tangent = tangents[i]; binormal = binormals[i]; } else { GeometryUtility.CalculateTangents(planes[i].normal, out tangent, out binormal); } shape.Surfaces[i].Tangent = -tangent; shape.Surfaces[i].BiNormal = -binormal; shape.Surfaces[i].TexGenIndex = i; shape.TexGens[i] = new TexGen(materials[i]); if (smoothingGroups != null) { shape.TexGens[i].SmoothingGroup = smoothingGroups[i]; } if (texGenFlags != null) { shape.TexGenFlags[i] = texGenFlags[i]; } else { shape.TexGenFlags[i] = RealtimeCSG.CSGSettings.DefaultTexGenFlags; } } controlMesh = ControlMeshUtility.CreateFromShape(shape, MathConstants.DistanceEpsilon); if (controlMesh == null) { return(false); } if (!ControlMeshUtility.Validate(controlMesh, shape)) { //Debug.LogError("Generated mesh is not valid"); return(false); } if (textureMatrices != null) { int n = 0; for (var i = 0; i < planes.Length; i++) { if (shape.Surfaces[n].TexGenIndex != i) { continue; } shape.Surfaces[n].TexGenIndex = n; SurfaceUtility.AlignTextureSpaces(textureMatrices[i], textureMatrixSpace == TextureMatrixSpace.PlaneSpace, ref shape.TexGens[n], ref shape.TexGenFlags[n], ref shape.Surfaces[n]); n++; } } return(true); }
public static void Flip(CSGBrush[] brushes, Matrix4x4 flipMatrix, string undoDescription = "Flip brushes") { var fail = false; Undo.IncrementCurrentGroup(); Undo.RegisterCompleteObjectUndo(brushes.ToArray <UnityEngine.Object>(), undoDescription); var isGlobal = Tools.pivotRotation == PivotRotation.Global; var centerAll = BoundsUtilities.GetCenter(brushes); for (var t = 0; t < brushes.Length; t++) { var brush = brushes[t]; var shape = brush.Shape; var position = brush.transform.position; Matrix4x4 brushFlip; Vector3 brushCenter; if (isGlobal) { brushFlip = brush.transform.localToWorldMatrix * flipMatrix * brush.transform.worldToLocalMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll) - position; } else { brushFlip = flipMatrix; brushCenter = brush.transform.InverseTransformPoint(centerAll); } for (var s = 0; s < shape.Surfaces.Length; s++) { var plane = shape.Surfaces[s].Plane; var normal = brushFlip.MultiplyVector(plane.normal); var biNormal = brushFlip.MultiplyVector(shape.Surfaces[s].BiNormal); var tangent = brushFlip.MultiplyVector(shape.Surfaces[s].Tangent); var pointOnPlane = plane.pointOnPlane; pointOnPlane -= brushCenter; pointOnPlane = brushFlip.MultiplyPoint(pointOnPlane); pointOnPlane += brushCenter; shape.Surfaces[s].Plane = new CSGPlane(normal, pointOnPlane); shape.Surfaces[s].BiNormal = biNormal; shape.Surfaces[s].Tangent = tangent; } var controlMesh = brush.ControlMesh; brush.Shape = shape; brush.ControlMesh = ControlMeshUtility.CreateFromShape(shape); if (brush.ControlMesh == null) { brush.ControlMesh = controlMesh; fail = true; break; } ShapeUtility.CreateCutter(shape, brush.ControlMesh); brush.EnsureInitialized(); brush.ControlMesh.SetDirty(); EditorUtility.SetDirty(brush); InternalCSGModelManager.CheckSurfaceModifications(brush, true); ControlMeshUtility.RebuildShape(brush); } if (fail) { Debug.Log("Failed to perform operation"); Undo.RevertAllInCurrentGroup(); } InternalCSGModelManager.Refresh(); }