/// <summary> /// Initialize a Model from a UnityEngine.Mesh and transform. /// </summary> public CSG_Model(Mesh mesh, Material[] materials, Transform transform) { if (mesh == null) { throw new ArgumentNullException("mesh"); } if (transform == null) { throw new ArgumentNullException("transform"); } vertices = CSG_VertexUtility.GetVertices(mesh).Select(x => transform.TransformVertex(x)).ToList(); m_Materials = new List <Material>(materials); m_Indices = new List <List <int> >(); for (int i = 0, c = mesh.subMeshCount; i < c; i++) { if (mesh.GetTopology(i) != MeshTopology.Triangles) { continue; } var indices = new List <int>(); mesh.GetIndices(indices, i); m_Indices.Add(indices); } }
// 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(CSG_Polygon polygon, List <CSG_Polygon> coplanarFront, List <CSG_Polygon> coplanarBack, ref List <CSG_Polygon> front, ref List <CSG_Polygon> back) { // Classify each point as well as the entire polygon into one of the above // four classes. EPolygonType polygonType = 0; List <EPolygonType> types = new List <EPolygonType>(); for (int i = 0; i < polygon.vertices.Count; i++) { float t = Vector3.Dot(this.normal, polygon.vertices[i].position) - this.w; EPolygonType type = (t < -Boolean.k_Epsilon) ? EPolygonType.Back : ((t > Boolean.k_Epsilon) ? EPolygonType.Front : EPolygonType.Coplanar); polygonType |= type; types.Add(type); } // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case EPolygonType.Coplanar: { if (Vector3.Dot(this.normal, polygon.plane.normal) > 0) { coplanarFront.Add(polygon); } else { coplanarBack.Add(polygon); } } break; case EPolygonType.Front: { front.Add(polygon); } break; case EPolygonType.Back: { back.Add(polygon); } break; case EPolygonType.Spanning: { List <CSG_Vertex> f = new List <CSG_Vertex>(); List <CSG_Vertex> b = new List <CSG_Vertex>(); for (int i = 0; i < polygon.vertices.Count; i++) { int j = (i + 1) % polygon.vertices.Count; EPolygonType ti = types[i], tj = types[j]; CSG_Vertex vi = polygon.vertices[i], vj = polygon.vertices[j]; if (ti != EPolygonType.Back) { f.Add(vi); } if (ti != EPolygonType.Front) { b.Add(ti != EPolygonType.Back ? vi.Clone() : vi); } if ((ti | tj) == EPolygonType.Spanning) { float t = (this.w - Vector3.Dot(this.normal, vi.position)) / Vector3.Dot(this.normal, vj.position - vi.position); CSG_Vertex v = CSG_VertexUtility.Mix(vi, vj, t); f.Add(v); b.Add(v.Clone()); } } if (f.Count >= 3) { front.Add(new CSG_Polygon(f, polygon.material)); } if (b.Count >= 3) { back.Add(new CSG_Polygon(b, polygon.material)); } } break; } // End switch(polygonType) }