public static bool GenerateSphere(ref BrushMesh brushMesh, ref ChiselSphereDefinition definition) { definition.Validate(); var transform = float4x4.TRS(Vector3.zero, quaternion.AxisAngle(new Vector3(0, 1, 0), definition.rotation), Vector3.one); return(BrushMeshFactory.GenerateSphere(ref brushMesh, definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition)); }
private static bool UpdateBrushMesh(Int32 brushMeshIndex, BrushMesh brushMesh) { if (brushMeshIndex == 0 || brushMesh.vertices == null || brushMesh.halfEdges == null || brushMesh.polygons == null) { return(false); } var edgeCount = brushMesh.halfEdges.Length; if (edgeCount < 12) { return(false); } var polygonCount = brushMesh.polygons.Length; if (polygonCount < 4) { return(false); } var vertexCount = brushMesh.vertices.Length; var result = UpdateBrushMesh(brushMeshIndex, brushMesh.vertices, brushMesh.halfEdges, brushMesh.polygons); return(result); }
public BrushMesh(BrushMesh other) { version = other.version; if (other.vertices != null) { vertices = new float3[other.vertices.Length]; Array.Copy(other.vertices, this.vertices, other.vertices.Length); } if (other.halfEdges != null) { halfEdges = new HalfEdge[other.halfEdges.Length]; Array.Copy(other.halfEdges, this.halfEdges, other.halfEdges.Length); } if (other.halfEdgePolygonIndices != null) { halfEdgePolygonIndices = new int[other.halfEdgePolygonIndices.Length]; Array.Copy(other.halfEdgePolygonIndices, this.halfEdgePolygonIndices, other.halfEdgePolygonIndices.Length); } if (other.polygons != null) { polygons = new Polygon[other.polygons.Length]; Array.Copy(other.polygons, this.polygons, other.polygons.Length); } if (other.planes != null) { planes = new float4[other.planes.Length]; Array.Copy(other.planes, this.planes, other.planes.Length); } }
public static bool UpdateBrushMesh(Int32 brushMeshInstanceID, Vector3[] vertices, BrushMesh.HalfEdge[] halfEdges, BrushMesh.Polygon[] polygons) { if (vertices == null || halfEdges == null || polygons == null) { return(false); } if (!AssertBrushMeshIDValid(brushMeshInstanceID)) { return(false); } BrushMesh brushMesh = GetBrushMesh(brushMeshInstanceID); if (brushMesh == null) { Debug.LogWarning("Brush has no BrushMeshInstance set"); return(false); } if (!brushMesh.Set(vertices, halfEdges, polygons)) { Debug.LogWarning("GenerateMesh failed"); return(false); } CSGManager.NotifyBrushMeshModified(brushMeshInstanceID); return(true); }
public static bool GenerateCapsule(ref BrushMesh brushMesh, ref ChiselCapsuleDefinition definition) { Vector3[] vertices = null; if (!BrushMeshFactory.GenerateCapsuleVertices(ref definition, ref vertices)) { brushMesh.Clear(); return(false); } // TODO: share this with GenerateCapsuleVertices var bottomCap = !definition.haveRoundedBottom; var topCap = !definition.haveRoundedTop; var sides = definition.sides; var segments = definition.segments; var bottomVertex = definition.bottomVertex; var topVertex = definition.topVertex; if (!BrushMeshFactory.GenerateSegmentedSubMesh(ref brushMesh, sides, segments, vertices, topCap, bottomCap, topVertex, bottomVertex, definition.surfaceDefinition)) { brushMesh.Clear(); return(false); } return(true); }
public static bool GenerateHemisphere(ref BrushMesh brushMesh, ref ChiselHemisphereDefinition definition) { definition.Validate(); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); return(GenerateHemisphereSubMesh(ref brushMesh, definition.diameterXYZ, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition)); }
public bool EnsureSize(int expectedSize) { if ((brushMeshes != null && expectedSize == brushMeshes.Length) || (brushMeshes == null && expectedSize == 0)) { return(false); } if (expectedSize == 0) { brushMeshes = null; return(true); } var newBrushMeshes = new BrushMesh[expectedSize]; var prevLength = (brushMeshes == null) ? 0 : brushMeshes.Length; if (prevLength > 0) { Array.Copy(brushMeshes, newBrushMeshes, Mathf.Min(newBrushMeshes.Length, prevLength)); } for (int i = prevLength; i < newBrushMeshes.Length; i++) { newBrushMeshes[i] = new BrushMesh(); } brushMeshes = newBrushMeshes; operations = new CSGOperationType[expectedSize]; return(true); }
public BrushMesh(BrushMesh other) { version = other.version; if (other.vertices != null) { vertices = new Vector3[other.vertices.Length]; Array.Copy(other.vertices, this.vertices, other.vertices.Length); } if (other.halfEdges != null) { halfEdges = new HalfEdge[other.halfEdges.Length]; Array.Copy(other.halfEdges, this.halfEdges, other.halfEdges.Length); } if (other.halfEdgePolygonIndices != null) { halfEdgePolygonIndices = new int[other.halfEdgePolygonIndices.Length]; Array.Copy(other.halfEdgePolygonIndices, this.halfEdgePolygonIndices, other.halfEdgePolygonIndices.Length); } if (other.polygons != null) { polygons = new Polygon[other.polygons.Length]; Array.Copy(other.polygons, this.polygons, other.polygons.Length); } if (other.surfaces != null) { surfaces = new Surface[other.surfaces.Length]; Array.Copy(other.surfaces, this.surfaces, other.surfaces.Length); } }
public void Reset() { brushOutline = null; if (surfaceDefinition != null) { surfaceDefinition.Reset(); } }
// TODO: batch & jobify this somehow public unsafe static BlobAssetReference <BrushMeshBlob> Build(BrushMesh brushMesh, Allocator allocator = Allocator.Persistent) { if (brushMesh == null || brushMesh.vertices == null || brushMesh.polygons == null || brushMesh.halfEdges == null || brushMesh.vertices.Length < 4 || brushMesh.polygons.Length < 4 || brushMesh.halfEdges.Length < 12) { return(BlobAssetReference <BrushMeshBlob> .Null); } ref var srcVertices = ref brushMesh.vertices;
// temporary solution to be able to see a brush wireframe static BrushOutline CreateOutline(BrushMesh brushMesh) { var brushOutline = new BrushOutline(); brushOutline.Reset(); if (brushMesh == null) { return(brushOutline); } brushOutline.surfaceOutlines = new Outline[brushMesh.surfaces.Length]; brushOutline.vertices = brushMesh.vertices.ToArray(); var surfaceOutlines = brushOutline.surfaceOutlines; for (int p = 0; p < brushMesh.polygons.Length; p++) { surfaceOutlines[p] = new Outline(); surfaceOutlines[p].Reset(); } var brushVisibleOuterLines = new List <int>(); var surfaceVisibleOuterLines = new List <int>(); for (int p = 0; p < brushMesh.polygons.Length; p++) { var surfaceOutline = surfaceOutlines[p]; surfaceVisibleOuterLines.Clear(); var firstEdge = brushMesh.polygons[p].firstEdge; var edgeCount = brushMesh.polygons[p].edgeCount; var lastEdge = firstEdge + edgeCount; var vertexIndex0 = brushMesh.halfEdges[lastEdge - 1].vertexIndex; var vertexIndex1 = 0; for (int h = firstEdge; h < lastEdge; vertexIndex0 = vertexIndex1, h++) { vertexIndex1 = brushMesh.halfEdges[h].vertexIndex; if (vertexIndex0 > vertexIndex1) // avoid duplicate edges { brushVisibleOuterLines.Add(vertexIndex0); brushVisibleOuterLines.Add(vertexIndex1); } surfaceVisibleOuterLines.Add(vertexIndex0); surfaceVisibleOuterLines.Add(vertexIndex1); } surfaceOutline.visibleOuterLines = surfaceVisibleOuterLines.ToArray(); } brushOutline.brushOutline.visibleOuterLines = brushVisibleOuterLines.ToArray(); return(brushOutline); }
public bool Generate(ref ChiselBrushContainer brushContainer) { Profiler.BeginSample("GenerateBrush"); try { if (!IsValid) { return(false); } Profiler.BeginSample("EnsureSize"); brushContainer.EnsureSize(1); Profiler.EndSample(); Profiler.BeginSample("new BrushMesh"); BrushMesh brushMesh; if (brushContainer.brushMeshes[0] == null) { brushMesh = new BrushMesh(brushOutline); brushContainer.brushMeshes[0] = brushMesh; } else { brushContainer.brushMeshes[0].CopyFrom(brushOutline); brushMesh = brushContainer.brushMeshes[0]; } Profiler.EndSample(); Profiler.BeginSample("Definition.Validate"); Validate(); Profiler.EndSample(); Profiler.BeginSample("Assign Materials"); for (int p = 0; p < brushMesh.polygons.Length; p++) { brushMesh.polygons[p].surface = surfaceDefinition.surfaces[p]; } Profiler.EndSample(); Profiler.BeginSample("BrushMesh.Validate"); var valid = brushMesh.Validate(); Profiler.EndSample(); return(valid); } finally { Profiler.EndSample(); } }
static bool GenerateBox(ref BrushMesh brushMesh, ref ChiselBoxDefinition definition) { definition.Validate(); var min = definition.min; var max = definition.max; if (!BoundsExtensions.IsValid(min, max)) { brushMesh.Clear(); return(false); } return(GenerateBox(ref brushMesh, definition.min, definition.max, definition.surfaceDefinition)); }
private static Int32 CreateBrushMesh(int userID, BrushMesh brushMesh) { if (brushMesh == null || brushMesh.vertices == null || brushMesh.halfEdges == null || brushMesh.polygons == null) { return(0); } var edgeCount = brushMesh.halfEdges.Length; if (edgeCount < 12) { return(0); } var polygonCount = brushMesh.polygons.Length; if (polygonCount < 4) { return(0); } var vertexCount = brushMesh.vertices.Length; if (vertexCount < 4) { return(0); } #if USE_MANAGED_CSG_IMPLEMENTATION var result = CreateBrushMesh(userID, brushMesh.vertices, brushMesh.halfEdges, brushMesh.polygons); #else var result = CreateBrushMesh(userID, vertexCount, brushMesh.vertices, edgeCount, brushMesh.halfEdges, polygonCount, brushMesh.polygons); #endif if (result <= 0) { result = 0; } return(result); }
public static bool UpdateBrushMesh(Int32 brushMeshInstanceID, float3[] vertices, BrushMesh.HalfEdge[] halfEdges, BrushMesh.Polygon[] polygons) { if (vertices == null || halfEdges == null || polygons == null) { return(false); } if (!AssertBrushMeshIDValid(brushMeshInstanceID)) { return(false); } BrushMesh brushMesh = GetBrushMesh(brushMeshInstanceID); if (brushMesh == null) { Debug.LogWarning("Brush has no BrushMeshInstance set"); return(false); } if (!brushMesh.Set(vertices, halfEdges, polygons)) { Debug.LogWarning("GenerateMesh failed"); return(false); } var brushMeshIndex = brushMeshInstanceID - 1; if (ChiselMeshLookup.Value.brushMeshBlobs.TryGetValue(brushMeshIndex, out BlobAssetReference <BrushMeshBlob> item)) { ChiselMeshLookup.Value.brushMeshBlobs.Remove(brushMeshIndex); if (item.IsCreated) { item.Dispose(); } } ChiselMeshLookup.Value.brushMeshBlobs[brushMeshIndex] = BrushMeshBlob.Build(brushMesh); Profiler.BeginSample("BrushMeshBlob.Build"); CSGManager.NotifyBrushMeshModified(brushMeshInstanceID); Profiler.EndSample(); return(true); }
public BrushMesh(BrushMesh other) { if (other.vertices != null) { vertices = new Vector3[other.vertices.Length]; Array.Copy(other.vertices, this.vertices, other.vertices.Length); } if (other.halfEdges != null) { halfEdges = new HalfEdge[other.halfEdges.Length]; Array.Copy(other.halfEdges, this.halfEdges, other.halfEdges.Length); } if (other.polygons != null) { polygons = new Polygon[other.polygons.Length]; Array.Copy(other.polygons, this.polygons, other.polygons.Length); } }
private static Int32 CreateBrushMesh(int userID, BrushMesh brushMesh) { if (brushMesh == null || brushMesh.vertices == null || brushMesh.halfEdges == null || brushMesh.polygons == null) { return(0); } var edgeCount = brushMesh.halfEdges.Length; if (edgeCount < 12) { return(0); } var polygonCount = brushMesh.polygons.Length; if (polygonCount < 4) { return(0); } var vertexCount = brushMesh.vertices.Length; if (vertexCount < 4) { return(0); } var result = CreateBrushMesh(userID, brushMesh.vertices, brushMesh.halfEdges, brushMesh.polygons); if (result <= 0) { result = 0; } return(result); }
public static bool GenerateStadium(ref BrushMesh brushMesh, ref ChiselStadiumDefinition definition) { definition.Validate(); Vector3[] vertices = null; if (!GenerateStadiumVertices(definition, ref vertices)) { brushMesh.Clear(); return(false); } var surfaceIndices = new int[vertices.Length + 2]; if (!BrushMeshFactory.CreateExtrudedSubMesh(ref brushMesh, definition.sides, surfaceIndices, 0, 1, vertices, definition.surfaceDefinition)) { brushMesh.Clear(); return(false); } return(true); }
public static Int32 CreateBrushMesh(Int32 userID, float3[] vertices, BrushMesh.HalfEdge[] halfEdges, BrushMesh.Polygon[] polygons) { int brushMeshID = CreateBrushMeshID(userID); BrushMesh brushMesh = GetBrushMesh(brushMeshID); if (brushMesh == null) { Debug.LogWarning("brushMesh == nullptr"); DestroyBrushMesh(brushMeshID); return(BrushMeshInstance.InvalidInstanceID); } if (!brushMesh.Set(vertices, halfEdges, polygons)) { Debug.LogWarning("GenerateMesh failed"); DestroyBrushMesh(brushMeshID); return(BrushMeshInstance.InvalidInstanceID); } var brushMeshIndex = brushMeshID - 1; if (ChiselMeshLookup.Value.brushMeshBlobs.TryGetValue(brushMeshIndex, out BlobAssetReference <BrushMeshBlob> item)) { ChiselMeshLookup.Value.brushMeshBlobs.Remove(brushMeshIndex); if (item.IsCreated) { item.Dispose(); } } ChiselMeshLookup.Value.brushMeshUpdateList.Add(brushMeshIndex); /* * Profiler.BeginSample("BrushMeshBlob.Build"); * ChiselMeshLookup.Value.brushMeshBlobs[brushMeshIndex] = BrushMeshBlob.Build(brushMesh); * Profiler.EndSample();*/ return(brushMeshID); }
private static bool UpdateBrushMesh(Int32 brushMeshIndex, BrushMesh brushMesh) { if (brushMeshIndex == 0 || brushMesh.vertices == null || brushMesh.halfEdges == null || brushMesh.polygons == null) { return(false); } var edgeCount = brushMesh.halfEdges.Length; if (edgeCount < 12) { return(false); } var polygonCount = brushMesh.polygons.Length; if (polygonCount < 5) { return(false); } var vertexCount = brushMesh.vertices.Length; #if USE_MANAGED_CSG_IMPLEMENTATION var result = UpdateBrushMesh(brushMeshIndex, brushMesh.vertices, brushMesh.halfEdges, brushMesh.polygons); #else var result = UpdateBrushMesh(brushMeshIndex, vertexCount, brushMesh.vertices, edgeCount, brushMesh.halfEdges, polygonCount, brushMesh.polygons); #endif return(result); }
private static bool UpdateBrushMesh(Int32 brushMeshID, BrushMesh brushMesh, bool notifyBrushMeshModified = true) { if (brushMeshID == 0 || brushMesh.vertices == null || brushMesh.halfEdges == null || brushMesh.polygons == null) { return(false); } var edgeCount = brushMesh.halfEdges.Length; if (edgeCount < 12) { return(false); } var polygonCount = brushMesh.polygons.Length; if (polygonCount < 4) { return(false); } var result = UpdateBrushMesh(brushMeshID, brushMesh.vertices, brushMesh.halfEdges, brushMesh.polygons); if (notifyBrushMeshModified) { Profiler.BeginSample("CSGManager.NotifyBrushMeshModified"); CSGManager.NotifyBrushMeshModified(brushMeshID); Profiler.EndSample(); } return(result); }
public static Int32 CreateBrushMesh(Int32 userID, Vector3[] vertices, BrushMesh.HalfEdge[] halfEdges, BrushMesh.Polygon[] polygons) { int brushMeshID = CreateBrushMeshID(userID); BrushMesh brushMesh = GetBrushMesh(brushMeshID); if (brushMesh == null) { Debug.LogWarning("brushMesh == nullptr"); DestroyBrushMesh(brushMeshID); return(BrushMeshInstance.InvalidInstanceID); } if (!brushMesh.Set(vertices, halfEdges, polygons)) { Debug.LogWarning("GenerateMesh failed"); DestroyBrushMesh(brushMeshID); return(BrushMeshInstance.InvalidInstanceID); } return(brushMeshID); }
public unsafe static BlobAssetReference <BrushMeshBlob> Build(BrushMesh brushMesh) { if (brushMesh == null || brushMesh.vertices.Length < 4 || brushMesh.polygons.Length < 4 || brushMesh.halfEdges.Length < 12) { return(BlobAssetReference <BrushMeshBlob> .Null); } var srcVertices = brushMesh.vertices; //var srcPlanes = brushMesh.planes; var totalPolygonSize = 16 + (brushMesh.polygons.Length * UnsafeUtility.SizeOf <Polygon>()); var totalPlaneSize = 16 + (brushMesh.planes.Length * UnsafeUtility.SizeOf <float4>()); var totalPolygonIndicesSize = 16 + (brushMesh.halfEdgePolygonIndices.Length * UnsafeUtility.SizeOf <int>()); var totalHalfEdgeSize = 16 + (brushMesh.halfEdges.Length * UnsafeUtility.SizeOf <BrushMesh.HalfEdge>()); var totalVertexSize = 16 + (srcVertices.Length * UnsafeUtility.SizeOf <float3>()); var totalSize = totalPlaneSize + totalPolygonSize + totalPolygonIndicesSize + totalHalfEdgeSize + totalVertexSize; var builder = new BlobBuilder(Allocator.Temp, totalSize); ref var root = ref builder.ConstructRoot <BrushMeshBlob>();
public void Reset() { brushOutline = null; }
public static bool GenerateHemisphereSubMesh(ref BrushMesh brushMesh, Vector3 diameterXYZ, Matrix4x4 transform, int horzSegments, int vertSegments, in ChiselSurfaceDefinition surfaceDefinition)
// TODO: clean up public static bool GenerateSegmentedSubMesh(ref BrushMesh brushMesh, int horzSegments, int vertSegments, Vector3[] segmentVertices, bool topCap, bool bottomCap, int topVertex, int bottomVertex, in ChiselSurfaceDefinition surfaceDefinition)
public static bool GenerateRevolvedShape(ref ChiselBrushContainer brushContainer, ref ChiselRevolvedShapeDefinition definition) { definition.Validate(); var shapeVertices = new List <Vector2>(); var shapeSegmentIndices = new List <int>(); BrushMeshFactory.GetPathVertices(definition.shape, definition.curveSegments, shapeVertices, shapeSegmentIndices); Vector2[][] polygonVerticesArray; int[][] polygonIndicesArray; if (!Decomposition.ConvexPartition(shapeVertices, shapeSegmentIndices, out polygonVerticesArray, out polygonIndicesArray)) { return(false); } // TODO: splitting it before we do the composition would be better var polygonVerticesList = polygonVerticesArray.ToList(); for (int i = polygonVerticesList.Count - 1; i >= 0; i--) { SplitPolygon(polygonVerticesList, i); } var brushMeshesList = new List <BrushMesh>(); var horzSegments = definition.revolveSegments; //horizontalSegments; var horzDegreePerSegment = definition.totalAngle / horzSegments; // TODO: make this work when intersecting rotation axis // 1. split polygons along rotation axis // 2. if edge lies on rotation axis, make sure we don't create infinitely thin quad // collapse this quad, or prevent this from happening // TODO: share this code with torus generator for (int p = 0; p < polygonVerticesList.Count; p++) { var polygonVertices = polygonVerticesList[p]; // var segmentIndices = polygonIndicesArray[p]; var shapeSegments = polygonVertices.Length; var vertSegments = polygonVertices.Length; var descriptionIndex = new int[2 + vertSegments]; descriptionIndex[0] = 0; descriptionIndex[1] = 1; for (int v = 0; v < vertSegments; v++) { descriptionIndex[v + 2] = 2; } var horzOffset = definition.startAngle; for (int h = 1, pr = 0; h < horzSegments + 1; pr = h, h++) { var hDegree0 = (pr * horzDegreePerSegment) + horzOffset; var hDegree1 = (h * horzDegreePerSegment) + horzOffset; var rotation0 = quaternion.AxisAngle(Vector3.forward, hDegree0); var rotation1 = quaternion.AxisAngle(Vector3.forward, hDegree1); var subMeshVertices = new Vector3[vertSegments * 2]; for (int v = 0; v < vertSegments; v++) { subMeshVertices[v + vertSegments] = math.mul(rotation0, new Vector3(polygonVertices[v].x, 0, polygonVertices[v].y)); subMeshVertices[v] = math.mul(rotation1, new Vector3(polygonVertices[v].x, 0, polygonVertices[v].y)); } var brushMesh = new BrushMesh(); if (!BrushMeshFactory.CreateExtrudedSubMesh(ref brushMesh, vertSegments, descriptionIndex, 0, 1, subMeshVertices, in definition.surfaceDefinition)) { continue; } if (!brushMesh.Validate()) { return(false); } brushMeshesList.Add(brushMesh); } } brushContainer.CopyFrom(brushMeshesList); return(true); }
/// <summary>Update this <see cref="Chisel.Core.BrushMeshInstance"/> with the given <see cref="Chisel.Core.BrushMesh"/>.</summary> /// <param name="brushMesh">The <see cref="Chisel.Core.BrushMesh"/> to update the <see cref="Chisel.Core.BrushMeshInstance"/> with</param> /// <returns><b>true</b> on success, <b>false</b> on failure. In case of failure the brush will keep using the previously set <see cref="Chisel.Core.BrushMesh"/>.</returns> public bool Set(BrushMesh brushMesh) { return(UpdateBrushMesh(brushMeshID, brushMesh)); }
/// <summary>Create a <see cref="Chisel.Core.BrushMeshInstance"/> from a given <see cref="Chisel.Core.BrushMesh"/></summary> /// <param name="brushMesh">The <see cref="Chisel.Core.BrushMesh"/> to create an instance with</param> /// <returns>A newly created <see cref="Chisel.Core.BrushMeshInstance"/> on success, or an invalid <see cref="Chisel.Core.BrushMeshInstance"/> on failure.</returns> public static BrushMeshInstance Create(BrushMesh brushMesh, Int32 userID = 0) { return(new BrushMeshInstance { brushMeshID = CreateBrushMesh(userID, brushMesh) }); }
public static bool GenerateBox(ref BrushMesh brushMesh, UnityEngine.Vector3 min, UnityEngine.Vector3 max, in ChiselSurfaceDefinition surfaceDefinition)