nv_scalar ffast_cos(const nv_scalar x) { // assert: 0 <= fT <= PI/2 // maximum absolute error = 1.1880e-03 // speedup = 2.14 nv_scalar x_sqr = x*x; nv_scalar res = nv_scalar(3.705e-02); res *= x_sqr; res -= nv_scalar(4.967e-01); res *= x_sqr; res += nv_one; return res; }
vec3& cube_map_normal(int i, int x, int y, int cubesize, vec3& v) { nv_scalar s, t, sc, tc; s = (nv_scalar(x) + nv_zero_5) / nv_scalar(cubesize); t = (nv_scalar(y) + nv_zero_5) / nv_scalar(cubesize); sc = s * nv_two - nv_one; tc = t * nv_two - nv_one; switch (i) { case 0: v.x = nv_one; v.y = -tc; v.z = -sc; break; case 1: v.x = -nv_one; v.y = -tc; v.z = sc; break; case 2: v.x = sc; v.y = nv_one; v.z = tc; break; case 3: v.x = sc; v.y = -nv_one; v.z = -tc; break; case 4: v.x = sc; v.y = -tc; v.z = nv_one; break; case 5: v.x = -sc; v.y = -tc; v.z = -nv_one; break; } normalize(v); return v; }
nv_scalar fast_cos(const nv_scalar x) { // assert: 0 <= fT <= PI/2 // maximum absolute error = 2.3082e-09 // speedup = 1.47 nv_scalar x_sqr = x*x; nv_scalar res = nv_scalar(-2.605e-07); res *= x_sqr; res += nv_scalar(2.47609e-05); res *= x_sqr; res -= nv_scalar(1.3888397e-03); res *= x_sqr; res += nv_scalar(4.16666418e-02); res *= x_sqr; res -= nv_scalar(4.999999963e-01); res *= x_sqr; res += nv_one; return res; }
// v is normalized // theta in radians void mat3::set_rot(const nv_scalar& theta, const vec3& v) { nv_scalar ct = nv_scalar(_cos(theta)); nv_scalar st = nv_scalar(_sin(theta)); nv_scalar xx = v.x * v.x; nv_scalar yy = v.y * v.y; nv_scalar zz = v.z * v.z; nv_scalar xy = v.x * v.y; nv_scalar xz = v.x * v.z; nv_scalar yz = v.y * v.z; a00 = xx + ct*(1-xx); a01 = xy + ct*(-xy) + st*-v.z; a02 = xz + ct*(-xz) + st*v.y; a10 = xy + ct*(-xy) + st*v.z; a11 = yy + ct*(1-yy); a12 = yz + ct*(-yz) + st*-v.x; a20 = xz + ct*(-xz) + st*-v.y; a21 = yz + ct*(-yz) + st*v.x; a22 = zz + ct*(1-zz); }
/* * Ok, simulate a track-ball. Project the points onto the virtual * trackball, then figure out the axis of rotation, which is the cross * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) * Note: This is a deformed trackball-- is a trackball in the center, * but is deformed into a hyperbolic sheet of rotation away from the * center. This particular function was chosen after trying out * several variations. * * It is assumed that the arguments to this routine are in the range * (-1.0 ... 1.0) */ quat & trackball(quat& q, vec2& pt1, vec2& pt2, nv_scalar trackballsize) { vec3 a; // Axis of rotation nv_scalar phi; // how much to rotate about axis vec3 d; nv_scalar t; if (pt1.x == pt2.x && pt1.y == pt2.y) { // Zero rotation q = quat_id; return q; } // First, figure out z-coordinates for projection of P1 and P2 to // deformed sphere vec3 p1(pt1.x,pt1.y,tb_project_to_sphere(trackballsize,pt1.x,pt1.y)); vec3 p2(pt2.x,pt2.y,tb_project_to_sphere(trackballsize,pt2.x,pt2.y)); // Now, we want the cross product of P1 and P2 cross(a,p1,p2); // Figure out how much to rotate around that axis. d.x = p1.x - p2.x; d.y = p1.y - p2.y; d.z = p1.z - p2.z; t = _sqrt(d.x * d.x + d.y * d.y + d.z * d.z) / (trackballsize); // Avoid problems with out-of-control values... if (t > nv_one) t = nv_one; if (t < -nv_one) t = -nv_one; phi = nv_two * nv_scalar(asin(t)); axis_to_quat(q,a,phi); return q; }
vec3 & spect_decomp(vec3 & kv, mat3 & S, mat3 & U) { #define X 0 #define Y 1 #define Z 2 #define W 3 vec3 Diag,OffD; // OffD is off-diag (by omitted index) nv_scalar g,h,fabsh,fabsOffDi,t,theta,c,s,tau,ta,OffDq,a,b; static char nxt[] = {Y,Z,X}; U = mat3_id; Diag[X] = S(X,X); Diag[Y] = S(Y,Y); Diag[Z] = S(Z,Z); OffD[X] = S(Y,Z); OffD[Y] = S(Z,X); OffD[Z] = S(X,Y); for (int sweep=20; sweep>0; --sweep) { nv_scalar sm = (fabs(OffD[X])+fabs(OffD[Y])+fabs(OffD[Z])); if (sm == nv_zero) break; for (int i=Z; i>=X; --i) { int p = nxt[i]; int q = nxt[p]; fabsOffDi = fabs(OffD[i]); g = nv_scalar(100.0)*fabsOffDi; if (fabsOffDi > nv_zero) { h = Diag[q] - Diag[p]; fabsh = fabs(h); if (fabsh+g==fabsh) { t = OffD[i]/h; } else { theta = nv_zero_5*h/OffD[i]; t = nv_one/(fabs(theta)+sqrt(theta*theta+nv_one)); if (theta < nv_zero) t = -t; } c = nv_one/sqrt(t*t+nv_one); s = t*c; tau = s/(c+nv_one); ta = t*OffD[i]; OffD[i] = nv_zero; Diag[p] -= ta; Diag[q] += ta; OffDq = OffD[q]; OffD[q] -= s*(OffD[p] + tau*OffD[q]); OffD[p] += s*(OffDq - tau*OffD[p]); for (int j=Z; j>=X; --j) { a = U(j,p); b = U(j,q); U(j,p) -= s*(b + tau*a); U(j,q) += s*(a - tau*b); } } } } kv = Diag; return kv; }