public static CSGVertex Interpolate(CSGVertex _vertexA, CSGVertex _vertexB, float _step) { CSGVertex result = new CSGVertex(); result.m_position = Vector3.Lerp(_vertexA.m_position, _vertexB.m_position, _step); result.m_normal = Vector3.Lerp(_vertexA.m_normal, _vertexB.m_normal, _step); result.m_uv = Vector2.Lerp(_vertexA.m_uv, _vertexB.m_uv, _step); result.m_color = (_vertexA.m_color + _vertexB.m_color) / 2f; return(result); }
// 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) { // Classify each point as well as the entire polygon into one of the above // four classes. PolygonType polygonType = 0; List <PolygonType> types = new List <PolygonType>(); for (int i = 0; i < _polygon.m_vertices.Count; i++) { float t = Vector3.Dot(m_normal, _polygon.m_vertices[i].m_position) - m_planeWidth; PolygonType type = (t < -CSG.EPSILON) ? PolygonType.Back : ((t > CSG.EPSILON) ? PolygonType.Front : PolygonType.Coplanar); polygonType |= type; types.Add(type); } // Put the polygon in the correct list, splitting it when necessary. switch (polygonType) { case PolygonType.Coplanar: { if (Vector3.Dot(m_normal, _polygon.m_plane.m_normal) > 0) { _coplanarFront.Add(_polygon); } else { _coplanarBack.Add(_polygon); } } break; case PolygonType.Front: { _front.Add(_polygon); } break; case PolygonType.Back: { _back.Add(_polygon); } break; case PolygonType.Spanning: { List <CSGVertex> front = new List <CSGVertex>(); List <CSGVertex> back = new List <CSGVertex>(); for (int vertexIter = 0; vertexIter < _polygon.m_vertices.Count; vertexIter++) { int nextVertexIndex = (vertexIter + 1) % _polygon.m_vertices.Count; PolygonType currentType = types[vertexIter]; PolygonType nextType = types[nextVertexIndex]; CSGVertex currentVertex = _polygon.m_vertices[vertexIter]; CSGVertex nextVertex = _polygon.m_vertices[nextVertexIndex]; if (currentType != PolygonType.Back) { front.Add(currentVertex); } if (currentType != PolygonType.Front) { back.Add(currentVertex); } if ((currentType | nextType) == PolygonType.Spanning) { float step = (m_planeWidth - Vector3.Dot(m_normal, currentVertex.m_position)) / Vector3.Dot(m_normal, nextVertex.m_position - currentVertex.m_position); CSGVertex vertex = CSGVertex.Interpolate(currentVertex, nextVertex, step); front.Add(vertex); back.Add(vertex); } } if (front.Count >= 3) { _front.Add(new CSGPolygon(front)); } if (back.Count >= 3) { _back.Add(new CSGPolygon(back)); } } break; } }