bool ray4::hitsTriangle(const float4 *points, float &length) const { const float4 p0p1(points[1] - points[0]); const float4 p0p2(points[2] - points[0]); const float4 normal = float4(p0p1.cross(p0p2)); // n * p = n * (s + t*d) = n*s + n*d*t // n(p-s) = ndt // (n(p-s))/(n*d) = t float4 dir = direction(); float4 outFactor = float4(-1.0f); float4 normalTimesDirection = normal.prod(dir); outFactor = (normalTimesDirection != float4(0.0f)).select(normal.prod(points[0] - start()) / normalTimesDirection, outFactor); if((outFactor < float4(0.0f)).all()) return false; if(outFactor.max() > 1.0f) return false; const float4 location = this->point(outFactor.max()); length = outFactor.max(); return location.isOnTriangle(points); }
bool float4::isOnTriangle(const float4 *points) const { const float4 zero(0.0f); const float4 one(1.0f); const float4 p0p1(points[1] - points[0]); const float4 p0p2(points[2] - points[0]); const float4 normal(p0p1.cross(p0p2)); if(std::abs((normal * *this) - (normal * points[0])) >= 0.001f) return false; const float4 p0hp(*this - points[0]); // dot00 = dot(v0, v0) // dot01 = dot(v0, v1) // dot02 = dot(v0, v2) // dot11 = dot(v1, v1) // dot12 = dot(v1, v2) // // // Compute barycentric coordinates // invDenom = 1 / (dot00 * dot11 - dot01 * dot01) // u = (dot11 * dot02 - dot01 * dot12) * invDenom // v = (dot00 * dot12 - dot01 * dot02) * invDenom // // // Check if point is in triangle // return (u > 0) && (v > 0) && (u + v < 1) const float4 dot00(p0p1.vdot(p0p1)); const float4 dot01(p0p1.vdot(p0p2)); const float4 dot02(p0p1.vdot(p0hp)); const float4 dot11(p0p2.vdot(p0p2)); const float4 dot12(p0p2.vdot(p0hp)); const float4 invDenom = one / (dot00.prod(dot11) - dot01.prod(dot01)); const float4 u = (dot11.prod(dot02) - dot01.prod(dot12)).prod(invDenom); const float4 v = (dot00.prod(dot12) - dot01.prod(dot02)).prod(invDenom); return (u >= zero).all() && (v >= zero).all() && (u + v <= one).all(); }