On Thursday, 22 September 2016 19:43:35 UTC+1, Jamie Clarkson wrote:
>
> Sure, as you say for your use case it might be best for you, and you might
> need different information from the test anyway. Usually in a fast ray
> tracer you'd pre-calculate the inverse of the direction components and
> store them (since you do LOTS of ray-bbox intersections for each ray while
> traversing the bounding hierarchies) then the slab test is pure
> multiplication and adds. The branchless version then replaces all branch
> tests with min/max operations. I'd be interested if your div free version
> is faster and doesn't need the precalculation/storage costs.
>
> Cheers,
>
> Jamie
>
>
I'm currently fiddling with the "no-division" version - it's not optimised.
It doesn't actually avoid the division, unless all that is needed is a
true/false (intersects) return - for a function that also returns the
scalar along the ray the division is still needed, but it's not in the
boundary check
Easier to show : Original code (in my first post)
front_n = (x_front - s.X) / v.X
ripY = s.Y + front_n*v.Y
ripZ = s.Z + front_n*v.Z
if (front_n > 0) && (ymin <= ripY && ripY <= ymax) && (zmin <= ripZ && ripZ
<= zmax) { ..etc ..
becomes (completely non-optimized)
front_n_d = (x_front - s.X) // non-divided version
positive = (v.X > 0)
if (front_n_d > ) == positive &&
((ymin-s.Y)*v.X <= front_n_d*v.Y)==positive &&
(front_n_d*v.Y <= (ymax-s.Y)*v.X)==positive &&
((zmin-s.Z)*v.X <= front_n_d*v.Z)==positive &&
(front_n_d*v.Z <= (zmax-s.Z)*v.X))==positive {
..etc..
(terms such as ymin-s.Y are reused many times .. I haven't remove them here
as it obscures the math.)
the obvious alternative is to add an extra if positive .. else .. to
simplify all those ==positive out of the condition.. *either way I'm not
expecting it to be faste*r, but the *numerical errors should be much less*,
since each side has only 1 multiply and 1 add/subtract, whereas the
original form had all the math on one side of the boundary condition -
consisting of a subtract followed by a divide ie (x_front - s.X) / v.X (or
a multiplication by a reciprocal which adds more potential numerical
error), compounded into an additional multiplication and add ie s.Y +
front_n*v.Y - so in terms of numerical accuracy the non-multiply version
should be much better.
however if the condition is true the divide is still required to get the
scalar if needed :
front_n = front_n_d / v.X
So for multiple rays the pre-store of the reciprocal of v.X, v.Y, v.Z still
make sense.
For the usual raytracing bounding boxes a few errors, or slightly oversized
bounding boxes are fine, but in my case the ray-box intersection is used to
generate indexes for a 3d voxel array - so errors here can throw an index
out of range (about 1 in 1 million rays, but still a run time panic for me)
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.