public static CSG Cylinder(CSGVector bottom, CSGVector top, int radius) { CylinderBottom = bottom; CylinderTop = top; CylinderRadius = radius; ray = CylinderTop.minus(CylinderBottom); int slices = 16; axisZ = ray.unit(); int isY = Math.Abs(axisZ.y) > 0.5 ? 1 : 0; axisX = new CSGVector(isY, 1 - isY, 0).cross(axisZ).unit(); axisY = axisX.cross(axisZ).unit(); CSGVertex start = new CSGVertex(CylinderBottom, axisZ.negated()); CSGVertex end = new CSGVertex(CylinderTop, axisZ.unit()); List <CSGPolygon> polygons = new List <CSGPolygon>(); for (int i = 0; i < slices; i++) { double t0 = (double)i / (double)slices; double t1 = (double)(i + 1) / (double)slices; polygons.Add(new CSGPolygon(start, point(0, t0, -1), point(0, t1, -1))); polygons.Add(new CSGPolygon(point(0, t1, 0), point(0, t0, 0), point(1, t0, 0), point(1, t1, 0))); polygons.Add(new CSGPolygon(end, point(1, t1, 1), point(1, t0, 1))); } return(CSG.fromPolygons(polygons)); }
public CSGPolygon(CSGVertex P0, CSGVertex P1, CSGVertex P2) { vertices.Add(P0); vertices.Add(P1); vertices.Add(P2); shared = 0; this.plane = CSGPlane.fromPoints(P0.pos, P1.pos, P2.pos); }
public void splitPolygon(CSGPolygon polygon, List <CSGPolygon> coplanarFront, List <CSGPolygon> coPlanarBack, List <CSGPolygon> front, List <CSGPolygon> back) { const int COPLANAR = 0; const int FRONT = 1; const int BACK = 2; const int SPANNING = 3; int polygonType = 0; List <int> types = new List <int>(); for (int i = 0; i < polygon.vertices.Count; i++) { float t = this.normal.dot(polygon.vertices[i].pos) - this.w; int type = (t < -EPSILON) ? BACK : (t > EPSILON) ? FRONT : COPLANAR; polygonType |= type; types.Add(type); } switch (polygonType) { case COPLANAR: (this.normal.dot(polygon.plane.normal) > 0 ? coplanarFront : coPlanarBack).Add(polygon); break; case FRONT: front.Add(polygon); break; case BACK: back.Add(polygon); break; case SPANNING: List <CSGVertex> f = new List <CSGVertex>(); List <CSGVertex> b = new List <CSGVertex>(); for (int i = 0; i < polygon.vertices.Count; i++) { int j = (i + 1) % polygon.vertices.Count; int ti = types[i]; int tj = types[j]; CSGVertex vi = polygon.vertices[i]; CSGVertex vj = polygon.vertices[j]; if (ti != BACK) { f.Add(vi); } if (ti != FRONT) { b.Add(ti != BACK ? vi.clone() : vi); } if ((ti | tj) == SPANNING) { float t = (this.w - this.normal.dot(vi.pos)) / this.normal.dot(vj.pos.minus(vi.pos)); CSGVertex v = vi.interpolate(vj, t); f.Add(v); b.Add(v.clone()); } } if (f.Count >= 3) { front.Add(new CSGPolygon(f, polygon.shared)); } if (b.Count >= 3) { back.Add(new CSGPolygon(b, polygon.shared)); } break; } }
public CSGVertex interpolate(CSGVertex other, float t) { return(new CSGVertex(this.pos.lerp(other.pos, t), this.normal.lerp(other.normal, t))); }
public CSGVector(CSGVertex v) { this.x = v.pos.x; this.y = v.pos.y; this.z = v.pos.z; }