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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * New (3.1) transformation code written by Keith Whitwell.
30 /* Functions to tranform a vector of normals. This includes applying
31 * the transformation matrix, rescaling and normalization.
35 * mat - the 4x4 transformation matrix
36 * scale - uniform scale factor of the transformation matrix (not always used)
37 * in - the source vector of normals
38 * lengths - length of each incoming normal (may be NULL) (a display list
40 * dest - the destination vector of normals
43 TAG(transform_normalize_normals)( const GLmatrix *mat,
46 const GLfloat *lengths,
49 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
50 const GLfloat *from = in->start;
51 const GLuint stride = in->stride;
52 const GLuint count = in->count;
53 const GLfloat *m = mat->inv;
54 GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
55 GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
56 GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
63 const GLfloat ux = from[0], uy = from[1], uz = from[2];
64 tx = ux * m0 + uy * m1 + uz * m2;
65 ty = ux * m4 + uy * m5 + uz * m6;
66 tz = ux * m8 + uy * m9 + uz * m10;
69 GLdouble len = tx*tx + ty*ty + tz*tz;
71 GLfloat scale = INV_SQRTF(len);
72 out[i][0] = tx * scale;
73 out[i][1] = ty * scale;
74 out[i][2] = tz * scale;
77 out[i][0] = out[i][1] = out[i][2] = 0;
84 m0 *= scale, m4 *= scale, m8 *= scale;
85 m1 *= scale, m5 *= scale, m9 *= scale;
86 m2 *= scale, m6 *= scale, m10 *= scale;
92 const GLfloat ux = from[0], uy = from[1], uz = from[2];
93 tx = ux * m0 + uy * m1 + uz * m2;
94 ty = ux * m4 + uy * m5 + uz * m6;
95 tz = ux * m8 + uy * m9 + uz * m10;
98 GLfloat len = lengths[i];
100 out[i][1] = ty * len;
101 out[i][2] = tz * len;
105 dest->count = in->count;
109 static void _XFORMAPI
110 TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
112 const GLvector4f *in,
113 const GLfloat *lengths,
116 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
117 const GLfloat *from = in->start;
118 const GLuint stride = in->stride;
119 const GLuint count = in->count;
120 const GLfloat *m = mat->inv;
130 const GLfloat ux = from[0], uy = from[1], uz = from[2];
136 GLdouble len = tx*tx + ty*ty + tz*tz;
138 GLfloat scale = INV_SQRTF(len);
139 out[i][0] = tx * scale;
140 out[i][1] = ty * scale;
141 out[i][2] = tz * scale;
144 out[i][0] = out[i][1] = out[i][2] = 0;
157 const GLfloat ux = from[0], uy = from[1], uz = from[2];
163 GLfloat len = lengths[i];
164 out[i][0] = tx * len;
165 out[i][1] = ty * len;
166 out[i][2] = tz * len;
170 dest->count = in->count;
174 static void _XFORMAPI
175 TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
177 const GLvector4f *in,
178 const GLfloat *lengths,
181 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
182 const GLfloat *from = in->start;
183 const GLuint stride = in->stride;
184 const GLuint count = in->count;
185 const GLfloat *m = mat->inv;
186 const GLfloat m0 = scale*m[0];
187 const GLfloat m5 = scale*m[5];
188 const GLfloat m10 = scale*m[10];
194 GLfloat ux = from[0], uy = from[1], uz = from[2];
197 out[i][2] = uz * m10;
199 dest->count = in->count;
203 static void _XFORMAPI
204 TAG(transform_rescale_normals)( const GLmatrix *mat,
206 const GLvector4f *in,
207 const GLfloat *lengths,
210 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
211 const GLfloat *from = in->start;
212 const GLuint stride = in->stride;
213 const GLuint count = in->count;
214 /* Since we are unlikely to have < 3 vertices in the buffer,
215 * it makes sense to pre-multiply by scale.
217 const GLfloat *m = mat->inv;
218 const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
219 const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
220 const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
226 GLfloat ux = from[0], uy = from[1], uz = from[2];
227 out[i][0] = ux * m0 + uy * m1 + uz * m2;
228 out[i][1] = ux * m4 + uy * m5 + uz * m6;
229 out[i][2] = ux * m8 + uy * m9 + uz * m10;
231 dest->count = in->count;
235 static void _XFORMAPI
236 TAG(transform_normals_no_rot)( const GLmatrix *mat,
238 const GLvector4f *in,
239 const GLfloat *lengths,
242 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
243 const GLfloat *from = in->start;
244 const GLuint stride = in->stride;
245 const GLuint count = in->count;
246 const GLfloat *m = mat->inv;
247 const GLfloat m0 = m[0];
248 const GLfloat m5 = m[5];
249 const GLfloat m10 = m[10];
256 GLfloat ux = from[0], uy = from[1], uz = from[2];
259 out[i][2] = uz * m10;
261 dest->count = in->count;
265 static void _XFORMAPI
266 TAG(transform_normals)( const GLmatrix *mat,
268 const GLvector4f *in,
269 const GLfloat *lengths,
272 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
273 const GLfloat *from = in->start;
274 const GLuint stride = in->stride;
275 const GLuint count = in->count;
276 const GLfloat *m = mat->inv;
277 const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
278 const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
279 const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
286 GLfloat ux = from[0], uy = from[1], uz = from[2];
287 out[i][0] = ux * m0 + uy * m1 + uz * m2;
288 out[i][1] = ux * m4 + uy * m5 + uz * m6;
289 out[i][2] = ux * m8 + uy * m9 + uz * m10;
291 dest->count = in->count;
295 static void _XFORMAPI
296 TAG(normalize_normals)( const GLmatrix *mat,
298 const GLvector4f *in,
299 const GLfloat *lengths,
302 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
303 const GLfloat *from = in->start;
304 const GLuint stride = in->stride;
305 const GLuint count = in->count;
313 const GLfloat x = from[0], y = from[1], z = from[2];
314 GLfloat invlen = lengths[i];
315 out[i][0] = x * invlen;
316 out[i][1] = y * invlen;
317 out[i][2] = z * invlen;
322 const GLfloat x = from[0], y = from[1], z = from[2];
323 GLdouble len = x * x + y * y + z * z;
325 len = INV_SQRTF(len);
326 out[i][0] = (GLfloat)(x * len);
327 out[i][1] = (GLfloat)(y * len);
328 out[i][2] = (GLfloat)(z * len);
337 dest->count = in->count;
341 static void _XFORMAPI
342 TAG(rescale_normals)( const GLmatrix *mat,
344 const GLvector4f *in,
345 const GLfloat *lengths,
348 GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
349 const GLfloat *from = in->start;
350 const GLuint stride = in->stride;
351 const GLuint count = in->count;
358 SCALE_SCALAR_3V( out[i], scale, from );
360 dest->count = in->count;
364 static void _XFORMAPI
365 TAG(init_c_norm_transform)( void )
367 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
368 TAG(transform_normals_no_rot);
370 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
371 TAG(transform_rescale_normals_no_rot);
373 _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
374 TAG(transform_normalize_normals_no_rot);
376 _mesa_normal_tab[NORM_TRANSFORM] =
377 TAG(transform_normals);
379 _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
380 TAG(transform_rescale_normals);
382 _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
383 TAG(transform_normalize_normals);
385 _mesa_normal_tab[NORM_RESCALE] =
386 TAG(rescale_normals);
388 _mesa_normal_tab[NORM_NORMALIZE] =
389 TAG(normalize_normals);