Consistent copyright info (version number, date) across all files.
[mesa.git] / src / mesa / math / m_norm_tmp.h
1 /* $Id: m_norm_tmp.h,v 1.5 2001/03/12 00:48:41 gareth Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 #include <math.h>
32 #include "m_vertices.h"
33
34 static void _XFORMAPI
35 TAG(transform_normalize_normals)( const GLmatrix *mat,
36 GLfloat scale,
37 const GLvector3f *in,
38 const GLfloat *lengths,
39 const GLubyte mask[],
40 GLvector3f *dest )
41 {
42 GLuint i;
43 const GLfloat *from = in->start;
44 GLuint stride = in->stride;
45 GLuint count = in->count;
46 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
47 GLfloat *m = mat->inv;
48 GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
49 GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
50 GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
51
52 (void) mask;
53 if (!lengths) {
54 STRIDE_LOOP {
55 CULL_CHECK {
56 GLfloat tx, ty, tz;
57 {
58 const GLfloat ux = from[0], uy = from[1], uz = from[2];
59 tx = ux * m0 + uy * m1 + uz * m2;
60 ty = ux * m4 + uy * m5 + uz * m6;
61 tz = ux * m8 + uy * m9 + uz * m10;
62 }
63 {
64 GLdouble len = tx*tx + ty*ty + tz*tz;
65 if (len > 1e-20) {
66 GLdouble scale = 1.0 / GL_SQRT(len);
67 out[i][0] = (GLfloat) (tx * scale);
68 out[i][1] = (GLfloat) (ty * scale);
69 out[i][2] = (GLfloat) (tz * scale);
70 }
71 else
72 {
73 out[i][0] = out[i][1] = out[i][2] = 0;
74 }
75 }
76 }
77 }
78 }
79 else {
80 if (scale != 1.0) {
81 m0 *= scale, m4 *= scale, m8 *= scale;
82 m1 *= scale, m5 *= scale, m9 *= scale;
83 m2 *= scale, m6 *= scale, m10 *= scale;
84 }
85
86 STRIDE_LOOP {
87 CULL_CHECK {
88 GLfloat tx, ty, tz;
89 {
90 const GLfloat ux = from[0], uy = from[1], uz = from[2];
91 tx = ux * m0 + uy * m1 + uz * m2;
92 ty = ux * m4 + uy * m5 + uz * m6;
93 tz = ux * m8 + uy * m9 + uz * m10;
94 }
95 {
96 GLfloat len = lengths[i];
97 out[i][0] = tx * len;
98 out[i][1] = ty * len;
99 out[i][2] = tz * len;
100 }
101 }
102 }
103 }
104 dest->count = in->count;
105 }
106
107
108 static void _XFORMAPI
109 TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
110 GLfloat scale,
111 const GLvector3f *in,
112 const GLfloat *lengths,
113 const GLubyte mask[],
114 GLvector3f *dest )
115 {
116 GLuint i;
117 const GLfloat *from = in->start;
118 GLuint stride = in->stride;
119 GLuint count = in->count;
120 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
121 GLfloat *m = mat->inv;
122 GLfloat m0 = m[0];
123 GLfloat m5 = m[5];
124 GLfloat m10 = m[10];
125 (void) mask;
126 if (!lengths) {
127 STRIDE_LOOP {
128 CULL_CHECK {
129 GLfloat tx, ty, tz;
130 {
131 const GLfloat ux = from[0], uy = from[1], uz = from[2];
132 tx = ux * m0 ;
133 ty = uy * m5 ;
134 tz = uz * m10;
135 }
136 {
137 GLdouble len = tx*tx + ty*ty + tz*tz;
138 if (len > 1e-20) {
139 GLdouble scale = 1.0 / GL_SQRT(len);
140 out[i][0] = (GLfloat) (tx * scale);
141 out[i][1] = (GLfloat) (ty * scale);
142 out[i][2] = (GLfloat) (tz * scale);
143 }
144 else
145 {
146 out[i][0] = out[i][1] = out[i][2] = 0;
147 }
148 }
149 }
150 }
151 }
152 else {
153 /* scale has been snapped to 1.0 if it is close.
154 */
155 if (scale != 1.0) {
156 m0 *= scale;
157 m5 *= scale;
158 m10 *= scale;
159 }
160
161 STRIDE_LOOP {
162 CULL_CHECK {
163 GLfloat tx, ty, tz;
164 {
165 const GLfloat ux = from[0], uy = from[1], uz = from[2];
166 tx = ux * m0 ;
167 ty = uy * m5 ;
168 tz = uz * m10;
169 }
170 {
171 GLfloat len = lengths[i];
172 out[i][0] = tx * len;
173 out[i][1] = ty * len;
174 out[i][2] = tz * len;
175 }
176 }
177 }
178 }
179 dest->count = in->count;
180 }
181
182
183 static void _XFORMAPI
184 TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
185 GLfloat scale,
186 const GLvector3f *in,
187 const GLfloat *lengths,
188 const GLubyte mask[],
189 GLvector3f *dest )
190 {
191 GLuint i;
192 const GLfloat *from = in->start;
193 GLuint stride = in->stride;
194 GLuint count = in->count;
195 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
196 const GLfloat *m = mat->inv;
197 GLfloat m0 = scale*m[0];
198 GLfloat m5 = scale*m[5];
199 GLfloat m10 = scale*m[10];
200 (void) lengths;
201 (void) mask;
202 STRIDE_LOOP {
203 CULL_CHECK {
204 GLfloat ux = from[0], uy = from[1], uz = from[2];
205 out[i][0] = ux * m0;
206 out[i][1] = uy * m5;
207 out[i][2] = uz * m10;
208 }
209 }
210 dest->count = in->count;
211 }
212
213 static void _XFORMAPI
214 TAG(transform_rescale_normals)( const GLmatrix *mat,
215 GLfloat scale,
216 const GLvector3f *in,
217 const GLfloat *lengths,
218 const GLubyte mask[],
219 GLvector3f *dest )
220 {
221 GLuint i;
222 const GLfloat *from = in->start;
223 GLuint stride = in->stride;
224 GLuint count = in->count;
225 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
226 /* Since we are unlikely to have < 3 vertices in the buffer,
227 * it makes sense to pre-multiply by scale.
228 */
229 const GLfloat *m = mat->inv;
230 GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
231 GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
232 GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
233 (void) lengths;
234 (void) mask;
235 STRIDE_LOOP {
236 CULL_CHECK {
237 GLfloat ux = from[0], uy = from[1], uz = from[2];
238 out[i][0] = ux * m0 + uy * m1 + uz * m2;
239 out[i][1] = ux * m4 + uy * m5 + uz * m6;
240 out[i][2] = ux * m8 + uy * m9 + uz * m10;
241 }
242 }
243 dest->count = in->count;
244 }
245
246
247 static void _XFORMAPI
248 TAG(transform_normals_no_rot)(const GLmatrix *mat,
249 GLfloat scale,
250 const GLvector3f *in,
251 const GLfloat *lengths,
252 const GLubyte mask[],
253 GLvector3f *dest )
254 {
255 GLuint i;
256 const GLfloat *from = in->start;
257 GLuint stride = in->stride;
258 GLuint count = in->count;
259 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
260 const GLfloat *m = mat->inv;
261 GLfloat m0 = m[0];
262 GLfloat m5 = m[5];
263 GLfloat m10 = m[10];
264 (void) scale;
265 (void) lengths;
266 (void) mask;
267 STRIDE_LOOP {
268 CULL_CHECK {
269 GLfloat ux = from[0], uy = from[1], uz = from[2];
270 out[i][0] = ux * m0;
271 out[i][1] = uy * m5;
272 out[i][2] = uz * m10;
273 }
274 }
275 dest->count = in->count;
276 }
277
278
279 static void _XFORMAPI
280 TAG(transform_normals)( const GLmatrix *mat,
281 GLfloat scale,
282 const GLvector3f *in,
283 const GLfloat *lengths,
284 const GLubyte mask[],
285 GLvector3f *dest )
286 {
287 GLuint i;
288 const GLfloat *from = in->start;
289 GLuint stride = in->stride;
290 GLuint count = in->count;
291 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
292 const GLfloat *m = mat->inv;
293 GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
294 GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
295 GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
296 (void) scale;
297 (void) lengths;
298 (void) mask;
299 STRIDE_LOOP {
300 CULL_CHECK {
301 GLfloat ux = from[0], uy = from[1], uz = from[2];
302 out[i][0] = ux * m0 + uy * m1 + uz * m2;
303 out[i][1] = ux * m4 + uy * m5 + uz * m6;
304 out[i][2] = ux * m8 + uy * m9 + uz * m10;
305 }
306 }
307 dest->count = in->count;
308 }
309
310
311 static void _XFORMAPI
312 TAG(normalize_normals)( const GLmatrix *mat,
313 GLfloat scale,
314 const GLvector3f *in,
315 const GLfloat *lengths,
316 const GLubyte mask[],
317 GLvector3f *dest )
318 {
319 GLuint i;
320 const GLfloat *from = in->start;
321 GLuint stride = in->stride;
322 GLuint count = in->count;
323 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
324 (void) mat;
325 (void) mask;
326 (void) scale;
327 if (lengths) {
328 STRIDE_LOOP {
329 CULL_CHECK {
330 const GLfloat x = from[0], y = from[1], z = from[2];
331 GLfloat invlen = lengths[i];
332 out[i][0] = x * invlen;
333 out[i][1] = y * invlen;
334 out[i][2] = z * invlen;
335 }
336 }
337 }
338 else {
339 STRIDE_LOOP {
340 CULL_CHECK {
341 const GLfloat x = from[0], y = from[1], z = from[2];
342 GLdouble len = x * x + y * y + z * z;
343 if (len > 1e-50) {
344 len = 1.0 / GL_SQRT(len);
345 out[i][0] = (GLfloat) (x * len);
346 out[i][1] = (GLfloat) (y * len);
347 out[i][2] = (GLfloat) (z * len);
348 }
349 else {
350 out[i][0] = x;
351 out[i][1] = y;
352 out[i][2] = z;
353 }
354 }
355 }
356 }
357 dest->count = in->count;
358 }
359
360
361 static void _XFORMAPI
362 TAG(rescale_normals)( const GLmatrix *mat,
363 GLfloat scale,
364 const GLvector3f *in,
365 const GLfloat *lengths,
366 const GLubyte mask[],
367 GLvector3f *dest )
368 {
369 GLuint i;
370 const GLfloat *from = in->start;
371 GLuint stride = in->stride;
372 GLuint count = in->count;
373 GLfloat (*out)[3] = (GLfloat (*)[3])dest->start;
374 (void) mat;
375 (void) lengths;
376 (void) mask;
377
378 STRIDE_LOOP {
379 CULL_CHECK {
380 SCALE_SCALAR_3V( out[i], scale, from );
381 }
382 }
383 dest->count = in->count;
384 }
385
386
387 static void _XFORMAPI
388 TAG(init_c_norm_transform)( void )
389 {
390 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT][IDX] =
391 TAG(transform_normals_no_rot);
392
393 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE][IDX] =
394 TAG(transform_rescale_normals_no_rot);
395
396 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE][IDX] =
397 TAG(transform_normalize_normals_no_rot);
398
399 _mesa_normal_tab[NORM_TRANSFORM][IDX] =
400 TAG(transform_normals);
401
402 _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE][IDX] =
403 TAG(transform_rescale_normals);
404
405 _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE][IDX] =
406 TAG(transform_normalize_normals);
407
408 _mesa_normal_tab[NORM_RESCALE][IDX] =
409 TAG(rescale_normals);
410
411 _mesa_normal_tab[NORM_NORMALIZE][IDX] =
412 TAG(normalize_normals);
413 }