123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell/*
323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * Mesa 3-D graphics library
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
527558a160a9fe91745728d7626995cd88f8fe339Brian Paul * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * copy of this software and associated documentation files (the "Software"),
923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * to deal in the Software without restriction, including without limitation
1023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
1223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1322144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
1423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * The above copyright notice and this permission notice shall be included
1523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * in all copies or substantial portions of the Software.
1622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
1723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
213d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
223d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
233d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER DEALINGS IN THE SOFTWARE.
2423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell */
2523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
2623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell/*
2723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell * New (3.1) transformation code written by Keith Whitwell.
2823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell */
2923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
30ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul/* Functions to tranform a vector of normals.  This includes applying
31ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * the transformation matrix, rescaling and normalization.
32ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul */
33ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
34ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul/*
35ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * mat - the 4x4 transformation matrix
36ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * scale - uniform scale factor of the transformation matrix (not always used)
37ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * in - the source vector of normals
38ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * lengths - length of each incoming normal (may be NULL) (a display list
39ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul *           optimization)
40ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul * dest - the destination vector of normals
41ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul */
4209ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
4323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(transform_normalize_normals)( const GLmatrix *mat,
4423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                  GLfloat scale,
45bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                  const GLvector4f *in,
4623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                  const GLfloat *lengths,
47bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                  GLvector4f *dest )
4823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
49bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
50ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
51ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
52ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
53ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *m = mat->inv;
5423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
5523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
5623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
57ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
5823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
5923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   if (!lengths) {
6023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
615e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLfloat tx, ty, tz;
625e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
635e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    const GLfloat ux = from[0],  uy = from[1],  uz = from[2];
645e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tx = ux * m0 + uy * m1 + uz * m2;
655e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    ty = ux * m4 + uy * m5 + uz * m6;
665e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tz = ux * m8 + uy * m9 + uz * m10;
675e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 }
685e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
695e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    GLdouble len = tx*tx + ty*ty + tz*tz;
705e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    if (len > 1e-20) {
71a2b366b92cecc5045293528aa0bb8b1f0678bbccBrian Paul	       GLfloat scale = 1.0f / sqrtf(len);
72f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][0] = tx * scale;
73f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][1] = ty * scale;
74f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][2] = tz * scale;
7523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	    }
76ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul	    else {
775e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	       out[i][0] = out[i][1] = out[i][2] = 0;
7823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	    }
7923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 }
8023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
8123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
8223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   else {
837adc9fa1f1d12683c5855bf5854dec814629093dMatt Turner      if (scale != 1.0f) {
8423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 m0 *= scale,  m4 *= scale,  m8 *= scale;
8523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 m1 *= scale,  m5 *= scale,  m9 *= scale;
8623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 m2 *= scale,  m6 *= scale,  m10 *= scale;
8723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
8823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
8923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
905e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLfloat tx, ty, tz;
915e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
925e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    const GLfloat ux = from[0],  uy = from[1],  uz = from[2];
935e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tx = ux * m0 + uy * m1 + uz * m2;
945e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    ty = ux * m4 + uy * m5 + uz * m6;
955e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tz = ux * m8 + uy * m9 + uz * m10;
965e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 }
975e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
985e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    GLfloat len = lengths[i];
995e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][0] = tx * len;
1005e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][1] = ty * len;
1015e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][2] = tz * len;
10223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 }
10323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
10423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
10523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
10623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
10723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
10823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
10909ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
11023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
11123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                         GLfloat scale,
112bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                         const GLvector4f *in,
11323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                         const GLfloat *lengths,
114bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                         GLvector4f *dest )
11523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
116bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
117ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
118ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
119ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
120ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *m = mat->inv;
12123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m0 = m[0];
12223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m5 = m[5];
12323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   GLfloat m10 = m[10];
124ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
125ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
12623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   if (!lengths) {
12723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
1285e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLfloat tx, ty, tz;
1295e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
1305e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    const GLfloat ux = from[0],  uy = from[1],  uz = from[2];
1315e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tx = ux * m0                    ;
1325e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    ty =           uy * m5          ;
1335e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tz =                     uz * m10;
1345e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 }
1355e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
1365e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    GLdouble len = tx*tx + ty*ty + tz*tz;
1375e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    if (len > 1e-20) {
138a2b366b92cecc5045293528aa0bb8b1f0678bbccBrian Paul	       GLfloat scale = 1.0f / sqrtf(len);
139f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][0] = tx * scale;
140f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][1] = ty * scale;
141f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul	       out[i][2] = tz * scale;
14223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	    }
143ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul	    else {
1445e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	       out[i][0] = out[i][1] = out[i][2] = 0;
14523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	    }
14623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 }
14723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
14823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
14923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   else {
15047a28c0b4d4ca27592e3cbb8e4b17d1cd8f7997dKeith Whitwell      m0 *= scale;
15147a28c0b4d4ca27592e3cbb8e4b17d1cd8f7997dKeith Whitwell      m5 *= scale;
15247a28c0b4d4ca27592e3cbb8e4b17d1cd8f7997dKeith Whitwell      m10 *= scale;
15323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
15423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
1555e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLfloat tx, ty, tz;
1565e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
1575e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    const GLfloat ux = from[0],  uy = from[1],  uz = from[2];
1585e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tx = ux * m0                    ;
1595e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    ty =           uy * m5          ;
1605e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    tz =                     uz * m10;
1615e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 }
1625e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 {
1635e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    GLfloat len = lengths[i];
1645e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][0] = tx * len;
1655e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][1] = ty * len;
1665e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][2] = tz * len;
16723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell	 }
16823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
16923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
17023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
17123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
17223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
17323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
17409ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
17523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
17623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                       GLfloat scale,
177bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                       const GLvector4f *in,
17823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                       const GLfloat *lengths,
179bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                       GLvector4f *dest )
18023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
181bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
182ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
183ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
184ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
18523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   const GLfloat *m = mat->inv;
186ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m0 = scale*m[0];
187ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m5 = scale*m[5];
188ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m10 = scale*m[10];
189ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
190ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
19123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) lengths;
192ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
19323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   STRIDE_LOOP {
1945e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      GLfloat ux = from[0],  uy = from[1],  uz = from[2];
1955e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][0] = ux * m0;
1965e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][1] =           uy * m5;
1975e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][2] =                     uz * m10;
19823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
19923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
20023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
20123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
202ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
20309ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
20423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(transform_rescale_normals)( const GLmatrix *mat,
20523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                GLfloat scale,
206bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                const GLvector4f *in,
20723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                                const GLfloat *lengths,
208bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                                GLvector4f *dest )
20923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
210bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
211ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
212ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
213ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
21423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   /* Since we are unlikely to have < 3 vertices in the buffer,
21523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell    * it makes sense to pre-multiply by scale.
21623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell    */
21723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   const GLfloat *m = mat->inv;
218ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m0 = scale*m[0],  m4 = scale*m[4],  m8 = scale*m[8];
219ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m1 = scale*m[1],  m5 = scale*m[5],  m9 = scale*m[9];
220ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m2 = scale*m[2],  m6 = scale*m[6],  m10 = scale*m[10];
221ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
222ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
22323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) lengths;
224ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
22523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   STRIDE_LOOP {
2265e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      GLfloat ux = from[0],  uy = from[1],  uz = from[2];
2275e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][0] = ux * m0 + uy * m1 + uz * m2;
2285e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][1] = ux * m4 + uy * m5 + uz * m6;
2295e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][2] = ux * m8 + uy * m9 + uz * m10;
23023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
23123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
23223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
23323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
23423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
23509ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
23679b2d13ae2280650070d5a0f157afecbfa02f9e6Gareth HughesTAG(transform_normals_no_rot)( const GLmatrix *mat,
23779b2d13ae2280650070d5a0f157afecbfa02f9e6Gareth Hughes			       GLfloat scale,
238bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul			       const GLvector4f *in,
23979b2d13ae2280650070d5a0f157afecbfa02f9e6Gareth Hughes			       const GLfloat *lengths,
240bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul			       GLvector4f *dest )
24123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
242bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
243ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
244ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
245ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
24623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   const GLfloat *m = mat->inv;
247ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m0 = m[0];
248ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m5 = m[5];
249ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m10 = m[10];
250ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
251ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
25223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) scale;
25323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) lengths;
254ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
25523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   STRIDE_LOOP {
2565e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      GLfloat ux = from[0],  uy = from[1],  uz = from[2];
2575e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][0] = ux * m0;
2585e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][1] =           uy * m5;
2595e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][2] =                     uz * m10;
26023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
26123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
26223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
26323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
26423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
26509ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
26623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(transform_normals)( const GLmatrix *mat,
26723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                        GLfloat scale,
268bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                        const GLvector4f *in,
26923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                        const GLfloat *lengths,
270bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                        GLvector4f *dest )
27123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
272bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
273ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
274ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
275ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
27623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   const GLfloat *m = mat->inv;
277ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
278ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
279ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
280ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
281ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
28223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) scale;
28323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) lengths;
284ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
28523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   STRIDE_LOOP {
2865e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      GLfloat ux = from[0],  uy = from[1],  uz = from[2];
2875e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][0] = ux * m0 + uy * m1 + uz * m2;
2885e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][1] = ux * m4 + uy * m5 + uz * m6;
2895e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      out[i][2] = ux * m8 + uy * m9 + uz * m10;
29023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
29123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
29223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
29323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
29423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
29509ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
29623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(normalize_normals)( const GLmatrix *mat,
29723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                        GLfloat scale,
298bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                        const GLvector4f *in,
29923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                        const GLfloat *lengths,
300bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                        GLvector4f *dest )
30123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
302bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
303ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
304ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
305ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
306ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
307ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
30823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) mat;
30923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) scale;
310ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
31123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   if (lengths) {
31223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
3135e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 const GLfloat x = from[0], y = from[1], z = from[2];
3145e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLfloat invlen = lengths[i];
3155e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 out[i][0] = x * invlen;
3165e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 out[i][1] = y * invlen;
3175e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 out[i][2] = z * invlen;
31823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
31923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
32023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   else {
32123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      STRIDE_LOOP {
3225e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 const GLfloat x = from[0], y = from[1], z = from[2];
3235e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 GLdouble len = x * x + y * y + z * z;
3245e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 if (len > 1e-50) {
325a2b366b92cecc5045293528aa0bb8b1f0678bbccBrian Paul	    len = 1.0f / sqrtf(len);
326dc24230de7f913969b52dee3579bb8fa3d50a8c0Karl Schultz	    out[i][0] = (GLfloat)(x * len);
327dc24230de7f913969b52dee3579bb8fa3d50a8c0Karl Schultz	    out[i][1] = (GLfloat)(y * len);
328dc24230de7f913969b52dee3579bb8fa3d50a8c0Karl Schultz	    out[i][2] = (GLfloat)(z * len);
3295e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 }
3305e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	 else {
3315e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][0] = x;
3325e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][1] = y;
3335e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes	    out[i][2] = z;
33422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes	 }
33523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      }
33623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
33723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
33823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
33923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
34023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
34109ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
34223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(rescale_normals)( const GLmatrix *mat,
34323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                      GLfloat scale,
344bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                      const GLvector4f *in,
34523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell                      const GLfloat *lengths,
346bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul                      GLvector4f *dest )
34723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
348bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul   GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
349ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLfloat *from = in->start;
350ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint stride = in->stride;
351ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   const GLuint count = in->count;
352ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul   GLuint i;
353ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
35423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) mat;
35523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   (void) lengths;
356ca209ae1f95760bef87a10bca031bdbd6fb3ac3cBrian Paul
35723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   STRIDE_LOOP {
3585e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes      SCALE_SCALAR_3V( out[i], scale, from );
35923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   }
36023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell   dest->count = in->count;
36123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
36223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
36323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
36409ffa04cd9c560b7a8c6d8ac80e3d59c49c5ef70Brian Paulstatic void
36523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith WhitwellTAG(init_c_norm_transform)( void )
36623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell{
3675e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
36823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_normals_no_rot);
36923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3705e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
37123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_rescale_normals_no_rot);
37223caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3735e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
37423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_normalize_normals_no_rot);
37523caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3765e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM] =
37723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_normals);
37823caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3795e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
38023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_rescale_normals);
38123caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3825e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
38323caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(transform_normalize_normals);
38423caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3855e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_RESCALE] =
38623caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(rescale_normals);
38723caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell
3885e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes   _mesa_normal_tab[NORM_NORMALIZE] =
38923caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell      TAG(normalize_normals);
39023caf20169ac38436ee9c13914f1d6aa7cf6bb5eKeith Whitwell}
391