*. I am messing with my Swift ray tracer and just looked around for the "best known method". This routine is always annoyingly inelegant in my code so I was hoping for something better. Some googling yeilded a lovely paper by Jeppe Revall Frisvad. He builds the basis with no normalization required:*

**n**It's not obvious, but those are orthonormal. The catch is the case where 1-nz = 0 so unfortunately an if is needed:

Still even with the branch it is very nice. I was hoping that a careful use of IEEE floating point rules would allow the branch to be avoided but I don't see it. But perhaps some clever person will see a reconstructing. The terms 0*0/0 should be a zero in principle and then all works out. The good news is that for n.z near 1.0 the stability looks good.

## 1 comment:

This is great! Here is my variant:

if ( n.z >= n.y ) {

const float a = 1.0f/(1.0f + n.z);

const float b = -n.x*n.y*a;

b1 = Vec3f( 1.0f - n.x*n.x*a, b, -n.x );

b2 = Vec3f( b, 1.0f - n.y*n.y*a, -n.y );

} else {

const float a = 1.0f/(1.0f + n.y);

const float b = -n.x*n.z*a;

b1 = Vec3f( b, -n.z, 1.0f - n.z*n.z*a );

b2 = Vec3f( 1.0f - n.x*n.x*a, -n.x, b );

}

This one also has a branch, but it is marginally faster with MSVC. More importantly, it doesn't have a singularity, so it behaves better numerically (no division by a very small number).

Post a Comment