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
);