ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/util.C
(Generate patch)

Comparing libgender/util.C (file contents):
Revision 1.2 by root, Sun Oct 3 22:46:03 2004 UTC vs.
Revision 1.3 by root, Sun Oct 3 23:32:57 2004 UTC

1/*
2 * math support
3 * most of the more complicated code is taken from mesa.
4 */
5
1#include <cstdio> // ugly 6#include <cstdio> // ugly
2 7
3#include <cmath> 8#include <cmath>
4 9
5#include <blitz/tinymat.h> 10#include <blitz/tinymat.h>
6 11
7using namespace blitz; 12using namespace blitz;
8 13
9#include "util.h" 14#include "util.h"
10 15
16#define DEG2RAD (M_PI / 180.)
17
11const vec3 normalize (const vec3 &v) 18const vec3 normalize (const vec3 &v)
12{ 19{
13 GLfloat s = 1. / sqrtf (v.x * v.x + v.y * v.y + v.z * v.z); 20 GLfloat s = abs (v);
14 21
22 if (!s)
23 return v;
24
25 s = 1. / s;
15 return vec3 (v.x * s, v.y * s, v.z * s); 26 return vec3 (v.x * s, v.y * s, v.z * s);
16} 27}
17 28
18const vec3 cross (const vec3 &a, const vec3 &b) 29const vec3 cross (const vec3 &a, const vec3 &b)
19{ 30{
20 return vec3 ( 31 return vec3 (
21 a.y * b.z - a.z * b.y, 32 a.y * b.z - a.z * b.y,
22 a.z * b.x - a.x * b.z, 33 a.z * b.x - a.x * b.z,
23 a.x * b.y - a.y * b.x 34 a.x * b.y - a.y * b.x
24 ); 35 );
25}
26
27GLfloat dot (const vec3 &a, const vec3 &b)
28{
29 return a.x * b.x + a.y * b.y + a.z * b.z;
30} 36}
31 37
32void gl_matrix::diagonal (GLfloat v) 38void gl_matrix::diagonal (GLfloat v)
33{ 39{
34 for (int i = 4; i--; ) 40 for (int i = 4; i--; )
38 44
39const gl_matrix operator *(const gl_matrix &a, const gl_matrix &b) 45const gl_matrix operator *(const gl_matrix &a, const gl_matrix &b)
40{ 46{
41 gl_matrix r; 47 gl_matrix r;
42 48
43 int i, j, k; 49 // taken from mesa
44
45 for (i = 0; i < 4; i++) 50 for (int i = 0; i < 4; i++)
46 for (j = 0; j < 4; j++)
47 { 51 {
48 GLfloat s = 0.; 52 const GLfloat ai0=a(i,0), ai1=a(i,1), ai2=a(i,2), ai3=a(i,3);
49 for (k = 0; k < 4; k++)
50 s += a(i,k) * b(k,j);
51 53
52 r(i,j) = s; 54 r(i,0) = ai0 * b(0,0) + ai1 * b(1,0) + ai2 * b(2,0) + ai3 * b(3,0);
55 r(i,1) = ai0 * b(0,1) + ai1 * b(1,1) + ai2 * b(2,1) + ai3 * b(3,1);
56 r(i,2) = ai0 * b(0,2) + ai1 * b(1,2) + ai2 * b(2,2) + ai3 * b(3,2);
57 r(i,3) = ai0 * b(0,3) + ai1 * b(1,3) + ai2 * b(2,3) + ai3 * b(3,3);
53 } 58 }
54 59
55 return r; 60 return r;
61}
62
63void gl_matrix::rotate (GLfloat angle, const vec3 &axis)
64{
65 gl_matrix m;
66 GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
67
68 s = (GLfloat) sinf (angle * DEG2RAD);
69 c = (GLfloat) cosf (angle * DEG2RAD);
70
71 const GLfloat mag = abs (axis);
72
73 if (mag <= 1.0e-4)
74 return; /* no rotation, leave mat as-is */
75
76 const vec3 n = axis * (1. / mag);
77
78 /*
79 * Arbitrary axis rotation matrix.
80 *
81 * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
82 * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
83 * (which is about the X-axis), and the two composite transforms
84 * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
85 * from the arbitrary axis to the X-axis then back. They are
86 * all elementary rotations.
87 *
88 * Rz' is a rotation about the Z-axis, to bring the axis vector
89 * into the x-z plane. Then Ry' is applied, rotating about the
90 * Y-axis to bring the axis vector parallel with the X-axis. The
91 * rotation about the X-axis is then performed. Ry and Rz are
92 * simply the respective inverse transforms to bring the arbitrary
93 * axis back to it's original orientation. The first transforms
94 * Rz' and Ry' are considered inverses, since the data from the
95 * arbitrary axis gives you info on how to get to it, not how
96 * to get away from it, and an inverse must be applied.
97 *
98 * The basic calculation used is to recognize that the arbitrary
99 * axis vector (x, y, z), since it is of unit length, actually
100 * represents the sines and cosines of the angles to rotate the
101 * X-axis to the same orientation, with theta being the angle about
102 * Z and phi the angle about Y (in the order described above)
103 * as follows:
104 *
105 * cos ( theta ) = x / sqrt ( 1 - z^2 )
106 * sin ( theta ) = y / sqrt ( 1 - z^2 )
107 *
108 * cos ( phi ) = sqrt ( 1 - z^2 )
109 * sin ( phi ) = z
110 *
111 * Note that cos ( phi ) can further be inserted to the above
112 * formulas:
113 *
114 * cos ( theta ) = x / cos ( phi )
115 * sin ( theta ) = y / sin ( phi )
116 *
117 * ...etc. Because of those relations and the standard trigonometric
118 * relations, it is pssible to reduce the transforms down to what
119 * is used below. It may be that any primary axis chosen will give the
120 * same results (modulo a sign convention) using this method.
121 *
122 * Particularly nice is to notice that all divisions that might
123 * have caused trouble when parallel to certain planes or
124 * axis go away with care paid to reducing the expressions.
125 * After checking, it does perform correctly under all cases, since
126 * in all the cases of division where the denominator would have
127 * been zero, the numerator would have been zero as well, giving
128 * the expected result.
129 */
130
131 xx = n.x * n.x;
132 yy = n.y * n.y;
133 zz = n.z * n.z;
134 xy = n.x * n.y;
135 yz = n.y * n.z;
136 zx = n.z * n.x;
137 xs = n.x * s;
138 ys = n.y * s;
139 zs = n.z * s;
140 one_c = 1.0F - c;
141
142 m(0,0) = (one_c * xx) + c;
143 m(0,1) = (one_c * xy) - zs;
144 m(0,2) = (one_c * zx) + ys;
145 m(0,3) = 0;
146
147 m(1,0) = (one_c * xy) + zs;
148 m(1,1) = (one_c * yy) + c;
149 m(1,2) = (one_c * yz) - xs;
150 m(1,3) = 0;
151
152 m(2,0) = (one_c * zx) - ys;
153 m(2,1) = (one_c * yz) + xs;
154 m(2,2) = (one_c * zz) + c;
155 m(2,3) = 0;
156
157 m(3,0) = 0;
158 m(3,1) = 0;
159 m(3,2) = 0;
160 m(3,3) = 1;
161
162 (*this) = (*this) * m;
163}
164
165const vec3 operator *(const gl_matrix &a, const vec3 &v)
166{
167 return vec3 (
168 a(0,0) * v.x + a(1,0) * v.y + a(2,0) * v.z + a(3,0),
169 a(0,1) * v.x + a(1,1) * v.y + a(2,1) * v.z + a(3,1),
170 a(0,2) * v.x + a(1,2) * v.y + a(2,2) * v.z + a(3,2)
171 );
56} 172}
57 173
58void gl_matrix::print () 174void gl_matrix::print ()
59{ 175{
60 printf ("\n"); 176 printf ("\n");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines