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