public static Mesh MeshFromPolygons(List <CsgPolygon> polygons) { Mesh model = new Mesh(); HashSet <PolygonMesh.Vertex> vertices = new HashSet <PolygonMesh.Vertex>(); for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++) { CsgPolygon poly = polygons[polygonIndex]; vertices.Clear(); for (int vertexIndex = 0; vertexIndex < poly.vertices.Count; vertexIndex++) { vertices.Add(model.CreateVertex(poly.vertices[vertexIndex].Position)); } if (vertices.Count > 2) { model.CreateFace(vertices.ToArray()); } } return(model); }
// Split `polygon` by this plane if needed, then put the polygon or polygon // fragments in the appropriate lists. Coplanar polygons go into either // `coplanarFront` or `coplanarBack` depending on their orientation with // respect to this plane. Polygons in front or in back of this plane go into // either `front` or `back`. public void SplitPolygon(CsgPolygon polygon, List <CsgPolygon> coplanarFront, List <CsgPolygon> coplanarBack, List <CsgPolygon> front, List <CsgPolygon> back) { double splitTolerance = 0.00001; // Classify each point as well as the entire polygon into one of the above // four classes. PolyType polygonType = PolyType.COPLANAR; List <PolyType> types = new List <PolyType>(); for (int i = 0; i < polygon.vertices.Count; i++) { double t = Vector3.Dot(this.normal, polygon.vertices[i].Position) - this.w; PolyType type = (t < -splitTolerance) ? PolyType.BACK : ((t > splitTolerance) ? PolyType.FRONT : PolyType.COPLANAR); polygonType |= type; types.Add(type); } // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case PolyType.COPLANAR: { if (Vector3.Dot(this.normal, polygon.plane.normal) > 0) { coplanarFront.Add(polygon); } else { coplanarBack.Add(polygon); } break; } case PolyType.FRONT: { front.Add(polygon); break; } case PolyType.BACK: { back.Add(polygon); break; } case PolyType.SPANNING: { List <Vertex> frontVertices = new List <Vertex>(); List <Vertex> backVertices = new List <Vertex>(); for (int firstVertexIndex = 0; firstVertexIndex < polygon.vertices.Count; firstVertexIndex++) { int nextVertexIndex = (firstVertexIndex + 1) % polygon.vertices.Count; PolyType firstPolyType = types[firstVertexIndex]; PolyType nextPolyType = types[nextVertexIndex]; Vertex firstVertex = polygon.vertices[firstVertexIndex]; Vertex nextVertex = polygon.vertices[nextVertexIndex]; if (firstPolyType != PolyType.BACK) { frontVertices.Add(firstVertex); } if (firstPolyType != PolyType.FRONT) { backVertices.Add(firstVertex); } if ((firstPolyType | nextPolyType) == PolyType.SPANNING) { double planDotFirstVertex = Vector3.Dot(this.normal, firstVertex.Position); double firstDistToPlane = this.w - planDotFirstVertex; Vector3 deltaFromFirstToNext = nextVertex.Position - firstVertex.Position; double t = firstDistToPlane / Vector3.Dot(this.normal, deltaFromFirstToNext); Vertex newVertex = firstVertex.CreateInterpolated(nextVertex, t); frontVertices.Add(newVertex); backVertices.Add(newVertex); } } if (frontVertices.Count >= 3) { front.Add(new CsgPolygon(frontVertices)); } if (backVertices.Count >= 3) { back.Add(new CsgPolygon(backVertices)); } } break; default: throw new NotImplementedException(); } }
// Split `polygon` by this plane if needed, then put the polygon or polygon // fragments in the appropriate lists. Coplanar polygons go into either // `coplanarFront` or `coplanarBack` depending on their orientation with // respect to this plane. Polygons in front or in back of this plane go into // either `front` or `back`. public void SplitPolygon(CsgPolygon polygon, List<CsgPolygon> coplanarFront, List<CsgPolygon> coplanarBack, List<CsgPolygon> front, List<CsgPolygon> back) { double splitTolerance = 0.00001; // Classify each point as well as the entire polygon into one of the above // four classes. PolyType polygonType = PolyType.COPLANAR; List<PolyType> types = new List<PolyType>(); for (int i = 0; i < polygon.vertices.Count; i++) { double t = Vector3.Dot(this.normal, polygon.vertices[i].Position) - this.w; PolyType type = (t < -splitTolerance) ? PolyType.BACK : ((t > splitTolerance) ? PolyType.FRONT : PolyType.COPLANAR); polygonType |= type; types.Add(type); } // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case PolyType.COPLANAR: { if (Vector3.Dot(this.normal, polygon.plane.normal) > 0) { coplanarFront.Add(polygon); } else { coplanarBack.Add(polygon); } break; } case PolyType.FRONT: { front.Add(polygon); break; } case PolyType.BACK: { back.Add(polygon); break; } case PolyType.SPANNING: { List<Vertex> frontVertices = new List<Vertex>(); List<Vertex> backVertices = new List<Vertex>(); for (int firstVertexIndex = 0; firstVertexIndex < polygon.vertices.Count; firstVertexIndex++) { int nextVertexIndex = (firstVertexIndex + 1) % polygon.vertices.Count; PolyType firstPolyType = types[firstVertexIndex]; PolyType nextPolyType = types[nextVertexIndex]; Vertex firstVertex = polygon.vertices[firstVertexIndex]; Vertex nextVertex = polygon.vertices[nextVertexIndex]; if (firstPolyType != PolyType.BACK) { frontVertices.Add(firstVertex); } if (firstPolyType != PolyType.FRONT) { backVertices.Add(firstVertex); } if ((firstPolyType | nextPolyType) == PolyType.SPANNING) { double planDotFirstVertex = Vector3.Dot(this.normal, firstVertex.Position); double firstDistToPlane = this.w - planDotFirstVertex; Vector3 deltaFromFirstToNext = nextVertex.Position - firstVertex.Position; double t = firstDistToPlane / Vector3.Dot(this.normal, deltaFromFirstToNext); Vertex newVertex = firstVertex.CreateInterpolated(nextVertex, t); frontVertices.Add(newVertex); backVertices.Add(newVertex); } } if (frontVertices.Count >= 3) { front.Add(new CsgPolygon(frontVertices)); } if (backVertices.Count >= 3) { back.Add(new CsgPolygon(backVertices)); } } break; default: throw new NotImplementedException(); } }
// Split `polygon` by this plane if needed, then put the polygon or polygon // fragments in the appropriate lists. Coplanar polygons go into either // `coplanarFront` or `coplanarBack` depending on their orientation with // respect to this plane. Polygons in front or in back of this plane go into // either `front` or `back`. public void SplitPolygon(CsgPolygon polygon, List <CsgPolygon> coplanarFront, List <CsgPolygon> coplanarBack, List <CsgPolygon> front, List <CsgPolygon> back) { throw new NotImplementedException(); //double splitTolerance = 0.00001; //// Classify each point as well as the entire polygon into one of the above //// four classes. //PolyType polygonType = PolyType.COPLANAR; //List<PolyType> types = new List<PolyType>(); //for (int i = 0; i < polygon.vertices.Count; i++) //{ // double t = Vector3Ex.Dot(this.normal, polygon.vertices[i].Position) - this.w; // PolyType type = (t < -splitTolerance) ? PolyType.BACK : ((t > splitTolerance) ? PolyType.FRONT : PolyType.COPLANAR); // polygonType |= type; // types.Add(type); //} //// Put the polygon in the correct list, splitting it when necessary. //switch (polygonType) //{ // case PolyType.COPLANAR: // { // if (Vector3Ex.Dot(this.normal, polygon.plane.normal) > 0) // { // coplanarFront.Add(polygon); // } // else // { // coplanarBack.Add(polygon); // } // break; // } // case PolyType.FRONT: // { // front.Add(polygon); // break; // } // case PolyType.BACK: // { // back.Add(polygon); // break; // } // case PolyType.SPANNING: // { // List<IVertex> frontVertices = new List<IVertex>(); // List<IVertex> backVertices = new List<IVertex>(); // for (int firstVertexIndex = 0; firstVertexIndex < polygon.vertices.Count; firstVertexIndex++) // { // int nextVertexIndex = (firstVertexIndex + 1) % polygon.vertices.Count; // PolyType firstPolyType = types[firstVertexIndex]; // PolyType nextPolyType = types[nextVertexIndex]; // IVertex firstVertex = polygon.vertices[firstVertexIndex]; // IVertex nextVertex = polygon.vertices[nextVertexIndex]; // if (firstPolyType != PolyType.BACK) // { // frontVertices.Add(firstVertex); // } // if (firstPolyType != PolyType.FRONT) // { // backVertices.Add(firstVertex); // } // if ((firstPolyType | nextPolyType) == PolyType.SPANNING) // { // double planDotFirstVertex = Vector3Ex.Dot(this.normal, firstVertex.Position); // double firstDistToPlane = this.w - planDotFirstVertex; // Vector3 deltaFromFirstToNext = nextVertex.Position - firstVertex.Position; // double t = firstDistToPlane / Vector3Ex.Dot(this.normal, deltaFromFirstToNext); // IVertex newVertex = firstVertex.CreateInterpolated(nextVertex, t); // frontVertices.Add(newVertex); // backVertices.Add(newVertex); // } // } // if (frontVertices.Count >= 3) // { // front.Add(new CsgPolygon(frontVertices)); // } // if (backVertices.Count >= 3) // { // back.Add(new CsgPolygon(backVertices)); // } // } // break; // default: // throw new NotImplementedException(); //} }