3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
28 * New (3.1) transformation code written by Keith Whitwell.
31 /* Functions to tranform a vector of normals. This includes applying
32 * the transformation matrix, rescaling and normalization.
36 * mat - the 4x4 transformation matrix
37 * scale - uniform scale factor of the transformation matrix (not always used)
38 * in - the source vector of normals
39 * lengths - length of each incoming normal (may be NULL) (a display list
41 * dest - the destination vector of normals
44 TAG(transform_normalize_normals)( const GLmatrix *mat,
47 const GLfloat *lengths,
50 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
51 const GLfloat *from = in->start;
52 const GLuint stride = in->stride;
53 const GLuint count = in->count;
54 const GLfloat *m = mat->inv;
55 GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
56 GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
57 GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
64 const GLfloat ux = from[0], uy = from[1], uz = from[2];
65 tx = ux * m0 + uy * m1 + uz * m2;
66 ty = ux * m4 + uy * m5 + uz * m6;
67 tz = ux * m8 + uy * m9 + uz * m10;
70 GLdouble len = tx*tx + ty*ty + tz*tz;
72 GLfloat scale = INV_SQRTF(len);
73 out[i][0] = tx * scale;
74 out[i][1] = ty * scale;
75 out[i][2] = tz * scale;
78 out[i][0] = out[i][1] = out[i][2] = 0;
85 m0 *= scale, m4 *= scale, m8 *= scale;
86 m1 *= scale, m5 *= scale, m9 *= scale;
87 m2 *= scale, m6 *= scale, m10 *= scale;
93 const GLfloat ux = from[0], uy = from[1], uz = from[2];
94 tx = ux * m0 + uy * m1 + uz * m2;
95 ty = ux * m4 + uy * m5 + uz * m6;
96 tz = ux * m8 + uy * m9 + uz * m10;
99 GLfloat len = lengths[i];
100 out[i][0] = tx * len;
101 out[i][1] = ty * len;
102 out[i][2] = tz * len;
106 dest->count = in->count;
110 static void _XFORMAPI
111 TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
113 const GLvector4f *in,
114 const GLfloat *lengths,
117 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
118 const GLfloat *from = in->start;
119 const GLuint stride = in->stride;
120 const GLuint count = in->count;
121 const GLfloat *m = mat->inv;
131 const GLfloat ux = from[0], uy = from[1], uz = from[2];
137 GLdouble len = tx*tx + ty*ty + tz*tz;
139 GLfloat scale = INV_SQRTF(len);
140 out[i][0] = tx * scale;
141 out[i][1] = ty * scale;
142 out[i][2] = tz * scale;
145 out[i][0] = out[i][1] = out[i][2] = 0;
158 const GLfloat ux = from[0], uy = from[1], uz = from[2];
164 GLfloat len = lengths[i];
165 out[i][0] = tx * len;
166 out[i][1] = ty * len;
167 out[i][2] = tz * len;
171 dest->count = in->count;
175 static void _XFORMAPI
176 TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
178 const GLvector4f *in,
179 const GLfloat *lengths,
182 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
183 const GLfloat *from = in->start;
184 const GLuint stride = in->stride;
185 const GLuint count = in->count;
186 const GLfloat *m = mat->inv;
187 const GLfloat m0 = scale*m[0];
188 const GLfloat m5 = scale*m[5];
189 const GLfloat m10 = scale*m[10];
195 GLfloat ux = from[0], uy = from[1], uz = from[2];
198 out[i][2] = uz * m10;
200 dest->count = in->count;
204 static void _XFORMAPI
205 TAG(transform_rescale_normals)( const GLmatrix *mat,
207 const GLvector4f *in,
208 const GLfloat *lengths,
211 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
212 const GLfloat *from = in->start;
213 const GLuint stride = in->stride;
214 const GLuint count = in->count;
215 /* Since we are unlikely to have < 3 vertices in the buffer,
216 * it makes sense to pre-multiply by scale.
218 const GLfloat *m = mat->inv;
219 const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
220 const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
221 const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
227 GLfloat ux = from[0], uy = from[1], uz = from[2];
228 out[i][0] = ux * m0 + uy * m1 + uz * m2;
229 out[i][1] = ux * m4 + uy * m5 + uz * m6;
230 out[i][2] = ux * m8 + uy * m9 + uz * m10;
232 dest->count = in->count;
236 static void _XFORMAPI
237 TAG(transform_normals_no_rot)( const GLmatrix *mat,
239 const GLvector4f *in,
240 const GLfloat *lengths,
243 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
244 const GLfloat *from = in->start;
245 const GLuint stride = in->stride;
246 const GLuint count = in->count;
247 const GLfloat *m = mat->inv;
248 const GLfloat m0 = m[0];
249 const GLfloat m5 = m[5];
250 const GLfloat m10 = m[10];
257 GLfloat ux = from[0], uy = from[1], uz = from[2];
260 out[i][2] = uz * m10;
262 dest->count = in->count;
266 static void _XFORMAPI
267 TAG(transform_normals)( const GLmatrix *mat,
269 const GLvector4f *in,
270 const GLfloat *lengths,
273 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
274 const GLfloat *from = in->start;
275 const GLuint stride = in->stride;
276 const GLuint count = in->count;
277 const GLfloat *m = mat->inv;
278 const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
279 const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
280 const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
287 GLfloat ux = from[0], uy = from[1], uz = from[2];
288 out[i][0] = ux * m0 + uy * m1 + uz * m2;
289 out[i][1] = ux * m4 + uy * m5 + uz * m6;
290 out[i][2] = ux * m8 + uy * m9 + uz * m10;
292 dest->count = in->count;
296 static void _XFORMAPI
297 TAG(normalize_normals)( const GLmatrix *mat,
299 const GLvector4f *in,
300 const GLfloat *lengths,
303 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
304 const GLfloat *from = in->start;
305 const GLuint stride = in->stride;
306 const GLuint count = in->count;
314 const GLfloat x = from[0], y = from[1], z = from[2];
315 GLfloat invlen = lengths[i];
316 out[i][0] = x * invlen;
317 out[i][1] = y * invlen;
318 out[i][2] = z * invlen;
323 const GLfloat x = from[0], y = from[1], z = from[2];
324 GLdouble len = x * x + y * y + z * z;
326 len = INV_SQRTF(len);
327 out[i][0] = (GLfloat)(x * len);
328 out[i][1] = (GLfloat)(y * len);
329 out[i][2] = (GLfloat)(z * len);
338 dest->count = in->count;
342 static void _XFORMAPI
343 TAG(rescale_normals)( const GLmatrix *mat,
345 const GLvector4f *in,
346 const GLfloat *lengths,
349 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
350 const GLfloat *from = in->start;
351 const GLuint stride = in->stride;
352 const GLuint count = in->count;
359 SCALE_SCALAR_3V( out[i], scale, from );
361 dest->count = in->count;
365 static void _XFORMAPI
366 TAG(init_c_norm_transform)( void )
368 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
369 TAG(transform_normals_no_rot);
371 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
372 TAG(transform_rescale_normals_no_rot);
374 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
375 TAG(transform_normalize_normals_no_rot);
377 _mesa_normal_tab[NORM_TRANSFORM] =
378 TAG(transform_normals);
380 _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
381 TAG(transform_rescale_normals);
383 _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
384 TAG(transform_normalize_normals);
386 _mesa_normal_tab[NORM_RESCALE] =
387 TAG(rescale_normals);
389 _mesa_normal_tab[NORM_NORMALIZE] =
390 TAG(normalize_normals);