public static Csgjs CreateSphere(Vector3 center, Vector3 size, out List <CsgSurfaceSharedData> surfaces) { size *= 0.5f; float slices = 16; float stacks = 8; var polygons = new List <CsgPolygon>(); List <CsgVertex> vertices = null; void AddVertex(float theta, float phi) { Vector2 uvs = new Vector2(theta, phi); theta *= Mathf.Pi * 2; theta += Mathf.PiOverTwo; phi *= Mathf.Pi; var dir = new Vector3( Mathf.Cos(theta) * Mathf.Sin(phi), Mathf.Cos(phi), Mathf.Sin(theta) * Mathf.Sin(phi) ); vertices.Add(new CsgVertex(center + dir * size, dir, uvs)); } var sphereSurface = new CsgSurfaceSharedData("Sphere"); for (var i = 0; i < slices; i++) { for (var j = 0; j < stacks; j++) { vertices = new List <CsgVertex>(); AddVertex(i / slices, j / stacks); if (j > 0) { AddVertex((i + 1) / slices, j / stacks); } if (j < stacks - 1) { AddVertex((i + 1) / slices, (j + 1) / stacks); } AddVertex(i / slices, (j + 1) / stacks); polygons.Add(new CsgPolygon(vertices, sphereSurface)); } } surfaces = new List <CsgSurfaceSharedData>(1) { sphereSurface }; var csg = FromPolygons(polygons); // And set the shared data for (int i = 0; i < surfaces.Count; i++) { surfaces[i].Csgjs = csg; } return(csg); }
public CsgPolygon(List <CsgVertex> vertices, CsgSurfaceSharedData shared = null, CsgPlane plane = null) { Vertices = vertices; Shared = shared; Plane = plane?.Clone() ?? CsgPlane.FromPoints(vertices); }
public static Csgjs CreateCube(Vector3 center, Vector3 size, out List <CsgSurfaceSharedData> surfaces) { size *= 0.5f; Vector3[] normals = new[] { new Vector3(-1, 0, 0), new Vector3(+1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, +1, 0), new Vector3(0, 0, -1), new Vector3(0, 0, +1) }; string[] names = new[] { "Back", "Front", "Bottom", "Top", "Left", "Right" }; Vector2[] uvs = new[] { new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0), new Vector2(0, 1) }; int[][] faces = new[] { new int[] { 0, 4, 6, 2 }, new int[] { 5, 1, 3, 7 }, // new int[] { 0, 1, 5, 4 }, new int[] { 3, 2, 6, 7 }, // new int[] { 1, 0, 2, 3 }, // new int[] { 4, 5, 7, 6 }, }; var cubeSurfaces = new List <CsgSurfaceSharedData>(faces.Length); var polygons = faces .Select((face, index) => { var vertices = face.Select((i, j) => { Vector3 pos = center + size * new Vector3( 2 * (((i & 1) == 0) ? 0 : 1) - 1, 2 * (((i & 2) == 0) ? 0 : 1) - 1, 2 * (((i & 4) == 0) ? 0 : 1) - 1 ); return(new CsgVertex(pos, normals[index], uvs[j])); }).ToList(); var surface = new CsgSurfaceSharedData(names[index]); cubeSurfaces.Add(surface); return(new CsgPolygon(vertices, surface)); }) .ToList(); surfaces = cubeSurfaces; var csg = FromPolygons(polygons); // And set the shared data for (int i = 0; i < surfaces.Count; i++) { surfaces[i].Csgjs = csg; } return(csg); }
public static Csgjs CreateCylinder(Vector3 start, Vector3 end, Vector3 size, out List <CsgSurfaceSharedData> surfaces) { size *= 0.5f; // TODO: This does not entirely make sense for cylinders with arbitrary start and end coordinates start *= size.Y; end *= size.Y; Vector3 ray = end - start; float slices = 16; Vector3 axisZ = ray.Normalized; bool isY = (Mathf.Abs(axisZ.Y) > 0.5); Vector3 axisX = Vector3.Cross(new Vector3(isY ? 1 : 0, (!isY) ? 1 : 0, 0), axisZ).Normalized; Vector3 axisY = Vector3.Cross(axisX, axisZ).Normalized; Vector3 negatedAxisZ = axisZ; negatedAxisZ.Negate(); var startVertex = new CsgVertex(start, negatedAxisZ, Vector2.One * 0.5f); var endVertex = new CsgVertex(end, axisZ, Vector2.One * 0.5f); var polygons = new List <CsgPolygon>(); CsgVertex CreatePoint(float stack, float slice, float normalBlend, bool isSide = true) { var angle = slice * Mathf.Pi * 2; var outVector = axisX * Mathf.Cos(angle) + axisY * Mathf.Sin(angle); var pos = start + ray * stack + outVector * size; var normal = outVector * (1 - Mathf.Abs(normalBlend)) + axisZ * normalBlend; Vector2 uv; if (isSide) { uv = new Vector2(slice, stack); } else { uv = new Vector2(1f - (Mathf.Cos(angle) + 1f) * 0.5f, (Mathf.Sin(angle) + 1f) * 0.5f); } return(new CsgVertex(pos, normal, uv)); } var topSurface = new CsgSurfaceSharedData("Top"); var sideSurface = new CsgSurfaceSharedData("Side"); var bottomSurface = new CsgSurfaceSharedData("Bottom"); for (var i = 0; i < slices; i++) { float t0 = i / slices; float t1 = (i + 1) / slices; // Top triangle polygons.Add(new CsgPolygon(new List <CsgVertex>() { startVertex.Clone(), CreatePoint(0, t0, -1, false), CreatePoint(0, t1, -1, false) }, topSurface)); // Side rectangle polygons.Add(new CsgPolygon(new List <CsgVertex>() { CreatePoint(0, t1, 0), CreatePoint(0, t0, 0), CreatePoint(1, t0, 0), CreatePoint(1, t1, 0) }, sideSurface)); // Bottom triangle polygons.Add(new CsgPolygon(new List <CsgVertex>() { endVertex.Clone(), CreatePoint(1, t1, 1, false), CreatePoint(1, t0, 1, false) }, bottomSurface)); } surfaces = new List <CsgSurfaceSharedData>(1) { topSurface, sideSurface, bottomSurface }; var csg = FromPolygons(polygons); // And set the shared data for (int i = 0; i < surfaces.Count; i++) { surfaces[i].Csgjs = csg; } return(csg); }