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 */ 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 */ 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 */ 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 */ 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