Cycles: Fix for watertight intersection
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 22 Oct 2015 17:06:25 +0000 (22:06 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 22 Oct 2015 17:07:28 +0000 (22:07 +0500)
It was possible to miss some intersection caused by wrong barycentric
coordinates sign.

Cases when one of the coordinate is zero and other are negative was not
handled correct.

intern/cycles/kernel/geom/geom_triangle_intersect.h

index ba309a1dc535d7bdf887750d76a89002f5a795e1..1ce4eea48f4c41d563a7868ece8de2e6c4bff482 100644 (file)
@@ -142,12 +142,8 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
        float U = Cx * By - Cy * Bx;
        float V = Ax * Cy - Ay * Cx;
        float W = Bx * Ay - By * Ax;
-       const int sign_mask = (__float_as_int(U) & 0x80000000);
-       /* TODO(sergey): Check if multiplication plus sign check is faster
-        * or at least same speed (but robust for endian types).
-        */
-       if(sign_mask != (__float_as_int(V) & 0x80000000) ||
-          sign_mask != (__float_as_int(W) & 0x80000000))
+       if ((U < 0.0f || V < 0.0f || W < 0.0f) &&
+           (U > 0.0f || V > 0.0f || W > 0.0f))
        {
                return false;
        }
@@ -162,9 +158,10 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
         * the hit distance.
         */
        const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz;
-       const float sign_T = xor_signmask(T, sign_mask);
+       const int sign_det = (__float_as_int(det) & 0x80000000);
+       const float sign_T = xor_signmask(T, sign_det);
        if((sign_T < 0.0f) ||
-          (sign_T > isect->t * xor_signmask(det, sign_mask)))
+          (sign_T > isect->t * xor_signmask(det, sign_det)))
        {
                return false;
        }