/* Copyright (c) Mark J. Kilgard, 1998. */ /* This program is freely distributable without licensing fees and is provided without guarantee or warrantee expressed or implied. This program is -not- in the public domain. */ #include #include "glsmapint.h" /* (x,y,z) reflection vector --> (s,t) sphere map coordinates */ int smapRvecToSt(float rvec[3], float st[2]) { double m, recipm; /* In Section 2.10.4 ("Generating texture coordinates") of the OpenGL 1.1 specification, you will find the GL_SPHERE_MAP equations: n' = normal after transformation to eye coordinates u = unit vector from origin to vertex in eye coordinates (rx, ry, rz) = u - 2 * n' * transpose(n') * u m = 2 * sqrt(rx^2 + ry^2 + (rz + 1)^2)) s = rx/m + 0.5 t = ry/m + 0.5 The equation for calculating (rx, ry, rz) is the equation for calculating the reflection vector for a surface and observer. The explanation and derivation for this equation is found in Roger's "Procedural Elements for Computer Graphics" 2nd ed. in Section 5-5 ("Determining the Reflection Vector"). Note that Roger's convention has the Z axis in the opposite direction from the OpenGL convention. */ m = 2 * sqrt(rvec[0]*rvec[0] + rvec[1]*rvec[1] + (rvec[2]+1)*(rvec[2]+1)); if (m == 0.0) { /* Some point on the sphere map perimeter. */ st[0] = 0.0; st[1] = 0.5; return 0; } recipm = 1.0/m; st[0] = rvec[0]*recipm + 0.5; st[1] = rvec[1]*recipm + 0.5; return 1; } /* (s,t) sphere map coordinate --> reflection verctor (x,y,z) */ void smapStToRvec(float *st, float *rvec) { double tmp1, tmp2; /* Using algebra to invert the sphere mapping equations shown above in smapRvecToSt, you get: rx = 2*sqrt(-4*s^2 + 4*s - 4*t^2 + 4*t - 1)*(2*s-1) ry = 2*sqrt(-4*s^2 + 4*s - 4*t^2 + 4*t - 1)*(2*t-1) rz = -8*s^2 + 8*s - 8*t^2 + 8*t - 3 The C code below eliminates common subexpressions. */ tmp1 = st[0]*(1-st[0]) + st[1]*(1-st[1]); tmp2 = 2 * sqrt(4*tmp1 - 1); rvec[0] = tmp2 * (2*st[0]-1); rvec[1] = tmp2 * (2*st[1]-1); rvec[2] = 8 * tmp1 - 3; }