From: Roland Hieber Date: Wed, 3 Feb 2010 00:57:33 +0000 (+0100) Subject: (hopefully) finished Box::Clip() X-Git-Url: https://git.rohieb.name/MicroTrace.git/commitdiff_plain/556bb9d82b766ce68c56844492536525dc2d19d7 (hopefully) finished Box::Clip() --- diff --git a/Box.cxx b/Box.cxx index 9f1ca77..70ab618 100644 --- a/Box.cxx +++ b/Box.cxx @@ -67,41 +67,52 @@ Box::Clip(const Ray& ray, float& tnear, float& tfar) const Vec3f diff_min = m_min - ray.origin(); // o-a Vec3f diff_max = m_max - ray.origin(); - float cos_theta; - float tx_near, tx_far; + float cos_theta, temp; + float tx_near = -Infinity, tx_far = Infinity, + ty_near = -Infinity, ty_far = Infinity, + tz_near = -Infinity, tz_far = Infinity; // clip along x axis - if(cos_theta = ray.direction().dot(Vec3f(1,0,0)) != 0) // if not parallel... + if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0) // if not parallel... tx_near = diff_min.dot(Vec3f(1,0,0)) / cos_theta; - if(cos_theta = ray.direction().dot(Vec3f(1,0,0)) != 0) + if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0) tx_far = diff_max.dot(Vec3f(1,0,0)) / cos_theta; - // clip along y axis - if(cos_theta = ray.direction().dot(Vec3f(0,1,0)) != 0) + // we don't know which is nearer, m_min or m_max, so swap them if neccessary + if(tx_near > tx_far) { + temp = tx_near; + tx_near = tx_far; + tx_far = temp; + } + + // do the same for y axis + if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0) ty_near = diff_min.dot(Vec3f(0,1,0)) / cos_theta; - if(cos_theta = ray.direction().dot(Vec3f(0,0,1)) != 0) + if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0) ty_far = diff_max.dot(Vec3f(0,1,0)) / cos_theta; - - // ray intersects box iff it intersects projection on xy plane - // in this case: tx_near <= ty_near <= tx_far <= ty_far - // or: tx_far <= ty_near <= tx_near <= ty_far - // or: tx_far <= ty_far <= tx_near <= ty_near - // or: tx_near <= ty_far <= tx_far <= ty_near - if(tx_near <= ty_near && tx_far <= ty_near && - tx_near <= ty_far && tx_far <= ty_far) { - - // clip along z axis - if (cos_theta = ray.direction().dot(Vec3f(0, 1, 0)) != 0) - tz_near = diff_min.dot(Vec3f(0, 1, 0)) / cos_theta; - if (cos_theta = ray.direction().dot(Vec3f(0, 0, 1)) != 0) - tz_far = diff_max.dot(Vec3f(0, 1, 0)) / cos_theta; - - } else { - + if(ty_near > ty_far) { + temp = ty_near; + ty_near = ty_far; + ty_far = temp; } - ////////////////////////// + // ...and for z axis + if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0) + tz_near = diff_min.dot(Vec3f(0,0,1)) / cos_theta; + if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0) + tz_far = diff_max.dot(Vec3f(0,0,1)) / cos_theta; + if(tz_near > tz_far) { + temp = tz_near; + tz_near = tz_far; + tz_far = temp; + } + // now the maximum of "near"s is the entry point of the ray, the minimum + // of "far"s is the ray's exit point. Visually speaking: the ray must cross + // all three "near" planes before it can be inside the box. + // Note: If t_near_max > t_far_min, the ray does not intersect the box + tnear = fmax(fmax(tx_near, ty_near), tz_near); + tfar = fmin(fmin(tx_far, ty_far), tz_far); } const Vec3f&