comments, clean-ups, added lots of const qualifiers
[mesa.git] / src / mesa / math / m_norm_tmp.h
1 /* $Id: m_norm_tmp.h,v 1.9 2002/01/05 14:12:24 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 /*
28 * New (3.1) transformation code written by Keith Whitwell.
29 */
30
31 /* Functions to tranform a vector of normals. This includes applying
32 * the transformation matrix, rescaling and normalization.
33 */
34
35 #include <math.h>
36 #include "m_vertices.h"
37
38
39 /*
40 * mat - the 4x4 transformation matrix
41 * scale - uniform scale factor of the transformation matrix (not always used)
42 * in - the source vector of normals
43 * lengths - length of each incoming normal (may be NULL) (a display list
44 * optimization)
45 * dest - the destination vector of normals
46 */
47 static void _XFORMAPI
48 TAG(transform_normalize_normals)( const GLmatrix *mat,
49 GLfloat scale,
50 const GLvector3f *in,
51 const GLfloat *lengths,
52 GLvector3f *dest )
53 {
54 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
55 const GLfloat *from = in->start;
56 const GLuint stride = in->stride;
57 const GLuint count = in->count;
58 const GLfloat *m = mat->inv;
59 GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
60 GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
61 GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
62 GLuint i;
63
64 if (!lengths) {
65 STRIDE_LOOP {
66 GLfloat tx, ty, tz;
67 {
68 const GLfloat ux = from[0], uy = from[1], uz = from[2];
69 tx = ux * m0 + uy * m1 + uz * m2;
70 ty = ux * m4 + uy * m5 + uz * m6;
71 tz = ux * m8 + uy * m9 + uz * m10;
72 }
73 {
74 GLdouble len = tx*tx + ty*ty + tz*tz;
75 if (len > 1e-20) {
76 GLdouble scale = 1.0 / GL_SQRT(len);
77 out[i][0] = (GLfloat) (tx * scale);
78 out[i][1] = (GLfloat) (ty * scale);
79 out[i][2] = (GLfloat) (tz * scale);
80 }
81 else {
82 out[i][0] = out[i][1] = out[i][2] = 0;
83 }
84 }
85 }
86 }
87 else {
88 if (scale != 1.0) {
89 m0 *= scale, m4 *= scale, m8 *= scale;
90 m1 *= scale, m5 *= scale, m9 *= scale;
91 m2 *= scale, m6 *= scale, m10 *= scale;
92 }
93
94 STRIDE_LOOP {
95 GLfloat tx, ty, tz;
96 {
97 const GLfloat ux = from[0], uy = from[1], uz = from[2];
98 tx = ux * m0 + uy * m1 + uz * m2;
99 ty = ux * m4 + uy * m5 + uz * m6;
100 tz = ux * m8 + uy * m9 + uz * m10;
101 }
102 {
103 GLfloat len = lengths[i];
104 out[i][0] = tx * len;
105 out[i][1] = ty * len;
106 out[i][2] = tz * len;
107 }
108 }
109 }
110 dest->count = in->count;
111 }
112
113
114 static void _XFORMAPI
115 TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
116 GLfloat scale,
117 const GLvector3f *in,
118 const GLfloat *lengths,
119 GLvector3f *dest )
120 {
121 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
122 const GLfloat *from = in->start;
123 const GLuint stride = in->stride;
124 const GLuint count = in->count;
125 const GLfloat *m = mat->inv;
126 GLfloat m0 = m[0];
127 GLfloat m5 = m[5];
128 GLfloat m10 = m[10];
129 GLuint i;
130
131 if (!lengths) {
132 STRIDE_LOOP {
133 GLfloat tx, ty, tz;
134 {
135 const GLfloat ux = from[0], uy = from[1], uz = from[2];
136 tx = ux * m0 ;
137 ty = uy * m5 ;
138 tz = uz * m10;
139 }
140 {
141 GLdouble len = tx*tx + ty*ty + tz*tz;
142 if (len > 1e-20) {
143 GLdouble scale = 1.0 / GL_SQRT(len);
144 out[i][0] = (GLfloat) (tx * scale);
145 out[i][1] = (GLfloat) (ty * scale);
146 out[i][2] = (GLfloat) (tz * scale);
147 }
148 else {
149 out[i][0] = out[i][1] = out[i][2] = 0;
150 }
151 }
152 }
153 }
154 else {
155 m0 *= scale;
156 m5 *= scale;
157 m10 *= scale;
158
159 STRIDE_LOOP {
160 GLfloat tx, ty, tz;
161 {
162 const GLfloat ux = from[0], uy = from[1], uz = from[2];
163 tx = ux * m0 ;
164 ty = uy * m5 ;
165 tz = uz * m10;
166 }
167 {
168 GLfloat len = lengths[i];
169 out[i][0] = tx * len;
170 out[i][1] = ty * len;
171 out[i][2] = tz * len;
172 }
173 }
174 }
175 dest->count = in->count;
176 }
177
178
179 static void _XFORMAPI
180 TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
181 GLfloat scale,
182 const GLvector3f *in,
183 const GLfloat *lengths,
184 GLvector3f *dest )
185 {
186 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
187 const GLfloat *from = in->start;
188 const GLuint stride = in->stride;
189 const GLuint count = in->count;
190 const GLfloat *m = mat->inv;
191 const GLfloat m0 = scale*m[0];
192 const GLfloat m5 = scale*m[5];
193 const GLfloat m10 = scale*m[10];
194 GLuint i;
195
196 (void) lengths;
197
198 STRIDE_LOOP {
199 GLfloat ux = from[0], uy = from[1], uz = from[2];
200 out[i][0] = ux * m0;
201 out[i][1] = uy * m5;
202 out[i][2] = uz * m10;
203 }
204 dest->count = in->count;
205 }
206
207
208 static void _XFORMAPI
209 TAG(transform_rescale_normals)( const GLmatrix *mat,
210 GLfloat scale,
211 const GLvector3f *in,
212 const GLfloat *lengths,
213 GLvector3f *dest )
214 {
215 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
216 const GLfloat *from = in->start;
217 const GLuint stride = in->stride;
218 const GLuint count = in->count;
219 /* Since we are unlikely to have < 3 vertices in the buffer,
220 * it makes sense to pre-multiply by scale.
221 */
222 const GLfloat *m = mat->inv;
223 const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
224 const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
225 const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
226 GLuint i;
227
228 (void) lengths;
229
230 STRIDE_LOOP {
231 GLfloat ux = from[0], uy = from[1], uz = from[2];
232 out[i][0] = ux * m0 + uy * m1 + uz * m2;
233 out[i][1] = ux * m4 + uy * m5 + uz * m6;
234 out[i][2] = ux * m8 + uy * m9 + uz * m10;
235 }
236 dest->count = in->count;
237 }
238
239
240 static void _XFORMAPI
241 TAG(transform_normals_no_rot)( const GLmatrix *mat,
242 GLfloat scale,
243 const GLvector3f *in,
244 const GLfloat *lengths,
245 GLvector3f *dest )
246 {
247 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
248 const GLfloat *from = in->start;
249 const GLuint stride = in->stride;
250 const GLuint count = in->count;
251 const GLfloat *m = mat->inv;
252 const GLfloat m0 = m[0];
253 const GLfloat m5 = m[5];
254 const GLfloat m10 = m[10];
255 GLuint i;
256
257 (void) scale;
258 (void) lengths;
259
260 STRIDE_LOOP {
261 GLfloat ux = from[0], uy = from[1], uz = from[2];
262 out[i][0] = ux * m0;
263 out[i][1] = uy * m5;
264 out[i][2] = uz * m10;
265 }
266 dest->count = in->count;
267 }
268
269
270 static void _XFORMAPI
271 TAG(transform_normals)( const GLmatrix *mat,
272 GLfloat scale,
273 const GLvector3f *in,
274 const GLfloat *lengths,
275 GLvector3f *dest )
276 {
277 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
278 const GLfloat *from = in->start;
279 const GLuint stride = in->stride;
280 const GLuint count = in->count;
281 const GLfloat *m = mat->inv;
282 const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
283 const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
284 const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
285 GLuint i;
286
287 (void) scale;
288 (void) lengths;
289
290 STRIDE_LOOP {
291 GLfloat ux = from[0], uy = from[1], uz = from[2];
292 out[i][0] = ux * m0 + uy * m1 + uz * m2;
293 out[i][1] = ux * m4 + uy * m5 + uz * m6;
294 out[i][2] = ux * m8 + uy * m9 + uz * m10;
295 }
296 dest->count = in->count;
297 }
298
299
300 static void _XFORMAPI
301 TAG(normalize_normals)( const GLmatrix *mat,
302 GLfloat scale,
303 const GLvector3f *in,
304 const GLfloat *lengths,
305 GLvector3f *dest )
306 {
307 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
308 const GLfloat *from = in->start;
309 const GLuint stride = in->stride;
310 const GLuint count = in->count;
311 GLuint i;
312
313 (void) mat;
314 (void) scale;
315
316 if (lengths) {
317 STRIDE_LOOP {
318 const GLfloat x = from[0], y = from[1], z = from[2];
319 GLfloat invlen = lengths[i];
320 out[i][0] = x * invlen;
321 out[i][1] = y * invlen;
322 out[i][2] = z * invlen;
323 }
324 }
325 else {
326 STRIDE_LOOP {
327 const GLfloat x = from[0], y = from[1], z = from[2];
328 GLdouble len = x * x + y * y + z * z;
329 if (len > 1e-50) {
330 len = 1.0 / GL_SQRT(len);
331 out[i][0] = (GLfloat) (x * len);
332 out[i][1] = (GLfloat) (y * len);
333 out[i][2] = (GLfloat) (z * len);
334 }
335 else {
336 out[i][0] = x;
337 out[i][1] = y;
338 out[i][2] = z;
339 }
340 }
341 }
342 dest->count = in->count;
343 }
344
345
346 static void _XFORMAPI
347 TAG(rescale_normals)( const GLmatrix *mat,
348 GLfloat scale,
349 const GLvector3f *in,
350 const GLfloat *lengths,
351 GLvector3f *dest )
352 {
353 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
354 const GLfloat *from = in->start;
355 const GLuint stride = in->stride;
356 const GLuint count = in->count;
357 GLuint i;
358
359 (void) mat;
360 (void) lengths;
361
362 STRIDE_LOOP {
363 SCALE_SCALAR_3V( out[i], scale, from );
364 }
365 dest->count = in->count;
366 }
367
368
369 static void _XFORMAPI
370 TAG(init_c_norm_transform)( void )
371 {
372 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
373 TAG(transform_normals_no_rot);
374
375 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
376 TAG(transform_rescale_normals_no_rot);
377
378 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
379 TAG(transform_normalize_normals_no_rot);
380
381 _mesa_normal_tab[NORM_TRANSFORM] =
382 TAG(transform_normals);
383
384 _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
385 TAG(transform_rescale_normals);
386
387 _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
388 TAG(transform_normalize_normals);
389
390 _mesa_normal_tab[NORM_RESCALE] =
391 TAG(rescale_normals);
392
393 _mesa_normal_tab[NORM_NORMALIZE] =
394 TAG(normalize_normals);
395 }