ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/util.C
Revision: 1.9
Committed: Mon Oct 4 23:44:54 2004 UTC (19 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.8: +14 -15 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * math support
3 * most of the more complicated code is taken from mesa.
4 */
5
6 #include <cstdio> // ugly
7 #include <cmath>
8
9 #include <sys/time.h>
10 #include <time.h>
11
12 #include "util.h"
13
14 #define DEG2RAD (M_PI / 180.)
15
16 void renormalize (sector &s, point &p)
17 {
18 float i;
19
20 p.x = modff (p.x, &i); s.x += (int)i;
21 p.y = modff (p.y, &i); s.y += (int)i;
22 p.z = modff (p.z, &i); s.z += (int)i;
23 }
24
25 /////////////////////////////////////////////////////////////////////////////
26
27 const vec3 normalize (const vec3 &v)
28 {
29 GLfloat s = abs (v);
30
31 if (!s)
32 return v;
33
34 s = 1. / s;
35 return vec3 (v.x * s, v.y * s, v.z * s);
36 }
37
38 const vec3 cross (const vec3 &a, const vec3 &b)
39 {
40 return vec3 (
41 a.y * b.z - a.z * b.y,
42 a.z * b.x - a.x * b.z,
43 a.x * b.y - a.y * b.x
44 );
45 }
46
47 /////////////////////////////////////////////////////////////////////////////
48
49 void gl_matrix::diagonal (GLfloat v)
50 {
51 for (int i = 4; i--; )
52 for (int j = 4; j--; )
53 data[i][j] = i == j ? v : 0.;
54 }
55
56 const gl_matrix operator *(const gl_matrix &a, const gl_matrix &b)
57 {
58 gl_matrix r;
59
60 // taken from mesa
61 for (int i = 0; i < 4; i++)
62 {
63 const GLfloat ai0=a(i,0), ai1=a(i,1), ai2=a(i,2), ai3=a(i,3);
64
65 r(i,0) = ai0 * b(0,0) + ai1 * b(1,0) + ai2 * b(2,0) + ai3 * b(3,0);
66 r(i,1) = ai0 * b(0,1) + ai1 * b(1,1) + ai2 * b(2,1) + ai3 * b(3,1);
67 r(i,2) = ai0 * b(0,2) + ai1 * b(1,2) + ai2 * b(2,2) + ai3 * b(3,2);
68 r(i,3) = ai0 * b(0,3) + ai1 * b(1,3) + ai2 * b(2,3) + ai3 * b(3,3);
69 }
70
71 return r;
72 }
73
74 const gl_matrix gl_matrix::rotation (GLfloat angle, const vec3 &axis)
75 {
76 GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
77
78 s = (GLfloat) sinf (angle * DEG2RAD);
79 c = (GLfloat) cosf (angle * DEG2RAD);
80
81 const GLfloat mag = abs (axis);
82
83 if (mag <= 1.0e-4)
84 return gl_matrix (1);
85
86 gl_matrix m;
87 const vec3 n = axis * (1. / mag);
88
89 /*
90 * Arbitrary axis rotation matrix.
91 *
92 * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
93 * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
94 * (which is about the X-axis), and the two composite transforms
95 * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
96 * from the arbitrary axis to the X-axis then back. They are
97 * all elementary rotations.
98 *
99 * Rz' is a rotation about the Z-axis, to bring the axis vector
100 * into the x-z plane. Then Ry' is applied, rotating about the
101 * Y-axis to bring the axis vector parallel with the X-axis. The
102 * rotation about the X-axis is then performed. Ry and Rz are
103 * simply the respective inverse transforms to bring the arbitrary
104 * axis back to it's original orientation. The first transforms
105 * Rz' and Ry' are considered inverses, since the data from the
106 * arbitrary axis gives you info on how to get to it, not how
107 * to get away from it, and an inverse must be applied.
108 *
109 * The basic calculation used is to recognize that the arbitrary
110 * axis vector (x, y, z), since it is of unit length, actually
111 * represents the sines and cosines of the angles to rotate the
112 * X-axis to the same orientation, with theta being the angle about
113 * Z and phi the angle about Y (in the order described above)
114 * as follows:
115 *
116 * cos ( theta ) = x / sqrt ( 1 - z^2 )
117 * sin ( theta ) = y / sqrt ( 1 - z^2 )
118 *
119 * cos ( phi ) = sqrt ( 1 - z^2 )
120 * sin ( phi ) = z
121 *
122 * Note that cos ( phi ) can further be inserted to the above
123 * formulas:
124 *
125 * cos ( theta ) = x / cos ( phi )
126 * sin ( theta ) = y / sin ( phi )
127 *
128 * ...etc. Because of those relations and the standard trigonometric
129 * relations, it is pssible to reduce the transforms down to what
130 * is used below. It may be that any primary axis chosen will give the
131 * same results (modulo a sign convention) using this method.
132 *
133 * Particularly nice is to notice that all divisions that might
134 * have caused trouble when parallel to certain planes or
135 * axis go away with care paid to reducing the expressions.
136 * After checking, it does perform correctly under all cases, since
137 * in all the cases of division where the denominator would have
138 * been zero, the numerator would have been zero as well, giving
139 * the expected result.
140 */
141
142 xx = n.x * n.x;
143 yy = n.y * n.y;
144 zz = n.z * n.z;
145 xy = n.x * n.y;
146 yz = n.y * n.z;
147 zx = n.z * n.x;
148 xs = n.x * s;
149 ys = n.y * s;
150 zs = n.z * s;
151 one_c = 1.0F - c;
152
153 m(0,0) = (one_c * xx) + c;
154 m(0,1) = (one_c * xy) - zs;
155 m(0,2) = (one_c * zx) + ys;
156 m(0,3) = 0;
157
158 m(1,0) = (one_c * xy) + zs;
159 m(1,1) = (one_c * yy) + c;
160 m(1,2) = (one_c * yz) - xs;
161 m(1,3) = 0;
162
163 m(2,0) = (one_c * zx) - ys;
164 m(2,1) = (one_c * yz) + xs;
165 m(2,2) = (one_c * zz) + c;
166 m(2,3) = 0;
167
168 m(3,0) = 0;
169 m(3,1) = 0;
170 m(3,2) = 0;
171 m(3,3) = 1;
172
173 return m;
174 }
175
176 const vec3 operator *(const gl_matrix &a, const vec3 &v)
177 {
178 return vec3 (
179 a(0,0) * v.x + a(0,1) * v.y + a(0,2) * v.z + a(0,3),
180 a(1,0) * v.x + a(1,1) * v.y + a(1,2) * v.z + a(1,3),
181 a(2,0) * v.x + a(2,1) * v.y + a(2,2) * v.z + a(2,3)
182 );
183 }
184
185 void gl_matrix::print ()
186 {
187 printf ("\n");
188 printf ("[ %f, %f, %f, %f ]\n", data[0][0], data[1][0], data[2][0], data[3][0]);
189 printf ("[ %f, %f, %f, %f ]\n", data[0][1], data[1][1], data[2][1], data[3][1]);
190 printf ("[ %f, %f, %f, %f ]\n", data[0][2], data[1][2], data[2][2], data[3][2]);
191 printf ("[ %f, %f, %f, %f ]\n", data[0][3], data[1][3], data[2][3], data[3][3]);
192 }
193
194 const gl_matrix gl_matrix::translation (const vec3 &v)
195 {
196 gl_matrix m(1);
197
198 m(0,3) = v.x;
199 m(1,3) = v.y;
200 m(2,3) = v.z;
201
202 return m;
203 }
204
205 /////////////////////////////////////////////////////////////////////////////
206
207 plane::plane (GLfloat a, GLfloat b, GLfloat c, GLfloat d)
208 : n (vec3 (a,b,c))
209 {
210 GLfloat s = 1. / abs (n);
211
212 n = n * s;
213 this->d = d * s;
214 }
215
216 /////////////////////////////////////////////////////////////////////////////
217
218 void box::add (const box &o)
219 {
220 a.x = min (a.x, o.a.x);
221 a.y = min (a.y, o.a.y);
222 a.z = min (a.z, o.a.z);
223 b.x = max (b.x, o.b.x);
224 b.y = max (b.y, o.b.y);
225 b.z = max (b.z, o.b.z);
226 }
227
228 void box::add (const sector &p)
229 {
230 a.x = min (a.x, p.x);
231 a.y = min (a.y, p.y);
232 a.z = min (a.z, p.z);
233 b.x = max (b.x, p.x);
234 b.y = max (b.y, p.y);
235 b.z = max (b.z, p.z);
236 }
237
238 void box::add (const point &p)
239 {
240 a.x = min (a.x, (soffs)floorf (p.x));
241 a.y = min (a.y, (soffs)floorf (p.y));
242 a.z = min (a.z, (soffs)floorf (p.z));
243 b.x = max (b.x, (soffs)ceilf (p.x));
244 b.y = max (b.y, (soffs)ceilf (p.y));
245 b.z = max (b.z, (soffs)ceilf (p.z));
246 }
247
248 /////////////////////////////////////////////////////////////////////////////
249
250 struct timer timer;
251 static double base;
252 double timer::now = 0.;
253 double timer::diff;
254
255 void timer::frame ()
256 {
257 struct timeval tv;
258 gettimeofday (&tv, 0);
259
260 double next = tv.tv_sec - base + tv.tv_usec / 1.e6;
261
262 diff = next - now;
263 now = next;
264 }
265
266 timer::timer ()
267 {
268 struct timeval tv;
269 gettimeofday (&tv, 0);
270 base = tv.tv_sec + tv.tv_usec / 1.e6;
271 }
272
273 skedjuhlar main_scheduler;