public static bool GenerateCapsule(ref ChiselBrushContainer brushContainer, ref ChiselCapsuleDefinition definition) { definition.Validate(); Vector3[] vertices = null; if (!BrushMeshFactory.GenerateCapsuleVertices(ref definition, ref vertices)) { 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; brushContainer.EnsureSize(1); return(BrushMeshFactory.GenerateSegmentedSubMesh(ref brushContainer.brushMeshes[0], sides, segments, vertices, topCap, bottomCap, topVertex, bottomVertex, definition.surfaceDefinition)); }
public bool Generate(ref ChiselBrushContainer brushContainer) { if (!IsValid) { return(false); } brushContainer.EnsureSize(1); brushContainer.brushMeshes[0] = new BrushMesh(brushOutline); brushContainer.brushMeshes[0].CalculatePlanes(); // Detect if outline is inside-out and if so, just invert all polygons. isInsideOut = brushContainer.brushMeshes[0].IsInsideOut(); if (isInsideOut) { brushContainer.brushMeshes[0].Invert(); } // Split non planar polygons into convex pieces brushContainer.brushMeshes[0].SplitNonPlanarPolygons(); return(brushContainer.brushMeshes[0].Validate()); }
public static bool GenerateHemisphere(ref ChiselBrushContainer brushContainer, ref ChiselHemisphereDefinition definition) { definition.Validate(); brushContainer.EnsureSize(1); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); return GenerateHemisphereSubMesh(ref brushContainer.brushMeshes[0], definition.diameterXYZ, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition); }
public static bool GenerateSphere(ref ChiselBrushContainer brushContainer, ref ChiselSphereDefinition definition) { definition.Validate(); brushContainer.EnsureSize(1); var transform = float4x4.TRS(Vector3.zero, quaternion.AxisAngle(new Vector3(0, 1, 0), definition.rotation), Vector3.one); return(BrushMeshFactory.GenerateSphere(ref brushContainer.brushMeshes[0], definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition)); }
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(); } }
public static bool GenerateStadium(ref ChiselBrushContainer brushContainer, ref ChiselStadiumDefinition definition) { definition.Validate(); Vector3[] vertices = null; if (!GenerateStadiumVertices(definition, ref vertices)) { return(false); } brushContainer.EnsureSize(1); var surfaceIndices = new int[vertices.Length + 2]; return(BrushMeshFactory.CreateExtrudedSubMesh(ref brushContainer.brushMeshes[0], definition.sides, surfaceIndices, 0, 1, vertices, definition.surfaceDefinition)); }
public static bool GenerateBox(ref ChiselBrushContainer brushContainer, ref ChiselBoxDefinition definition) { definition.Validate(); var min = definition.min; var max = definition.max; if (!BoundsExtensions.IsValid(min, max)) { return(false); } brushContainer.EnsureSize(1); return(GenerateBox(ref brushContainer.brushMeshes[0], definition.min, definition.max, definition.surfaceDefinition)); }
public static bool GenerateLinearStairs(ref ChiselBrushContainer brushContainer, ref ChiselLinearStairsDefinition definition) { definition.Validate(); int requiredSubMeshCount = BrushMeshFactory.GetLinearStairsSubMeshCount(definition, definition.leftSide, definition.rightSide); if (requiredSubMeshCount == 0) { return(false); } int subMeshOffset = 0; brushContainer.EnsureSize(requiredSubMeshCount); return(GenerateLinearStairsSubMeshes(ref brushContainer, definition, definition.leftSide, definition.rightSide, subMeshOffset)); }
public static bool GenerateCylinder(ref ChiselBrushContainer brushContainer, ref ChiselCylinderDefinition definition) { definition.Validate(); var tempTop = definition.top; var tempBottom = definition.bottom; if (!definition.isEllipsoid) { tempTop.diameterZ = tempTop.diameterX; tempBottom.diameterZ = tempBottom.diameterX; } brushContainer.EnsureSize(1); bool result = false; switch (definition.type) { case CylinderShapeType.Cylinder: result = BrushMeshFactory.GenerateCylinder(ref brushContainer.brushMeshes[0], tempBottom, tempTop.height, definition.rotation, definition.sides, in definition.surfaceDefinition); break;
public static bool GeneratePathedStairs(ref ChiselBrushContainer brushContainer, ref ChiselPathedStairsDefinition definition) { definition.Validate(); var shapeVertices = new List <Vector2>(); var shapeSegmentIndices = new List <int>(); GetPathVertices(definition.shape, definition.curveSegments, shapeVertices, shapeSegmentIndices); var totalSubMeshCount = 0; for (int i = 0; i < shapeVertices.Count; i++) { if (i == 0 && !definition.shape.closed) { continue; } var leftSide = (!definition.shape.closed && i == 1) ? definition.stairs.leftSide : StairsSideType.None; var rightSide = (!definition.shape.closed && i == shapeVertices.Count - 1) ? definition.stairs.rightSide : StairsSideType.None; totalSubMeshCount += BrushMeshFactory.GetLinearStairsSubMeshCount(definition.stairs, leftSide, rightSide); } if (totalSubMeshCount == 0) { return(false); } // var stairDirections = definition.shape.closed ? shapeVertices.Count : (shapeVertices.Count - 1); brushContainer.EnsureSize(totalSubMeshCount); var depth = definition.stairs.depth; var height = definition.stairs.height; var halfDepth = depth * 0.5f; var halfHeight = height * 0.5f; int subMeshIndex = 0; for (int vi0 = shapeVertices.Count - 3, vi1 = shapeVertices.Count - 2, vi2 = shapeVertices.Count - 1, vi3 = 0; vi3 < shapeVertices.Count; vi0 = vi1, vi1 = vi2, vi2 = vi3, vi3++) { if (vi2 == 0 && !definition.shape.closed) { continue; } // TODO: optimize this, we're probably redoing a lot of stuff for every iteration var v0 = shapeVertices[vi0]; var v1 = shapeVertices[vi1]; var v2 = shapeVertices[vi2]; var v3 = shapeVertices[vi3]; var m0 = (v0 + v1) * 0.5f; var m1 = (v1 + v2) * 0.5f; var m2 = (v2 + v3) * 0.5f; var d0 = (v1 - v0); var d1 = (v2 - v1); var d2 = (v3 - v2); var maxWidth0 = d0.magnitude; var maxWidth1 = d1.magnitude; var maxWidth2 = d2.magnitude; var halfWidth1 = d1 * 0.5f; d0 /= maxWidth0; d1 /= maxWidth1; d2 /= maxWidth2; var depthVector = new Vector3(d1.y, 0, -d1.x); var lineCenter = new Vector3(m1.x, halfHeight, m1.y) - (depthVector * halfDepth); var depthVector0 = new Vector2(d0.y, -d0.x) * depth; var depthVector1 = new Vector2(d1.y, -d1.x) * depth; var depthVector2 = new Vector2(d2.y, -d2.x) * depth; m0 -= depthVector0; m1 -= depthVector1; m2 -= depthVector2; Vector2 output; var leftShear = Intersect(m1, d1, m0, d0, out output) ? Vector2.Dot(d1, (output - (m1 - halfWidth1))) : 0; var rightShear = Intersect(m1, d1, m2, d2, out output) ? -Vector2.Dot(d1, (output - (m1 + halfWidth1))) : 0; var transform = Matrix4x4.TRS(lineCenter, // move to center of line Quaternion.LookRotation(depthVector, Vector3.up), // rotate to align with line Vector3.one); // set the width to the width of the line definition.stairs.width = maxWidth1; definition.stairs.nosingWidth = 0; var leftSide = (!definition.shape.closed && vi2 == 1) ? definition.stairs.leftSide : StairsSideType.None; var rightSide = (!definition.shape.closed && vi2 == shapeVertices.Count - 1) ? definition.stairs.rightSide : StairsSideType.None; var subMeshCount = BrushMeshFactory.GetLinearStairsSubMeshCount(definition.stairs, leftSide, rightSide); if (subMeshCount == 0) { continue; } if (!BrushMeshFactory.GenerateLinearStairsSubMeshes(ref brushContainer, definition.stairs, leftSide, rightSide, subMeshIndex)) { return(false); } var halfWidth = maxWidth1 * 0.5f; for (int m = 0; m < subMeshCount; m++) { var vertices = brushContainer.brushMeshes[subMeshIndex + m].vertices; for (int v = 0; v < vertices.Length; v++) { // TODO: is it possible to put all of this in a single matrix? // lerp the stairs to go from less wide to wider depending on the depth of the vertex var depthFactor = 1.0f - ((vertices[v].z / definition.stairs.depth) + 0.5f); var wideFactor = (vertices[v].x / halfWidth) + 0.5f; var scale = (vertices[v].x / halfWidth); // lerp the stairs width depending on if it's on the left or right side of the stairs vertices[v].x = Mathf.Lerp(scale * (halfWidth - (rightShear * depthFactor)), scale * (halfWidth - (leftShear * depthFactor)), wideFactor); vertices[v] = transform.MultiplyPoint(vertices[v]); } } subMeshIndex += subMeshCount; } return(false); }
public static bool GenerateTorus(ref ChiselBrushContainer brushContainer, ref ChiselTorusDefinition definition) { definition.Validate(); Vector3[] vertices = null; if (!GenerateTorusVertices(definition, ref vertices)) { return(false); } var tubeRadiusX = (definition.tubeWidth * 0.5f); var tubeRadiusY = (definition.tubeHeight * 0.5f); var torusRadius = (definition.outerDiameter * 0.5f) - tubeRadiusX; var horzSegments = definition.horizontalSegments; var vertSegments = definition.verticalSegments; brushContainer.EnsureSize(horzSegments); var horzDegreePerSegment = (definition.totalAngle / horzSegments); var vertDegreePerSegment = math.radians(360.0f / vertSegments); var descriptionIndex = new int[2 + vertSegments]; descriptionIndex[0] = 0; descriptionIndex[1] = 1; var circleVertices = new Vector3[vertSegments]; var min = new float2(float.PositiveInfinity, float.PositiveInfinity); var max = new float2(float.NegativeInfinity, float.NegativeInfinity); var tubeAngleOffset = math.radians((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation); for (int v = 0; v < vertSegments; v++) { var vRad = tubeAngleOffset + (v * vertDegreePerSegment); circleVertices[v] = new Vector3((math.cos(vRad) * tubeRadiusX) - torusRadius, (math.sin(vRad) * tubeRadiusY), 0); min.x = math.min(min.x, circleVertices[v].x); min.y = math.min(min.y, circleVertices[v].y); max.x = math.max(max.x, circleVertices[v].x); max.y = math.max(max.y, circleVertices[v].y); descriptionIndex[v + 2] = 2; } if (definition.fitCircle) { var center = (max + min) * 0.5f; var size = (max - min) * 0.5f; size.x = tubeRadiusX / size.x; size.y = tubeRadiusY / size.y; for (int v = 0; v < vertSegments; v++) { circleVertices[v].x = (circleVertices[v].x - center.x) * size.x; circleVertices[v].y = (circleVertices[v].y - center.y) * size.y; circleVertices[v].x -= torusRadius; } } var horzOffset = definition.startAngle; for (int h = 1, p = 0; h < horzSegments + 1; p = h, h++) { var hDegree0 = (p * horzDegreePerSegment) + horzOffset; var hDegree1 = (h * horzDegreePerSegment) + horzOffset; var rotation0 = quaternion.AxisAngle(new Vector3(0, 1, 0), hDegree0); var rotation1 = quaternion.AxisAngle(new Vector3(0, 1, 0), hDegree1); var subMeshVertices = new Vector3[vertSegments * 2]; for (int v = 0; v < vertSegments; v++) { subMeshVertices[v + vertSegments] = math.mul(rotation0, circleVertices[v]); subMeshVertices[v] = math.mul(rotation1, circleVertices[v]); } var brushMesh = new BrushMesh(); BrushMeshFactory.CreateExtrudedSubMesh(ref brushMesh, vertSegments, descriptionIndex, 0, 1, subMeshVertices, in definition.surfaceDefinition); if (!brushMesh.Validate()) { return(false); } brushContainer.brushMeshes[h - 1] = brushMesh; } return(true); }