public static CSG sphere(Vector3 center, double radius = 1, double slices = 16, double stacks = 8f) { double r = radius; List <CsgPolygon> polygons = new List <CsgPolygon>(); List <IVertex> vertices; for (int i = 0; i < slices; i++) { for (int j = 0; j < stacks; j++) { vertices = new List <IVertex>(); makeSphereVertex(ref vertices, center, r, i / slices, j / stacks); if (j > 0) { makeSphereVertex(ref vertices, center, r, (i + 1) / slices, j / stacks); } if (j < stacks - 1) { makeSphereVertex(ref vertices, center, r, (i + 1) / slices, (j + 1) / stacks); } makeSphereVertex(ref vertices, center, r, i / slices, (j + 1) / stacks); polygons.Add(new CsgPolygon(vertices)); } } return(CSG.fromPolygons(polygons)); }
/// <summary> /// Cube function, Untested but compiles /// </summary> /// <param name="center">world space center of the cube</param> /// <param name="radius">size of the cube created at center</param> /// <returns></returns> public static CSG cube(Vector3?center, Vector3?radius) { Vector3 c = center.GetValueOrDefault(Vector3.Zero); Vector3 r = radius.GetValueOrDefault(Vector3.One); //TODO: Test if this works CsgPolygon[] polygons = new CsgPolygon[6]; int[][][] data = new int[][][] { new int[][] { new int[] { 0, 4, 6, 2 }, new int[] { -1, 0, 0 } }, new int[][] { new int[] { 1, 3, 7, 5 }, new int[] { 1, 0, 0 } }, new int[][] { new int[] { 0, 1, 5, 4 }, new int[] { 0, -1, 0 } }, new int[][] { new int[] { 2, 6, 7, 3 }, new int[] { 0, 1, 0 } }, new int[][] { new int[] { 0, 2, 3, 1 }, new int[] { 0, 0, -1 } }, new int[][] { new int[] { 4, 5, 7, 6 }, new int[] { 0, 0, 1 } } }; for (int x = 0; x < 6; x++) { int[][] v = data[x]; Vector3 normal = new Vector3(v[1][0], v[1][1], v[1][2]); IVertex[] verts = new IVertex[4]; for (int i = 0; i < 4; i++) { verts[i] = new Vertex( new Vector3( c.X + (r.X * (2 * (((v[0][i] & 1) > 0) ? 1 : 0) - 1)), c.Y + (r.Y * (2 * (((v[0][i] & 2) > 0) ? 1 : 0) - 1)), c.Z + (r.Z * (2 * (((v[0][i] & 4) > 0) ? 1 : 0) - 1))), normal ); } polygons[x] = new CsgPolygon(verts); } return(CSG.fromPolygons(polygons)); }
/// <summary> /// Create CSG from array, does not clone the polygons /// </summary> /// <param name="polygon"></param> /// <returns></returns> private static CSG fromPolygons(CsgPolygon[] polygons) { //TODO: Optimize polygons to share vertices CSG csg = new CSG(); csg.polygons.AddRange(polygons); return(csg); }
public CSG inverse() { CSG csg = this.clone(); foreach (CsgPolygon p in csg.polygons) { p.flip(); } return(csg); }
/// <summary> /// Clone /// </summary> /// <returns></returns> public CSG clone() { CSG csg = new CSG(); foreach (CsgPolygon p in this.polygons) { csg.polygons.Add(p.clone()); } return(csg); }
/// <summary> /// Construct a CSG solid from a list of `Polygon` instances. /// The polygons are cloned /// </summary> /// <param name="polygons"></param> /// <returns></returns> public static CSG fromPolygons(List <CsgPolygon> polygons) { //TODO: Optimize polygons to share vertices CSG csg = new CSG(); foreach (CsgPolygon p in polygons) { csg.polygons.Add(p.clone()); } return(csg); }
/// <summary> /// Return a new CSG solid representing space both this solid and in the /// solid `csg`. Neither this solid nor the solid `csg` are modified. /// </summary> /// <remarks> /// A.intersect(B) /// /// +-------+ /// | | /// | A | /// | +--+----+ = +--+ /// +----+--+ | +--+ /// | B | /// | | /// +-------+ /// </remarks> /// <param name="csg"></param> /// <returns>CSG of the intersection</returns> public CSG intersect(CSG csg) { Node a = new Node(this.polygons); Node b = new Node(csg.polygons); a.invert(); b.invert(); a.clipTo(b); b.clipTo(a); a.build(b.allPolygons()); return(CSG.fromPolygons(a.allPolygons()).inverse()); }
/// <summary> /// /// </summary> /// <param name="mesh"></param> public void Substract(Mesh mesh) { var a = CSG.fromMesh(this); var b = CSG.fromMesh(mesh); var c = a.subtract(b); var result = c.toMesh(); var color = Colors[0]; Colors = Enumerable.Repeat(color, result.Vertices.Length).ToArray(); Vertices = result.Vertices; Normals = result.Normals; Faces = result.Faces; }
/// <summary> /// Initializes a new instance of the <see cref="SharpGLForm"/> class. /// </summary> public SharpGLForm() { InitializeComponent(); this.Text = "CSG"; this.MouseWheel += new MouseEventHandler(openGLControl_MouseWheel); angles = DefaultAngles; distance = DefaultDistance; UpdateCamera(angles, distance); // Substract and union var a = CSG.cube(new Vector3(0, 1, 0), new Vector3(5, 1, 5)); var b = CSG.cube(new Vector3(0, 1, 0), new Vector3(2, 1, 2)); var c = CSG.cube(new Vector3(2, 1, 2), new Vector3(2, 1, 2)); var d = CSG.sphere(new Vector3(-4, 2, -4), 2, 16, 16); var x = a.subtract(b); var y = x.subtract(c); var z = y.union(d); var mesh = z.toMesh(); mesh.Colors = Enumerable.Repeat(Color.Red, mesh.Vertices.Length).ToArray(); meshes.Add(mesh); // Intersect var e = CSG.cube(new Vector3(10, 1, -10), new Vector3(2, 1, 2)); var f = CSG.sphere(new Vector3(9, 2, -9), 2, 16, 16); var w = e.intersect(f); mesh = w.toMesh(); mesh.Colors = Enumerable.Repeat(Color.Yellow, mesh.Vertices.Length).ToArray(); meshes.Add(mesh); // OSM polys issues var outer = ComputeBody(ReadPoly(@"..\..\samples\64955049.txt"), Color.Green); outer.Cap(Color.Green); var inner = ComputeBody(ReadPoly(@"..\..\samples\64955049-inner.txt"), Color.Green); inner.Cap(Color.Green); // outer.Substract(inner); meshes.Add(outer); }
// public static CSG fromMesh(Mesh m, Transform tf) public static CSG fromMesh(Mesh m) { List <CsgPolygon> triangles = new List <CsgPolygon>(); int[] tris = m.Faces; for (int t = 0; t < tris.Length; t += 3) { Vertex[] vs = new Vertex[3]; /* * vs[0] = TranslateVertex(m, tf, tris[t]); * vs[1] = TranslateVertex(m, tf, tris[t + 1]); * vs[2] = TranslateVertex(m, tf, tris[t + 2]); */ vs[0] = new Vertex(m.Vertices[tris[t]], m.Normals[tris[t]]); vs[1] = new Vertex(m.Vertices[tris[t + 1]], m.Normals[tris[t + 1]]); vs[2] = new Vertex(m.Vertices[tris[t + 2]], m.Normals[tris[t + 2]]); triangles.Add(new CsgPolygon(vs)); } return(CSG.fromPolygons(triangles)); }