public MeshPoint IntersectLine(MeshPolygon tri, int lineInd) { var points = tri.Points; var lineInd2 = (lineInd + 1) % points.Count; var pt1 = tri.Points[lineInd]; var pt2 = tri.Points[lineInd2]; Vector3 a = EdgeVec; //line 1 Vector3 b = pt2.Position - pt1.Position; //line 2 Vector3 c = EdgePos - pt1.Position; //vec between starts //percent of line 1 where we intersect with line 2 float ip = 1 / (-b.X * a.Z + a.X * b.Z); //projection float t = (b.X * c.Z - b.Z * c.X) * ip; //percent of line 2 where we intersect line 1 float ip2 = 1 / (-a.X * b.Z + b.X * a.Z); float s = (a.X * (-c.Z) - a.Z * (-c.X)) * ip2; //pos + vec * t = pos2 + vec2 * s //vec * t - vec2 * s = pos2 - pos1 float[] newTC = new float[pt1.TexCoords.Length]; float ms = 1 - s; for (int i = 0; i < newTC.Length; i++) { newTC[i] = pt1.TexCoords[i] * ms + pt2.TexCoords[i] * s; } return(new MeshPoint( //position from the clip triangle (use t) EdgePos + EdgeVec * t, //texcoords from the two points in the poly (use s) newTC )); }
private void ClipTriangles(BaseMeshTriangle baseTri, MeshTriangle projTri, List <MeshPoint> outverts, List <int> inds) { //Sutherland–Hodgman algorithm //clip a triangle against another by iteratively clipping each edge of the second one //we want to clip against base tri var outputList = new MeshPolygon(projTri); var basePlane = new Plane(baseTri.Vertices[0], baseTri.Vertices[1], baseTri.Vertices[2]); for (int i = 0; i < 3; i++) { if (outputList.Points.Count == 0) { return; } var inputList = outputList; var edge = new ClipEdge(baseTri.Vertices[i], baseTri.Vertices[(i + 1) % 3]); outputList = new MeshPolygon(); var lastPoint = inputList.Points.Last(); int j = inputList.Points.Count - 1; foreach (var point in inputList.Points) { if (!edge.ShouldClip(point.Position)) { if (edge.ShouldClip(lastPoint.Position)) { outputList.Points.Add(edge.IntersectLine(inputList, j)); } //we still need to project the point onto the surface... var ray = new Ray(point.Position, new Vector3(0, -1, 0)); var intersect2 = ray.Intersects(basePlane); if (intersect2 == null) { ray.Direction *= -1; intersect2 = ray.Intersects(basePlane); if (intersect2 == null) { } intersect2 = -(intersect2 ?? 0f); } point.Position.Y -= intersect2.Value; outputList.Points.Add(point); } else { if (!edge.ShouldClip(lastPoint.Position)) { outputList.Points.Add(edge.IntersectLine(inputList, j)); } } j = (j + 1) % inputList.Points.Count; lastPoint = point; } } if (outputList.Points.Count < 3) { return; //? } outputList.Triangulate(outverts, inds); }