1 /* $Id: xform.c,v 1.10 1997/10/30 06:00:06 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-1997 Brian Paul
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Revision 1.10 1997/10/30 06:00:06 brianp
27 * added Intel X86 assembly optimzations (Josh Vanderhoof)
29 * Revision 1.9 1997/07/24 01:25:54 brianp
30 * changed precompiled header symbol from PCH to PC_HEADER
32 * Revision 1.8 1997/05/28 03:27:03 brianp
33 * added precompiled header (PCH) support
35 * Revision 1.7 1997/05/01 01:40:51 brianp
36 * replaced sqrt() with GL_SQRT()
38 * Revision 1.6 1997/04/02 03:15:02 brianp
39 * removed gl_xform_texcoords_4fv()
41 * Revision 1.5 1997/01/03 23:54:17 brianp
42 * changed length threshold in gl_xform_normals_3fv() to 1E-30 per Jeroen
44 * Revision 1.4 1996/11/09 01:50:49 brianp
45 * relaxed the minimum normal threshold in gl_xform_normals_3fv()
47 * Revision 1.3 1996/11/08 02:20:39 brianp
48 * added gl_xform_texcoords_4fv()
50 * Revision 1.2 1996/11/05 01:38:50 brianp
53 * Revision 1.1 1996/09/13 01:38:16 brianp
60 * Matrix/vertex/vector transformation stuff
64 * 1. 4x4 transformation matrices are stored in memory in column major order.
65 * 2. Points/vertices are to be thought of as column vectors.
66 * 3. Transformation of a point p by a matrix M is: p' = M * p
83 * Apply a transformation matrix to an array of [X Y Z W] coordinates:
84 * for i in 0 to n-1 do q[i] = m * p[i]
85 * where p[i] and q[i] are 4-element column vectors and m is a 16-element
86 * transformation matrix.
88 void gl_xform_points_4fv( GLuint n
, GLfloat q
[][4], const GLfloat m
[16],
91 /* This function has been carefully crafted to maximize register usage
92 * and use loop unrolling with IRIX 5.3's cc. Hopefully other compilers
93 * will like this code too.
97 GLfloat m0
= m
[0], m4
= m
[4], m8
= m
[8], m12
= m
[12];
98 GLfloat m1
= m
[1], m5
= m
[5], m9
= m
[9], m13
= m
[13];
99 if (m12
==0.0F
&& m13
==0.0F
) {
102 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2];
103 q
[i
][0] = m0
* p0
+ m4
* p1
+ m8
* p2
;
104 q
[i
][1] = m1
* p0
+ m5
* p1
+ m9
* p2
;
110 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2], p3
= p
[i
][3];
111 q
[i
][0] = m0
* p0
+ m4
* p1
+ m8
* p2
+ m12
* p3
;
112 q
[i
][1] = m1
* p0
+ m5
* p1
+ m9
* p2
+ m13
* p3
;
118 GLfloat m2
= m
[2], m6
= m
[6], m10
= m
[10], m14
= m
[14];
119 GLfloat m3
= m
[3], m7
= m
[7], m11
= m
[11], m15
= m
[15];
120 if (m3
==0.0F
&& m7
==0.0F
&& m11
==0.0F
&& m15
==1.0F
) {
123 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2], p3
= p
[i
][3];
124 q
[i
][2] = m2
* p0
+ m6
* p1
+ m10
* p2
+ m14
* p3
;
131 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2], p3
= p
[i
][3];
132 q
[i
][2] = m2
* p0
+ m6
* p1
+ m10
* p2
+ m14
* p3
;
133 q
[i
][3] = m3
* p0
+ m7
* p1
+ m11
* p2
+ m15
* p3
;
142 * Apply a transformation matrix to an array of [X Y Z] coordinates:
143 * for i in 0 to n-1 do q[i] = m * p[i]
145 void gl_xform_points_3fv( GLuint n
, GLfloat q
[][4], const GLfloat m
[16],
148 /* This function has been carefully crafted to maximize register usage
149 * and use loop unrolling with IRIX 5.3's cc. Hopefully other compilers
150 * will like this code too.
154 GLfloat m0
= m
[0], m4
= m
[4], m8
= m
[8], m12
= m
[12];
155 GLfloat m1
= m
[1], m5
= m
[5], m9
= m
[9], m13
= m
[13];
157 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2];
158 q
[i
][0] = m0
* p0
+ m4
* p1
+ m8
* p2
+ m12
;
159 q
[i
][1] = m1
* p0
+ m5
* p1
+ m9
* p2
+ m13
;
164 GLfloat m2
= m
[2], m6
= m
[6], m10
= m
[10], m14
= m
[14];
165 GLfloat m3
= m
[3], m7
= m
[7], m11
= m
[11], m15
= m
[15];
166 if (m3
==0.0F
&& m7
==0.0F
&& m11
==0.0F
&& m15
==1.0F
) {
169 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2];
170 q
[i
][2] = m2
* p0
+ m6
* p1
+ m10
* p2
+ m14
;
177 GLfloat p0
= p
[i
][0], p1
= p
[i
][1], p2
= p
[i
][2];
178 q
[i
][2] = m2
* p0
+ m6
* p1
+ m10
* p2
+ m14
;
179 q
[i
][3] = m3
* p0
+ m7
* p1
+ m11
* p2
+ m15
;
189 * Apply a transformation matrix to an array of normal vectors:
190 * for i in 0 to n-1 do v[i] = u[i] * m
191 * where u[i] and v[i] are 3-element row vectors and m is a 16-element
192 * transformation matrix.
193 * If the normalize flag is true the normals will be scaled to length 1.
195 void gl_xform_normals_3fv( GLuint n
, GLfloat v
[][3], const GLfloat m
[16],
196 GLfloat u
[][3], GLboolean normalize
)
199 /* Transform normals and scale to unit length */
201 GLfloat m0
= m
[0], m4
= m
[4], m8
= m
[8];
202 GLfloat m1
= m
[1], m5
= m
[5], m9
= m
[9];
203 GLfloat m2
= m
[2], m6
= m
[6], m10
= m
[10];
207 GLfloat ux
= u
[i
][0], uy
= u
[i
][1], uz
= u
[i
][2];
208 tx
= ux
* m0
+ uy
* m1
+ uz
* m2
;
209 ty
= ux
* m4
+ uy
* m5
+ uz
* m6
;
210 tz
= ux
* m8
+ uy
* m9
+ uz
* m10
;
214 len
= GL_SQRT( tx
*tx
+ ty
*ty
+ tz
*tz
);
215 scale
= (len
>1E-30) ? (1.0 / len
) : 1.0;
216 v
[i
][0] = tx
* scale
;
217 v
[i
][1] = ty
* scale
;
218 v
[i
][2] = tz
* scale
;
223 /* Just transform normals, don't scale */
225 GLfloat m0
= m
[0], m4
= m
[4], m8
= m
[8];
226 GLfloat m1
= m
[1], m5
= m
[5], m9
= m
[9];
227 GLfloat m2
= m
[2], m6
= m
[6], m10
= m
[10];
229 GLfloat ux
= u
[i
][0], uy
= u
[i
][1], uz
= u
[i
][2];
230 v
[i
][0] = ux
* m0
+ uy
* m1
+ uz
* m2
;
231 v
[i
][1] = ux
* m4
+ uy
* m5
+ uz
* m6
;
232 v
[i
][2] = ux
* m8
+ uy
* m9
+ uz
* m10
;
240 * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
241 * function is used for transforming clipping plane equations and spotlight
243 * Mathematically, u = v * m.
244 * Input: v - input vector
245 * m - transformation matrix
246 * Output: u - transformed vector
248 void gl_transform_vector( GLfloat u
[4], const GLfloat v
[4], const GLfloat m
[16] )
250 GLfloat v0
=v
[0], v1
=v
[1], v2
=v
[2], v3
=v
[3];
251 #define M(row,col) m[col*4+row]
252 u
[0] = v0
* M(0,0) + v1
* M(1,0) + v2
* M(2,0) + v3
* M(3,0);
253 u
[1] = v0
* M(0,1) + v1
* M(1,1) + v2
* M(2,1) + v3
* M(3,1);
254 u
[2] = v0
* M(0,2) + v1
* M(1,2) + v2
* M(2,2) + v3
* M(3,2);
255 u
[3] = v0
* M(0,3) + v1
* M(1,3) + v2
* M(2,3) + v3
* M(3,3);