public void PointNearestToOtherRay(TRay r, ref float point) { Vector3 t = Vector3.Cross(dir, r.dir); TPlane p = new TPlane(Vector3.Cross(t, r.dir), r.pos); Inters(p, ref point); }
public bool Inters(TPlane plane, ref float t) { float v = Vector3.Dot(plane.normal, dir); if (v == 0) { return(false); } t = (plane.dist - Vector3.Dot(pos, plane.normal)) / v; return(t > 0); }
void CutTriangleByPlane(TPlane plane, int tri) { TMeshTri t = triangle[tri]; float d0 = plane.DistToPlane(pos[t.p0]), d1 = plane.DistToPlane(pos[t.p1]), d2 = plane.DistToPlane(pos[t.p2]); bool d0_sign = d0 >= 0; bool d1_sign = d1 >= 0; bool d2_sign = d2 >= 0; int vert0 = -1, vert1 = -1, vert2 = -1; { int zero_count = 0; if (d0 == 0.0f) { zero_count++; } if (d1 == 0.0f) { zero_count++; } if (d2 == 0.0f) { zero_count++; } if (zero_count == 3 || zero_count == 2) { return; } } if (d0 == 0.0f || d1 == 0.0f || d2 == 0.0f) { float x = 0; if (d0 == 0.0f) { if (d1_sign == d2_sign) { return; } vert0 = 0; vert1 = 1; vert2 = 2; x = d1 / (d1 - d2); } else if (d1 == 0.0f) { if (d0_sign == d2_sign) { return; } vert0 = 1; vert1 = 2; vert2 = 0; x = d2 / (d2 - d0); } else// if (d2 == 0.0f) { if (d0_sign == d1_sign) { return; } vert0 = 2; vert1 = 0; vert2 = 1; x = d0 / (d0 - d1); } Vector3 new_pos = Blend(pos[t.GetPos(vert1)], pos[t.GetPos(vert2)], x); Vector3 new_normal = Blend(normal[t.GetNormal(vert1)], normal[t.GetNormal(vert2)], x); new_normal.Normalize(); Debug.Assert(!float.IsNaN(new_pos.X) && !float.IsNaN(new_pos.Y) && !float.IsNaN(new_pos.Z)); pos.Add(new_pos); normal.Add(new_normal); TMeshTri temp = triangle[tri]; triangle[tri] = new TMeshTri( temp.GetPos(vert0), temp.GetPos(vert1), pos.High, temp.GetNormal(vert0), temp.GetNormal(vert1), normal.High, 0, 0, 0); triangle.Add(new TMeshTri( temp.GetPos(vert0), pos.High, temp.GetPos(vert2), temp.GetNormal(vert0), normal.High, temp.GetNormal(vert2), 0, 0, 0)); } else { float x1 = 0, x2 = 0; if ((d0_sign == d1_sign) && (d0_sign != d2_sign)) { vert0 = 2; vert1 = 0; vert2 = 1; x1 = d2 / (d2 - d0); x2 = d2 / (d2 - d1); } else if ((d0_sign == d2_sign) && (d0_sign != d1_sign)) { vert0 = 1; vert1 = 2; vert2 = 0; x1 = d1 / (d1 - d2); x2 = d1 / (d1 - d0); } else if ((d1_sign == d2_sign) && (d0_sign != d1_sign)) { vert0 = 0; vert1 = 1; vert2 = 2; x1 = d0 / (d0 - d1); x2 = d0 / (d0 - d2); } else { return; //треугольники могут пересекаются из-за неточностей } Vector3 new_pos1 = Blend(pos[t.GetPos(vert0)], pos[t.GetPos(vert1)], x1); Vector3 new_pos2 = Blend(pos[t.GetPos(vert0)], pos[t.GetPos(vert2)], x2); Vector3 new_normal1 = Blend(normal[t.GetNormal(vert0)], normal[t.GetNormal(vert1)], x1); Vector3 new_normal2 = Blend(normal[t.GetNormal(vert0)], normal[t.GetNormal(vert2)], x2); new_normal1.Normalize(); new_normal2.Normalize(); pos.Add(new_pos1); pos.Add(new_pos2); Debug.Assert(!float.IsNaN(new_pos1.X) && !float.IsNaN(new_pos1.Y) && !float.IsNaN(new_pos1.Z)); Debug.Assert(!float.IsNaN(new_pos2.X) && !float.IsNaN(new_pos2.Y) && !float.IsNaN(new_pos2.Z)); normal.Add(new_normal1); normal.Add(new_normal2); TMeshTri temp = triangle[tri]; //TODO выбирать наиболее короткое ребро triangle[tri] = new TMeshTri( temp.GetPos(vert0), pos.High - 1, pos.High, temp.GetNormal(vert0), normal.High - 1, normal.High, 0, 0, 0); triangle.Add(new TMeshTri( pos.High - 1, temp.GetPos(vert1), temp.GetPos(vert2), normal.High - 1, temp.GetNormal(vert1), temp.GetNormal(vert2), 0, 0, 0)); triangle.Add(new TMeshTri( pos.High - 1, temp.GetPos(vert2), pos.High, normal.High - 1, temp.GetNormal(vert2), normal.High, 0, 0, 0)); } }