xref: /reactos/dll/opengl/mesa/xform.c (revision 5f2bebf7)
1 /* $Id: xform.c,v 1.10 1997/10/30 06:00:06 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.5
6  * Copyright (C) 1995-1997  Brian Paul
7  *
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.
12  *
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.
17  *
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.
21  */
22 
23 
24 /*
25  * $Log: xform.c,v $
26  * Revision 1.10  1997/10/30 06:00:06  brianp
27  * added Intel X86 assembly optimzations (Josh Vanderhoof)
28  *
29  * Revision 1.9  1997/07/24 01:25:54  brianp
30  * changed precompiled header symbol from PCH to PC_HEADER
31  *
32  * Revision 1.8  1997/05/28 03:27:03  brianp
33  * added precompiled header (PCH) support
34  *
35  * Revision 1.7  1997/05/01 01:40:51  brianp
36  * replaced sqrt() with GL_SQRT()
37  *
38  * Revision 1.6  1997/04/02 03:15:02  brianp
39  * removed gl_xform_texcoords_4fv()
40  *
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
43  *
44  * Revision 1.4  1996/11/09 01:50:49  brianp
45  * relaxed the minimum normal threshold in gl_xform_normals_3fv()
46  *
47  * Revision 1.3  1996/11/08 02:20:39  brianp
48  * added gl_xform_texcoords_4fv()
49  *
50  * Revision 1.2  1996/11/05 01:38:50  brianp
51  * fixed some comments
52  *
53  * Revision 1.1  1996/09/13 01:38:16  brianp
54  * Initial revision
55  *
56  */
57 
58 
59 /*
60  * Matrix/vertex/vector transformation stuff
61  *
62  *
63  * NOTES:
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
67  *
68  */
69 
70 
71 #ifdef PC_HEADER
72 #include "all.h"
73 #else
74 #include <math.h>
75 #include "mmath.h"
76 #include "types.h"
77 #include "xform.h"
78 #endif
79 
80 
81 
82 /*
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.
87  */
gl_xform_points_4fv(GLuint n,GLfloat q[][4],const GLfloat m[16],GLfloat p[][4])88 void gl_xform_points_4fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
89                           GLfloat p[][4] )
90 {
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.
94     */
95    {
96       GLuint i;
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) {
100          /* common case */
101          for (i=0;i<n;i++) {
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;
105          }
106       }
107       else {
108          /* general case */
109          for (i=0;i<n;i++) {
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;
113          }
114       }
115    }
116    {
117       GLuint i;
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) {
121          /* common case */
122          for (i=0;i<n;i++) {
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;
125             q[i][3] = p3;
126          }
127       }
128       else {
129          /* general case */
130          for (i=0;i<n;i++) {
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;
134          }
135       }
136    }
137 }
138 
139 
140 
141 /*
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]
144  */
gl_xform_points_3fv(GLuint n,GLfloat q[][4],const GLfloat m[16],GLfloat p[][3])145 void gl_xform_points_3fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
146                           GLfloat p[][3] )
147 {
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.
151     */
152    {
153       GLuint i;
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];
156       for (i=0;i<n;i++) {
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;
160       }
161    }
162    {
163       GLuint i;
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) {
167          /* common case */
168          for (i=0;i<n;i++) {
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;
171             q[i][3] = 1.0F;
172          }
173       }
174       else {
175          /* general case */
176          for (i=0;i<n;i++) {
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;
180          }
181       }
182    }
183 }
184 
185 
186 
187 #ifndef USE_ASM
188 /*
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.
194  */
gl_xform_normals_3fv(GLuint n,GLfloat v[][3],const GLfloat m[16],GLfloat u[][3],GLboolean normalize)195 void gl_xform_normals_3fv( GLuint n, GLfloat v[][3], const GLfloat m[16],
196                            GLfloat u[][3], GLboolean normalize )
197 {
198    if (normalize) {
199       /* Transform normals and scale to unit length */
200       GLuint i;
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];
204       for (i=0;i<n;i++) {
205          GLdouble tx, ty, tz;
206          {
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;
211          }
212          {
213             GLdouble len, scale;
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;
219          }
220       }
221    }
222    else {
223       /* Just transform normals, don't scale */
224       GLuint i;
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];
228       for (i=0;i<n;i++) {
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;
233       }
234    }
235 }
236 #endif
237 
238 
239 /*
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
242  * directions.
243  * Mathematically,  u = v * m.
244  * Input:  v - input vector
245  *         m - transformation matrix
246  * Output:  u - transformed vector
247  */
gl_transform_vector(GLfloat u[4],const GLfloat v[4],const GLfloat m[16])248 void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
249 {
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);
256 #undef M
257 }
258 
259