/// <summary>Copy the contents of another <see cref="RealtimeCSG.Legacy.ControlMesh"/> to this <see cref="RealtimeCSG.Legacy.ControlMesh"/>.</summary> /// <param name="other">The <see cref="RealtimeCSG.Legacy.ControlMesh"/> to copy from.</param> public void CopyFrom(ControlMesh other) { if (other == null) { Reset(); return; } if (other.Vertices != null) { if (Vertices == null || Vertices.Length != other.Vertices.Length) { Vertices = new Vector3[other.Vertices.Length]; } Array.Copy(other.Vertices, Vertices, other.Vertices.Length); } else { Vertices = null; } if (other.Edges != null) { if (Edges == null || Edges.Length != other.Edges.Length) { Edges = new HalfEdge[other.Edges.Length]; } Array.Copy(other.Edges, Edges, other.Edges.Length); } else { Edges = null; } if (other.Polygons != null) { if (Polygons == null || Polygons.Length != other.Polygons.Length) { Polygons = new Polygon[other.Polygons.Length]; } for (var p = 0; p < other.Polygons.Length; p++) { if (other.Polygons[p].EdgeIndices == null || other.Polygons[p].EdgeIndices.Length == 0) { continue; } var newEdges = new int[other.Polygons[p].EdgeIndices.Length]; Array.Copy(other.Polygons[p].EdgeIndices, newEdges, other.Polygons[p].EdgeIndices.Length); Polygons[p] = new Polygon(newEdges, other.Polygons[p].TexGenIndex); } } else { Polygons = null; } valid = other.valid; Generation = other.Generation; }
/// <summary> /// Creates a cube <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair with <paramref name="size"/> and optional <paramref name="material"/> /// </summary> /// <param name="controlMesh">The generated <see cref="RealtimeCSG.Legacy.ControlMesh"/></param> /// <param name="shape">The generated <see cref="RealtimeCSG.Legacy.Shape"/></param> /// <param name="size">The size of the cube</param> /// <param name="material">The [UnityEngine.Material](https://docs.unity3d.com/ScriptReference/Material.html) that will be set to all surfaces of the cube (optional)</param> /// <returns>*true* on success, *false* on failure</returns> public static bool CreateCubeControlMesh(out ControlMesh controlMesh, out Shape shape, UnityEngine.Vector3 size, UnityEngine.Material material = null) { Vector3 halfSize = size * 0.5f; return(CreateCubeControlMesh(out controlMesh, out shape, halfSize, -halfSize, material)); }
/// <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); }
internal static CSGBrush CreateBrushComponent(UnityEngine.GameObject gameObject, ControlMesh controlMesh, Shape shape) { var brush = gameObject.AddComponent <CSGBrush>(); if (!brush) { return(null); } brush.ControlMesh = controlMesh; brush.Shape = shape; if (brush.ControlMesh != null) { brush.ControlMesh.SetDirty(); } if (brush.Shape != null) { ShapeUtility.EnsureInitialized(brush.Shape); } return(brush); }
/// <summary>Converts a <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair into a <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</summary> /// <param name="controlMesh">A legacy <see cref="RealtimeCSG.Legacy.ControlMesh"/> that describes the shape of the <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</param> /// <param name="shape">A legacy <see cref="RealtimeCSG.Legacy.Shape"/> that describes the surfaces in the <see cref="RealtimeCSG.Foundation.BrushMesh"/>.</param> /// <returns>A new <see cref="RealtimeCSG.Foundation.BrushMesh"/></returns> public static BrushMesh GenerateFromControlMesh(ControlMesh controlMesh, Shape shape) { if (controlMesh == null || shape == null) { return(null); } if (!ControlMeshUtility.Validate(controlMesh, shape)) { return(null); } var vertices = controlMesh.Vertices; var srcEdges = controlMesh.Edges; var srcPolygons = controlMesh.Polygons; if (vertices == null || srcEdges == null || srcPolygons == null) { return(null); } var surfaces = shape.Surfaces; var texgens = shape.TexGens; var texgenFlags = shape.TexGenFlags; if (surfaces == null || texgens == null || texgenFlags == null) { return(null); } var polygonCount = surfaces.Length; if (polygonCount != srcPolygons.Length || polygonCount != texgens.Length || polygonCount != texgenFlags.Length || polygonCount != surfaces.Length) { return(null); } var brushMesh = new BrushMesh { polygons = new BrushMesh.Polygon[polygonCount], vertices = vertices.ToArray() }; for (int i = 0; i < polygonCount; i++) { var polygonIndex = i; var surface = surfaces[polygonIndex]; var texGenIndex = surface.TexGenIndex; var texGen = texgens[texGenIndex]; var flags = texgenFlags[texGenIndex]; brushMesh.polygons[i].polygonID = polygonIndex; brushMesh.polygons[i].surface = CreateSurfaceDescription(surface, texGen, flags); brushMesh.polygons[i].layers = CreateSurfaceLayer(texGen, flags); } int counter = 0; for (var i = 0; i < polygonCount; i++) { var polygonIndex = i; var edgeIndices = srcPolygons[polygonIndex].EdgeIndices; brushMesh.polygons[i].firstEdge = counter; brushMesh.polygons[i].edgeCount = edgeIndices.Length; counter += edgeIndices.Length; } brushMesh.halfEdges = new BrushMesh.HalfEdge[counter]; counter = 0; for (var i = 0; i < polygonCount; i++) { var polygonIndex = i; var edgeIndices = srcPolygons[polygonIndex].EdgeIndices; for (var v = 0; v < edgeIndices.Length; v++) { var edge = srcEdges[edgeIndices[v]]; brushMesh.halfEdges[counter + v].vertexIndex = edge.VertexIndex; var twinIndex = edge.TwinIndex; var twinPolygonIndex = srcEdges[twinIndex].PolygonIndex; var twinEdges = srcPolygons[twinPolygonIndex].EdgeIndices; var found = false; for (var t = 0; t < twinEdges.Length; t++) { if (twinEdges[t] == twinIndex) { twinIndex = t + brushMesh.polygons[twinPolygonIndex].firstEdge; found = true; break; } } if (!found) { return(null); } brushMesh.halfEdges[counter + v].twinIndex = twinIndex; } counter += edgeIndices.Length; } return(brushMesh); }
internal static CSGBrush CreateBrush(UnityEngine.Transform parent, string brushName, ControlMesh controlMesh, Shape shape) { var gameObject = OperationsUtility.CreateGameObject(parent, brushName, false); if (!gameObject) { return(null); } var brush = gameObject.AddComponent <CSGBrush>(); if (!brush) { return(null); } brush.ControlMesh = controlMesh; brush.Shape = shape; if (brush.ControlMesh != null) { brush.ControlMesh.SetDirty(); } if (brush.Shape != null) { ShapeUtility.EnsureInitialized(brush.Shape); } return(brush); }
internal static bool CreateCubeControlMesh(out ControlMesh controlMesh, out Shape shape, UnityEngine.Vector3 min, UnityEngine.Vector3 max, UnityEngine.Material material = null) { if (min.x > max.x) { float x = min.x; min.x = max.x; max.x = x; } if (min.y > max.y) { float y = min.y; min.y = max.y; max.y = y; } if (min.z > max.z) { float z = min.z; min.z = max.z; max.z = z; } if (min.x == max.x || min.y == max.y || min.z == max.z) { shape = null; controlMesh = null; return(false); } controlMesh = new ControlMesh(); controlMesh.Vertices = new [] { new Vector3(min.x, min.y, min.z), // 0 new Vector3(min.x, max.y, min.z), // 1 new Vector3(max.x, max.y, min.z), // 2 new Vector3(max.x, min.y, min.z), // 3 new Vector3(min.x, min.y, max.z), // 4 new Vector3(max.x, min.y, max.z), // 5 new Vector3(max.x, max.y, max.z), // 6 new Vector3(min.x, max.y, max.z) // 7 }; controlMesh.Edges = new [] { new HalfEdge { PolygonIndex = 0, TwinIndex = 21, VertexIndex = 0 }, // 0 new HalfEdge { PolygonIndex = 0, TwinIndex = 8, VertexIndex = 1 }, // 1 new HalfEdge { PolygonIndex = 0, TwinIndex = 12, VertexIndex = 2 }, // 2 new HalfEdge { PolygonIndex = 0, TwinIndex = 17, VertexIndex = 3 }, // 3 new HalfEdge { PolygonIndex = 1, TwinIndex = 10, VertexIndex = 4 }, // 4 new HalfEdge { PolygonIndex = 1, TwinIndex = 23, VertexIndex = 5 }, // 5 new HalfEdge { PolygonIndex = 1, TwinIndex = 19, VertexIndex = 6 }, // 6 new HalfEdge { PolygonIndex = 1, TwinIndex = 14, VertexIndex = 7 }, // 7 new HalfEdge { PolygonIndex = 2, TwinIndex = 1, VertexIndex = 0 }, // 8 new HalfEdge { PolygonIndex = 2, TwinIndex = 20, VertexIndex = 4 }, // 9 new HalfEdge { PolygonIndex = 2, TwinIndex = 4, VertexIndex = 7 }, // 10 new HalfEdge { PolygonIndex = 2, TwinIndex = 13, VertexIndex = 1 }, // 11 new HalfEdge { PolygonIndex = 3, TwinIndex = 2, VertexIndex = 1 }, // 12 new HalfEdge { PolygonIndex = 3, TwinIndex = 11, VertexIndex = 7 }, // 13 new HalfEdge { PolygonIndex = 3, TwinIndex = 7, VertexIndex = 6 }, // 14 new HalfEdge { PolygonIndex = 3, TwinIndex = 18, VertexIndex = 2 }, // 15 new HalfEdge { PolygonIndex = 4, TwinIndex = 22, VertexIndex = 3 }, // 16 new HalfEdge { PolygonIndex = 4, TwinIndex = 3, VertexIndex = 2 }, // 17 new HalfEdge { PolygonIndex = 4, TwinIndex = 15, VertexIndex = 6 }, // 18 new HalfEdge { PolygonIndex = 4, TwinIndex = 6, VertexIndex = 5 }, // 19 new HalfEdge { PolygonIndex = 5, TwinIndex = 9, VertexIndex = 0 }, // 20 new HalfEdge { PolygonIndex = 5, TwinIndex = 0, VertexIndex = 3 }, // 21 new HalfEdge { PolygonIndex = 5, TwinIndex = 16, VertexIndex = 5 }, // 22 new HalfEdge { PolygonIndex = 5, TwinIndex = 5, VertexIndex = 4 } // 23 }; controlMesh.Polygons = new [] { // left/right new Polygon(new int[] { 0, 1, 2, 3 }, 0), // 0 new Polygon(new int[] { 4, 5, 6, 7 }, 1), // 1 // front/back new Polygon(new int[] { 8, 9, 10, 11 }, 2), // 2 new Polygon(new int[] { 12, 13, 14, 15 }, 3), // 3 // top/down new Polygon(new int[] { 16, 17, 18, 19 }, 4), // 4 new Polygon(new int[] { 20, 21, 22, 23 }, 5) // 5 }; shape = new Shape(); shape.Surfaces = new Surface[6]; shape.Surfaces[0].TexGenIndex = 0; shape.Surfaces[1].TexGenIndex = 1; shape.Surfaces[2].TexGenIndex = 2; shape.Surfaces[3].TexGenIndex = 3; shape.Surfaces[4].TexGenIndex = 4; shape.Surfaces[5].TexGenIndex = 5; shape.Surfaces[0].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 0); shape.Surfaces[1].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 1); shape.Surfaces[2].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 2); shape.Surfaces[3].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 3); shape.Surfaces[4].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 4); shape.Surfaces[5].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, 5); GeometryUtility.CalculateTangents(shape.Surfaces[0].Plane.normal, out shape.Surfaces[0].Tangent, out shape.Surfaces[0].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[1].Plane.normal, out shape.Surfaces[1].Tangent, out shape.Surfaces[1].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[2].Plane.normal, out shape.Surfaces[2].Tangent, out shape.Surfaces[2].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[3].Plane.normal, out shape.Surfaces[3].Tangent, out shape.Surfaces[3].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[4].Plane.normal, out shape.Surfaces[4].Tangent, out shape.Surfaces[4].BiNormal); GeometryUtility.CalculateTangents(shape.Surfaces[5].Plane.normal, out shape.Surfaces[5].Tangent, out shape.Surfaces[5].BiNormal); if (material == null) { material = CSGSettings.DefaultMaterial; } shape.TexGens = new TexGen[6]; shape.TexGens[0].RenderMaterial = material; shape.TexGens[1].RenderMaterial = material; shape.TexGens[2].RenderMaterial = material; shape.TexGens[3].RenderMaterial = material; shape.TexGens[4].RenderMaterial = material; shape.TexGens[5].RenderMaterial = material; shape.TexGens[0].Scale = MathConstants.oneVector3; shape.TexGens[1].Scale = MathConstants.oneVector3; shape.TexGens[2].Scale = MathConstants.oneVector3; shape.TexGens[3].Scale = MathConstants.oneVector3; shape.TexGens[4].Scale = MathConstants.oneVector3; shape.TexGens[5].Scale = MathConstants.oneVector3; // shape.TexGens[0].Color = Color.white; // shape.TexGens[1].Color = Color.white; // shape.TexGens[2].Color = Color.white; // shape.TexGens[3].Color = Color.white; // shape.TexGens[4].Color = Color.white; // shape.TexGens[5].Color = Color.white; shape.TexGenFlags = new [] { RealtimeCSG.CSGSettings.DefaultTexGenFlags, RealtimeCSG.CSGSettings.DefaultTexGenFlags, RealtimeCSG.CSGSettings.DefaultTexGenFlags, RealtimeCSG.CSGSettings.DefaultTexGenFlags, RealtimeCSG.CSGSettings.DefaultTexGenFlags, RealtimeCSG.CSGSettings.DefaultTexGenFlags }; //controlMesh.Validate(); ShapeUtility.EnsureInitialized(shape); controlMesh.Valid = ControlMeshUtility.Validate(controlMesh, shape); return(controlMesh.Valid); }
/// <summary>Create new <see cref="RealtimeCSG.Legacy.ControlMesh"/> by copying an existing <see cref="RealtimeCSG.Legacy.ControlMesh"/>.</summary> /// <param name="other">The <see cref="RealtimeCSG.Legacy.ControlMesh"/> to copy from.</param> public ControlMesh(ControlMesh other) { CopyFrom(other); }