public static bool GenerateHemisphereVertices(ref ChiselHemisphereDefinition definition, ref Vector3[] vertices) { definition.Validate(); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); return(GenerateHemisphereVertices(definition.diameterXYZ, transform, definition.horizontalSegments, definition.verticalSegments, ref vertices)); }
public static bool GenerateSphere(ref BrushMesh brushMesh, ref ChiselSphereDefinition definition) { definition.Validate(); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); return(BrushMeshFactory.GenerateSphere(ref brushMesh, definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceDefinition)); }
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 static bool GenerateSphereSubMesh(CSGBrushSubMesh subMesh, CSGSphereDefinition definition) { definition.Validate(); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); return(GenerateSphereSubMesh(subMesh, definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, transform, definition.horizontalSegments, definition.verticalSegments, definition.surfaceAssets, definition.surfaceDescriptions)); }
// TODO: could probably figure out "inverse" from direction of topY compared to bottomY public static Vector3[] GetConeFrustumVertices(CSGCircleDefinition definition, float topHeight, float rotation, int segments, ref Vector3[] vertices, bool inverse = false) { var rotate = Quaternion.AngleAxis(rotation, Vector3.up); var bottomAxisX = rotate * Vector3.right * definition.diameterX * 0.5f; var bottomAxisZ = rotate * Vector3.forward * definition.diameterZ * 0.5f; var topY = Vector3.up * topHeight; var bottomY = Vector3.up * definition.height; if (vertices == null || vertices.Length != segments + 1) { vertices = new Vector3[segments + 1]; } float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f); vertices[0] = topY; for (int v = 0; v < segments; v++) { var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad; var s = Mathf.Sin(r); var c = Mathf.Cos(r); var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s); bottomVertex += bottomY; var vi = inverse ? (segments - v) : (v + 1); vertices[vi] = bottomVertex; } return(vertices); }
public static bool GenerateSphereVertices(CSGSphereDefinition definition, ref Vector3[] vertices) { definition.Validate(); var transform = Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(definition.rotation, Vector3.up), Vector3.one); BrushMeshFactory.CreateSphereVertices(definition.diameterXYZ, definition.offsetY, definition.generateFromCenter, definition.horizontalSegments, definition.verticalSegments, ref vertices); return(true); }
public static Vector3[] GetConicalFrustumVertices(CSGCircleDefinition bottom, CSGCircleDefinition top, float rotation, int segments, ref Vector3[] vertices) { if (top.height > bottom.height) { var temp = top; top = bottom; bottom = temp; } var rotate = Quaternion.AngleAxis(rotation, Vector3.up); var topAxisX = rotate * Vector3.right * top.diameterX * 0.5f; var topAxisZ = rotate * Vector3.forward * top.diameterZ * 0.5f; var bottomAxisX = rotate * Vector3.right * bottom.diameterX * 0.5f; var bottomAxisZ = rotate * Vector3.forward * bottom.diameterZ * 0.5f; var topY = Vector3.up * top.height; var bottomY = Vector3.up * bottom.height; // TODO: handle situation where diameterX & diameterZ are 0 (only create one vertex) if (vertices == null || vertices.Length != segments * 2) { vertices = new Vector3[segments * 2]; } float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f); for (int v = 0; v < segments; v++) { var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad; var s = Mathf.Sin(r); var c = Mathf.Cos(r); var topVertex = (topAxisX * c) + (topAxisZ * s); var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s); topVertex += topY; bottomVertex += bottomY; vertices[v] = topVertex; vertices[v + segments] = bottomVertex; } return(vertices); }
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.AngleAxis(hDegree0, Vector3.forward); var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.forward); var subMeshVertices = new Vector3[vertSegments * 2]; for (int v = 0; v < vertSegments; v++) { subMeshVertices[v + vertSegments] = rotation0 * new Vector3(polygonVertices[v].x, 0, polygonVertices[v].y); subMeshVertices[v] = 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); }
public void Update(IChiselHandles handles, ChiselCylinderDefinition definition) { var tempBottomDiameterX = definition.BottomDiameterX; var tempBottomDiameterZ = definition.isEllipsoid ? definition.BottomDiameterZ : definition.BottomDiameterX; float tempTopDiameterX, tempTopDiameterZ; if (definition.type == CylinderShapeType.Cone) { tempTopDiameterX = 0; tempTopDiameterZ = 0; } else if (definition.type == CylinderShapeType.Cylinder) { tempTopDiameterX = tempBottomDiameterX; tempTopDiameterZ = tempBottomDiameterZ; } else { tempTopDiameterX = definition.TopDiameterX; tempTopDiameterZ = definition.isEllipsoid ? definition.TopDiameterZ : definition.TopDiameterX; } topY = (definition.height + definition.bottomOffset); bottomY = definition.bottomOffset; var rotate = Quaternion.AngleAxis(definition.rotation, Vector3.up); topXVector = rotate * Vector3.right * tempTopDiameterX * 0.5f; topZVector = rotate * Vector3.forward * tempTopDiameterZ * 0.5f; bottomXVector = rotate * Vector3.right * tempBottomDiameterX * 0.5f; bottomZVector = rotate * Vector3.forward * tempBottomDiameterZ * 0.5f; normal = Vector3.up; if (topY < bottomY) { normal = -Vector3.up; } else { normal = Vector3.up; } topPoint = normal * topY; bottomPoint = normal * bottomY; // Render vertical horizon of cylinder // TODO: make this work with math instead of "finding" it Vector3 bottomPointA, topPointA; Vector3 bottomPointB, topPointB; var camera = UnityEngine.Camera.current; var cameraTransform = camera.transform; var cameraPosition = handles.inverseMatrix.MultiplyPoint(cameraTransform.position); const float degreeStep = 5; var pointA = fullTopCircleHandle.GetPointAtDegree(360 - degreeStep); var pointB = fullBottomCircleHandle.GetPointAtDegree(360 - degreeStep); var camOrtho = camera.orthographic; var camForward = handles.inverseMatrix.MultiplyVector(cameraTransform.forward).normalized; var camDir = camOrtho ? camForward : (pointA - cameraPosition).normalized; var delta = (pointA - pointB).normalized; var normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized; var prevDot = Vector3.Dot(normal3, camDir) < 0; bool renderHorizon = false; //* bottomPointA = Vector3.zero; topPointA = Vector3.zero; bottomPointB = Vector3.zero; topPointB = Vector3.zero; var lineCount = 0; for (float degree = 0; degree < 360; degree += degreeStep) { pointA = fullTopCircleHandle.GetPointAtDegree(degree); pointB = fullBottomCircleHandle.GetPointAtDegree(degree); delta = (pointA - pointB).normalized; normal3 = -Vector3.Cross(delta, Vector3.Cross((pointB - bottomPoint).normalized, delta)).normalized; camDir = camOrtho ? camForward : (pointB - cameraPosition).normalized; var currDot = Vector3.Dot(normal3, camDir) < 0; if (prevDot != currDot) { lineCount++; if (lineCount == 1) { topPointA = pointA; bottomPointA = pointB; } else //if (lineCount == 2) { topPointB = pointA; bottomPointB = pointB; renderHorizon = true; break; } } prevDot = currDot; } #if false { var pointC = (Vector3.right * (definition.topDiameterX * 0.5f)) + (Vector3.up * (definition.height + definition.bottomOffset)); var pointD = (Vector3.right * (definition.bottomDiameterX * 0.5f)) + (Vector3.up * definition.bottomOffset); //var deltar = (pointC - pointD).normalized; //var normala = -Vector3.Cross(Vector3.forward, deltar).normalized; var DT = (cameraPosition - topPoint); var DB = (cameraPosition - bottomPoint); var DmT = DT.magnitude; var DmB = DB.magnitude; //var Dv = D / Dm; var RmT = definition.topDiameterX * 0.5f; var RmB = definition.bottomDiameterX * 0.5f; var cosAT = RmT / DmT; var cosAB = RmB / DmB; var AT = Mathf.Acos(cosAT) * Mathf.Rad2Deg; var AB = Mathf.Acos(cosAB) * Mathf.Rad2Deg; var RvT = (Quaternion.AngleAxis(AT, Vector3.up) * DT).normalized; var RvB = (Quaternion.AngleAxis(AB, Vector3.up) * DB).normalized; //var R = Rv * Rm; var angleT = Vector3.SignedAngle(Vector3.right, RvT, Vector3.up); var angleB = Vector3.SignedAngle(Vector3.right, RvB, Vector3.up); var arotationT = Quaternion.AngleAxis(angleT, Vector3.up); var arotationB = Quaternion.AngleAxis(angleB, Vector3.up); var ptA = arotationT * pointC; var ptB = arotationB * pointD; var prevCol = handles.color; handles.color = UnityEngine.Color.red; handles.DrawLine(bottomPoint, bottomPoint + Vector3.right); //handles.DrawLine(bottomPoint, bottomPoint + Vector3.forward); //handles.DrawLine(bottomPoint, bottomPoint + normala); //handles.DrawLine(bottomPoint, bottomPoint + deltar); //handles.DrawLine(bottomPoint, bottomPoint + R); handles.DrawLine(bottomPoint, bottomPoint + RvT); handles.DrawLine(bottomPoint, bottomPoint + RvB); //handles.DrawLine(bottomPoint, bottomPoint + desired); handles.DrawLine(ptA, ptB); handles.color = prevCol; } #endif /*/ * if (camera.orthographic) * { * { * var radius = definition.bottomDiameterX * 0.5f; * var center = bottomPoint; * bottomPointA = center + (cameraTransform.right * radius); * bottomPointB = center - (cameraTransform.right * radius); * } * { * var radius = definition.topDiameterX * 0.5f; * var center = topPoint; * topPointA = center + (cameraTransform.right * radius); * topPointB = center - (cameraTransform.right * radius); * } * } else * { * var handleMatrix = handles.matrix; * renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.bottomDiameterX, bottomPoint, -normal, out bottomPointB, out bottomPointA); * renderHorizon = GeometryMath.FindCircleHorizon(handleMatrix, definition.topDiameterX, topPoint, normal, out topPointA, out topPointB) && renderHorizon; * * if (renderHorizon && definition.bottomDiameterX != definition.topDiameterX) * { * renderHorizon = !(GeometryMath.PointInCameraCircle(handleMatrix, bottomPointA, definition.topDiameterX, topPoint, normal) || * GeometryMath.PointInCameraCircle(handleMatrix, topPointA, definition.bottomDiameterX, bottomPoint, -normal) || * GeometryMath.PointInCameraCircle(handleMatrix, bottomPointB, definition.topDiameterX, topPoint, normal) || * GeometryMath.PointInCameraCircle(handleMatrix, topPointB, definition.bottomDiameterX, bottomPoint, -normal)); * } * } * //*/ if (!renderHorizon) { bottomPointA = Vector3.zero; topPointA = Vector3.zero; bottomPointB = Vector3.zero; topPointB = Vector3.zero; } verticalHandle1.From = bottomPointA; verticalHandle1.To = topPointA; verticalHandle2.From = bottomPointB; verticalHandle2.To = topPointB; fullTopCircleHandle.Center = topPoint; fullBottomCircleHandle.Center = bottomPoint; fullTopCircleHandle.DiameterX = tempTopDiameterX; fullTopCircleHandle.DiameterZ = tempTopDiameterZ; fullBottomCircleHandle.DiameterX = tempBottomDiameterX; fullBottomCircleHandle.DiameterZ = tempBottomDiameterZ; topHandle.Origin = topPoint; bottomHandle.Origin = bottomPoint; fullTopCircleHandle.Normal = normal; fullBottomCircleHandle.Normal = -normal; topHandle.Normal = normal; bottomHandle.Normal = -normal; if (definition.isEllipsoid) { if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 4) { bottomRadiusHandles = new IChiselEllipsoidHandle[] { handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f, angles: 90), // left handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: +45f + 180f, angles: 90), // right handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f, angles: 90), // forward handles.CreateEllipsoidHandle(Vector3.zero, -normal, 0, 0, startAngle: -45f + 180f, angles: 90), // back }; } if (topRadiusHandles == null || topRadiusHandles.Length != 4) { topRadiusHandles = new IChiselEllipsoidHandle[] { handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f, angles: 90), // left handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: +45f + 180f, angles: 90), // right handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f, angles: 90), // forward handles.CreateEllipsoidHandle(Vector3.zero, normal, 0, 0, startAngle: -45f + 180f, angles: 90), // back }; } for (int i = 0; i < bottomRadiusHandles.Length; i++) { bottomRadiusHandles[i].Center = bottomPoint; bottomRadiusHandles[i].Normal = -normal; bottomRadiusHandles[i].DiameterX = tempBottomDiameterX; bottomRadiusHandles[i].DiameterZ = tempBottomDiameterZ; bottomRadiusHandles[i].Rotation = definition.rotation; } for (int i = 0; i < topRadiusHandles.Length; i++) { topRadiusHandles[i].Center = topPoint; topRadiusHandles[i].Normal = normal; topRadiusHandles[i].DiameterX = tempTopDiameterX; topRadiusHandles[i].DiameterZ = tempTopDiameterZ; topRadiusHandles[i].Rotation = definition.rotation; } if (bottomHandles == null || bottomHandles.Length != 4) { bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0], bottomRadiusHandles[1], bottomRadiusHandles[2], bottomRadiusHandles[3] } } ; if (definition.type != CylinderShapeType.Cone) { if (topHandles == null || topHandles.Length != 5) { topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0], topRadiusHandles[1], topRadiusHandles[2], topRadiusHandles[3] } } ; } else { if (topHandles == null || topHandles.Length != 1) { topHandles = new IChiselHandle[] { topHandle } } ; } } else { if (bottomRadiusHandles == null || bottomRadiusHandles.Length != 1) { bottomRadiusHandles = new IChiselEllipsoidHandle[] { fullBottomCircleHandle } } ; if (topRadiusHandles == null || topRadiusHandles.Length != 1) { topRadiusHandles = new IChiselEllipsoidHandle[] { fullTopCircleHandle } } ; if (bottomHandles == null || bottomHandles.Length != 2) { bottomHandles = new IChiselHandle[] { bottomHandle, bottomRadiusHandles[0] } } ; if (definition.type != CylinderShapeType.Cone) { if (topHandles == null || topHandles.Length != 2) { topHandles = new IChiselHandle[] { topHandle, topRadiusHandles[0] } } ; } else { if (topHandles == null || topHandles.Length != 1) { topHandles = new IChiselHandle[] { topHandle } } ; } } } }
public static bool GenerateTorusAsset(CSGBrushMeshAsset brushMeshAsset, CSGTorusDefinition definition) { Vector3[] vertices = null; if (!GenerateTorusVertices(definition, ref vertices)) { brushMeshAsset.Clear(); return(false); } definition.Validate(); var surfaces = definition.surfaceAssets; var descriptions = definition.surfaceDescriptions; 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; var horzDegreePerSegment = (definition.totalAngle / horzSegments); var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad; var descriptionIndex = new int[2 + vertSegments]; descriptionIndex[0] = 0; descriptionIndex[1] = 1; var circleVertices = new Vector2[vertSegments]; var min = new Vector2(float.PositiveInfinity, float.PositiveInfinity); var max = new Vector2(float.NegativeInfinity, float.NegativeInfinity); var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad; for (int v = 0; v < vertSegments; v++) { var vRad = tubeAngleOffset + (v * vertDegreePerSegment); circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius, (Mathf.Sin(vRad) * tubeRadiusY)); min.x = Mathf.Min(min.x, circleVertices[v].x); min.y = Mathf.Min(min.y, circleVertices[v].y); max.x = Mathf.Max(max.x, circleVertices[v].x); max.y = Mathf.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 subMeshes = new CSGBrushSubMesh[horzSegments]; 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.AngleAxis(hDegree0, Vector3.up); var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.up); var subMeshVertices = new Vector3[vertSegments * 2]; for (int v = 0; v < vertSegments; v++) { subMeshVertices[v + vertSegments] = rotation0 * circleVertices[v]; subMeshVertices[v] = rotation1 * circleVertices[v]; } var subMesh = new CSGBrushSubMesh(); CreateExtrudedSubMesh(subMesh, vertSegments, descriptionIndex, descriptionIndex, 0, 1, subMeshVertices, surfaces, descriptions); if (!subMesh.Validate()) { brushMeshAsset.Clear(); return(false); } subMeshes[h - 1] = subMesh; } brushMeshAsset.SubMeshes = subMeshes; brushMeshAsset.CalculatePlanes(); brushMeshAsset.SetDirty(); return(true); }
public static bool GenerateTorusVertices(CSGTorusDefinition definition, ref Vector3[] vertices) { definition.Validate(); //var surfaces = definition.surfaceAssets; //var descriptions = definition.surfaceDescriptions; 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; var horzDegreePerSegment = (definition.totalAngle / horzSegments); var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad; var circleVertices = new Vector2[vertSegments]; var min = new Vector2(float.PositiveInfinity, float.PositiveInfinity); var max = new Vector2(float.NegativeInfinity, float.NegativeInfinity); var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad; for (int v = 0; v < vertSegments; v++) { var vRad = tubeAngleOffset + (v * vertDegreePerSegment); circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius, (Mathf.Sin(vRad) * tubeRadiusY)); min.x = Mathf.Min(min.x, circleVertices[v].x); min.y = Mathf.Min(min.y, circleVertices[v].y); max.x = Mathf.Max(max.x, circleVertices[v].x); max.y = Mathf.Max(max.y, circleVertices[v].y); } 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; } } if (definition.totalAngle != 360) { horzSegments++; } var horzOffset = definition.startAngle; var vertexCount = vertSegments * horzSegments; if (vertices == null || vertices.Length != vertexCount) { vertices = new Vector3[vertexCount]; } for (int h = 0, v = 0; h < horzSegments; h++) { var hDegree1 = (h * horzDegreePerSegment) + horzOffset; var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.up); for (int i = 0; i < vertSegments; i++, v++) { vertices[v] = rotation1 * circleVertices[i]; } } return(true); }