raytracing.github.io icon indicating copy to clipboard operation
raytracing.github.io copied to clipboard

Book 3 8.3: onb class, axis calculation for u and v should be swapped

Open elegracer opened this issue 9 months ago • 1 comments

class onb {
  public:
    onb(const vec3& n) {
        axis[2] = unit_vector(n);
        vec3 a = (std::fabs(axis[2].x()) > 0.9) ? vec3(0,1,0) : vec3(1,0,0);
        axis[1] = unit_vector(cross(axis[2], a));
        axis[0] = cross(axis[2], axis[1]);
    }

    const vec3& u() const { return axis[0]; }
    const vec3& v() const { return axis[1]; }
    const vec3& w() const { return axis[2]; }

    vec3 transform(const vec3& v) const {
        // Transform from basis coordinates to local space.
        return (v[0] * axis[0]) + (v[1] * axis[1]) + (v[2] * axis[2]);
    }

  private:
    vec3 axis[3];
};

According to the code in vec3.h and the whole context, the following statements are true:

  1. The coordinate system is right-handed.
  2. order of axis[3] is u, v, w where w is the normal vector in basis coordinate.

Then to make sense, the constructor should be like this,

axis[0] = unit_vector(cross(axis[2], a));
axis[1] = cross(axis[2], axis[0]); // w cross u is v

to make the final result satisfy the following statements,

\begin{align}
\vec{\bf{w}} = \vec{\bf{u}} \times \vec{\bf{v}} \\
\vec{\bf{u}} = \vec{\bf{v}} \times \vec{\bf{w}} \\
\vec{\bf{v}} = \vec{\bf{w}} \times \vec{\bf{u}}
\end{align}

elegracer avatar Apr 30 '25 10:04 elegracer

Yeah, I think so. (It won’t actually affect rendering in this code, but I’m still inclined to change it for clearer understanding.)

Xlucidator avatar Aug 17 '25 13:08 Xlucidator