Thank you Wikipedia!
| 958 | |
| 959 | // Thank you Wikipedia! |
| 960 | inline std::optional<std::pair<olc::vf3d, float>> RayVsTriangle( |
| 961 | const olc::vf3d& ray_origin, |
| 962 | const olc::vf3d& ray_vector, |
| 963 | const olc::vf3d& ta, const olc::vf3d& tb, const olc::vf3d& tc) |
| 964 | { |
| 965 | constexpr float epsilon = std::numeric_limits<float>::epsilon(); |
| 966 | |
| 967 | olc::vf3d edge1 = tb - ta; |
| 968 | olc::vf3d edge2 = tc - ta; |
| 969 | olc::vf3d ray_cross_e2 = ray_vector.cross(edge2); |
| 970 | float det = edge1.dot(ray_cross_e2); |
| 971 | |
| 972 | if (det > -epsilon && det < epsilon) |
| 973 | return {}; |
| 974 | |
| 975 | float inv_det = 1.0f / det; |
| 976 | olc::vf3d s = ray_origin - ta; |
| 977 | float u = inv_det * s.dot(ray_cross_e2); |
| 978 | |
| 979 | if ((u < 0 && abs(u) > epsilon) || (u > 1 && abs(u - 1) > epsilon)) |
| 980 | return {}; |
| 981 | |
| 982 | olc::vf3d s_cross_e1 = s.cross(edge1); |
| 983 | float v = inv_det * ray_vector.dot(s_cross_e1); |
| 984 | |
| 985 | if ((v < 0 && abs(v) > epsilon) || (u + v > 1 && abs(u + v - 1) > epsilon)) |
| 986 | return {}; |
| 987 | |
| 988 | float t = inv_det * edge2.dot(s_cross_e1); |
| 989 | |
| 990 | if (t > epsilon) // ray intersection |
| 991 | { |
| 992 | return { {olc::vf3d(ray_origin + ray_vector * t), t} }; |
| 993 | } |
| 994 | else |
| 995 | return {}; |
| 996 | } |
| 997 | |
| 998 | inline std::optional<olc::vf3d> RayVsPlane(const olc::vf3d& vRayOrigin, const olc::vf3d& vRayDir, const olc::vf3d& vPlaneP, const olc::vf3d& vPlaneN) |
| 999 | { |