diff --git a/kernels/bvh/node_intersector1.h b/kernels/bvh/node_intersector1.h index 17641fa888..80749892ac 100644 --- a/kernels/bvh/node_intersector1.h +++ b/kernels/bvh/node_intersector1.h @@ -539,15 +539,40 @@ namespace embree template __forceinline size_t intersectNodeRobust(const typename BVHN::AABBNode* node, const TravRay& ray, vfloat& dist) { - const vfloat tNearX = (vfloat::load((float*)((const char*)&node->lower_x+ray.nearX)) - ray.org.x) * ray.rdir_near.x; - const vfloat tNearY = (vfloat::load((float*)((const char*)&node->lower_x+ray.nearY)) - ray.org.y) * ray.rdir_near.y; - const vfloat tNearZ = (vfloat::load((float*)((const char*)&node->lower_x+ray.nearZ)) - ray.org.z) * ray.rdir_near.z; - const vfloat tFarX = (vfloat::load((float*)((const char*)&node->lower_x+ray.farX )) - ray.org.x) * ray.rdir_far.x; - const vfloat tFarY = (vfloat::load((float*)((const char*)&node->lower_x+ray.farY )) - ray.org.y) * ray.rdir_far.y; - const vfloat tFarZ = (vfloat::load((float*)((const char*)&node->lower_x+ray.farZ )) - ray.org.z) * ray.rdir_far.z; + const vfloat lowerX = vfloat::load((float*)((const char*)&node->lower_x+ray.nearX)); + const vfloat lowerY = vfloat::load((float*)((const char*)&node->lower_x+ray.nearY)); + const vfloat lowerZ = vfloat::load((float*)((const char*)&node->lower_x+ray.nearZ)); + const vfloat upperX = vfloat::load((float*)((const char*)&node->lower_x+ray.farX )); + const vfloat upperY = vfloat::load((float*)((const char*)&node->lower_x+ray.farY )); + const vfloat upperZ = vfloat::load((float*)((const char*)&node->lower_x+ray.farZ )); + + const vfloat tNearX0 = (lowerX - ray.org.x) * ray.rdir_near.x; + const vfloat tNearY0 = (lowerY - ray.org.y) * ray.rdir_near.y; + const vfloat tNearZ0 = (lowerZ - ray.org.z) * ray.rdir_near.z; + const vfloat tFarX0 = (upperX - ray.org.x) * ray.rdir_far.x; + const vfloat tFarY0 = (upperY - ray.org.y) * ray.rdir_far.y; + const vfloat tFarZ0 = (upperZ - ray.org.z) * ray.rdir_far.z; + + const vbool parX = ray.dir.x == vfloat(0.0f); + const vbool parY = ray.dir.y == vfloat(0.0f); + const vbool parZ = ray.dir.z == vfloat(0.0f); + + const vbool outX = parX & ((ray.org.x < lowerX) | (ray.org.x > upperX)); + const vbool outY = parY & ((ray.org.y < lowerY) | (ray.org.y > upperY)); + const vbool outZ = parZ & ((ray.org.z < lowerZ) | (ray.org.z > upperZ)); + + const vfloat pinf = std::numeric_limits::infinity(); + const vfloat ninf = -pinf; + const vfloat tNearX = select(parX, ninf, tNearX0); + const vfloat tNearY = select(parY, ninf, tNearY0); + const vfloat tNearZ = select(parZ, ninf, tNearZ0); + const vfloat tFarX = select(parX, pinf, tFarX0); + const vfloat tFarY = select(parY, pinf, tFarY0); + const vfloat tFarZ = select(parZ, pinf, tFarZ0); + const vfloat tNear = max(tNearX,tNearY,tNearZ,ray.tnear); const vfloat tFar = min(tFarX ,tFarY ,tFarZ ,ray.tfar); - const vbool vmask = tNear <= tFar; + const vbool vmask = (tNear <= tFar) & !(outX | outY | outZ); const size_t mask = movemask(vmask); dist = tNear; return mask;