/* ** Copyright 1991, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. ** ** Mathematical subroutines needed by the GL. ** ** $Revision: 1.12 $ ** $Date: 1993/12/11 01:03:25 $ */ #include "precomp.h" #pragma hdrstop #include "xform.h" #ifdef SGI // SGIBUG None of the assembly routines copies matrixType! #ifndef __GL_ASM_COPYMATRIX /* ** Copy src to dst */ void FASTCALL __glCopyMatrix(__GLmatrix *dst, const __GLmatrix *src) { dst->matrixType = src->matrixType; dst->matrix[0][0] = src->matrix[0][0]; dst->matrix[0][1] = src->matrix[0][1]; dst->matrix[0][2] = src->matrix[0][2]; dst->matrix[0][3] = src->matrix[0][3]; dst->matrix[1][0] = src->matrix[1][0]; dst->matrix[1][1] = src->matrix[1][1]; dst->matrix[1][2] = src->matrix[1][2]; dst->matrix[1][3] = src->matrix[1][3]; dst->matrix[2][0] = src->matrix[2][0]; dst->matrix[2][1] = src->matrix[2][1]; dst->matrix[2][2] = src->matrix[2][2]; dst->matrix[2][3] = src->matrix[2][3]; dst->matrix[3][0] = src->matrix[3][0]; dst->matrix[3][1] = src->matrix[3][1]; dst->matrix[3][2] = src->matrix[3][2]; dst->matrix[3][3] = src->matrix[3][3]; } #endif /* __GL_ASM_COPYMATRIX */ #endif // SGI /* ** Make m an identity matrix */ void FASTCALL __glMakeIdentity(__GLmatrix *m) { __GLfloat zer = __glZero; __GLfloat one = ((__GLfloat) 1.0);; m->matrix[0][0] = one; m->matrix[0][1] = zer; m->matrix[0][2] = zer; m->matrix[0][3] = zer; m->matrix[1][0] = zer; m->matrix[1][1] = one; m->matrix[1][2] = zer; m->matrix[1][3] = zer; m->matrix[2][0] = zer; m->matrix[2][1] = zer; m->matrix[2][2] = one; m->matrix[2][3] = zer; m->matrix[3][0] = zer; m->matrix[3][1] = zer; m->matrix[3][2] = zer; m->matrix[3][3] = one; m->matrixType = __GL_MT_IDENTITY; } #ifndef __GL_ASM_MULTMATRIX /* ** Compute r = a * b, where r can equal b. */ void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b) { __GLfloat b00, b01, b02, b03; __GLfloat b10, b11, b12, b13; __GLfloat b20, b21, b22, b23; __GLfloat b30, b31, b32, b33; GLint i; b00 = b->matrix[0][0]; b01 = b->matrix[0][1]; b02 = b->matrix[0][2]; b03 = b->matrix[0][3]; b10 = b->matrix[1][0]; b11 = b->matrix[1][1]; b12 = b->matrix[1][2]; b13 = b->matrix[1][3]; b20 = b->matrix[2][0]; b21 = b->matrix[2][1]; b22 = b->matrix[2][2]; b23 = b->matrix[2][3]; b30 = b->matrix[3][0]; b31 = b->matrix[3][1]; b32 = b->matrix[3][2]; b33 = b->matrix[3][3]; for (i = 0; i < 4; i++) { r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10 + a->matrix[i][2]*b20 + a->matrix[i][3]*b30; r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11 + a->matrix[i][2]*b21 + a->matrix[i][3]*b31; r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12 + a->matrix[i][2]*b22 + a->matrix[i][3]*b32; r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13 + a->matrix[i][2]*b23 + a->matrix[i][3]*b33; } } #endif /* __GL_ASM_MULTMATRIX */ #ifndef __GL_ASM_NORMALIZE /* ** Normalize v into vout. */ void FASTCALL __glNormalize(__GLfloat vout[3], const __GLfloat v[3]) { __GLfloat len; len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; if (__GL_FLOAT_LEZ(len)) { vout[0] = __glZero; vout[1] = __glZero; vout[2] = __glZero; return; } else { if (len == ((__GLfloat) 1.0)) { vout[0] = v[0]; vout[1] = v[1]; vout[2] = v[2]; } else { len = ((__GLfloat) 1.0) / __GL_SQRTF(len); vout[0] = v[0] * len; vout[1] = v[1] * len; vout[2] = v[2] * len; } } } #endif /* __GL_ASM_NORMALIZE */ #ifndef __GL_ASM_NORMAL_BATCH /* ** Normalize normals in a polyarray. */ void FASTCALL __glNormalizeBatch(POLYARRAY *pa) { POLYDATA * const pdLast = pa->pdNextVertex; POLYDATA *pd = pa->pd0; for (; pd < pdLast; pd++) { if (pd->flags & POLYDATA_NORMAL_VALID) { __GLcoord * const v = &pd->normal; const __GLfloat len = v->x*v->x + v->y*v->y + v->z*v->z; if (__GL_FLOAT_LEZ(len)) { v->x = __glZero; v->y = __glZero; v->z = __glZero; } else { if (fabs(len - (GLfloat)1.0) > (__GLfloat) 0.0001) { const __GLfloat tmp = ((__GLfloat)1.0) / __GL_SQRTF(len); v->x = v->x * tmp; v->y = v->y * tmp; v->z = v->z * tmp; } } } } } #endif /* __GL_ASM_NORMAL_BATCH */ /* ** inverse = invert(transpose(src)) This code uses Cramer's Rule to calculate the matrix inverse. In general, the inverse transpose has this form: [ ] -t [ ] [ ] [ -t -t t ] [ Q P ] [ S(SQ - PT) -(SQ - PT) T ] [ ] [ ] [ ] [ ] [ ] = [ ] [ ] [ -1 t ] [ ] [ -(Q P) 1 ] [ T S ] [ ------------- ------------- ] [ ] [ -1 t t -1 t t ] [ ] [ S - (Q P) T S - (Q P) T ] But in the usual case that P,S == [0, 0, 0, 1], this is enough: [ ] -t [ ] [ ] [ -t -t t ] [ Q 0 ] [ Q -Q T ] [ ] [ ] [ ] [ ] [ ] = [ ] [ ] [ ] [ ] [ ] [ T 1 ] [ 0 1 ] [ ] [ ] [ ] [ ] */ void FASTCALL __glInvertTransposeMatrix(__GLmatrix *inverse, const __GLmatrix *src) { __GLfloat x00, x01, x02; __GLfloat x10, x11, x12; __GLfloat x20, x21, x22; __GLfloat rcp; #ifdef NT // The matrix type of the inverse transpose is not necessarily the // same as that of the input. Always set it to general here to // be safe. The type can be refined later if necessary. inverse->matrixType = __GL_MT_GENERAL; if (src->matrixType) #else /* propagate matrix type & branch if general */ if (inverse->matrixType = src->matrixType) #endif { __GLfloat z00, z01, z02; __GLfloat z10, z11, z12; __GLfloat z20, z21, z22; /* read 3x3 matrix into registers */ x00 = src->matrix[0][0]; x01 = src->matrix[0][1]; x02 = src->matrix[0][2]; x10 = src->matrix[1][0]; x11 = src->matrix[1][1]; x12 = src->matrix[1][2]; x20 = src->matrix[2][0]; x21 = src->matrix[2][1]; x22 = src->matrix[2][2]; /* compute first three 2x2 cofactors */ z20 = x01*x12 - x11*x02; z10 = x21*x02 - x01*x22; z00 = x11*x22 - x12*x21; /* compute 3x3 determinant & its reciprocal */ rcp = x20*z20 + x10*z10 + x00*z00; if (rcp == (float)0) return; rcp = (float)1/rcp; /* compute other six 2x2 cofactors */ z01 = x20*x12 - x10*x22; z02 = x10*x21 - x20*x11; z11 = x00*x22 - x20*x02; z12 = x20*x01 - x00*x21; z21 = x10*x02 - x00*x12; z22 = x00*x11 - x10*x01; /* multiply all cofactors by reciprocal */ inverse->matrix[0][0] = z00*rcp; inverse->matrix[0][1] = z01*rcp; inverse->matrix[0][2] = z02*rcp; inverse->matrix[1][0] = z10*rcp; inverse->matrix[1][1] = z11*rcp; inverse->matrix[1][2] = z12*rcp; inverse->matrix[2][0] = z20*rcp; inverse->matrix[2][1] = z21*rcp; inverse->matrix[2][2] = z22*rcp; /* read translation vector & negate */ x00 = -src->matrix[3][0]; x01 = -src->matrix[3][1]; x02 = -src->matrix[3][2]; /* store bottom row of inverse transpose */ inverse->matrix[3][0] = 0; inverse->matrix[3][1] = 0; inverse->matrix[3][2] = 0; inverse->matrix[3][3] = 1; /* finish by tranforming translation vector */ inverse->matrix[0][3] = inverse->matrix[0][0]*x00 + inverse->matrix[0][1]*x01 + inverse->matrix[0][2]*x02; inverse->matrix[1][3] = inverse->matrix[1][0]*x00 + inverse->matrix[1][1]*x01 + inverse->matrix[1][2]*x02; inverse->matrix[2][3] = inverse->matrix[2][0]*x00 + inverse->matrix[2][1]*x01 + inverse->matrix[2][2]*x02; if ((rcp <= ((float)1.0 + __GL_MATRIX_UNITY_SCALE_EPSILON)) && (rcp >= ((float)1.0 - __GL_MATRIX_UNITY_SCALE_EPSILON))) { inverse->nonScaling = GL_TRUE; } else { inverse->nonScaling = GL_FALSE; } } else { __GLfloat x30, x31, x32; __GLfloat y01, y02, y03, y12, y13, y23; __GLfloat z02, z03, z12, z13, z22, z23, z32, z33; #define x03 x01 #define x13 x11 #define x23 x21 #define x33 x31 #define z00 x02 #define z10 x12 #define z20 x22 #define z30 x32 #define z01 x03 #define z11 x13 #define z21 x23 #define z31 x33 /* read 1st two columns of matrix into registers */ x00 = src->matrix[0][0]; x01 = src->matrix[0][1]; x10 = src->matrix[1][0]; x11 = src->matrix[1][1]; x20 = src->matrix[2][0]; x21 = src->matrix[2][1]; x30 = src->matrix[3][0]; x31 = src->matrix[3][1]; /* compute all six 2x2 determinants of 1st two columns */ y01 = x00*x11 - x10*x01; y02 = x00*x21 - x20*x01; y03 = x00*x31 - x30*x01; y12 = x10*x21 - x20*x11; y13 = x10*x31 - x30*x11; y23 = x20*x31 - x30*x21; /* read 2nd two columns of matrix into registers */ x02 = src->matrix[0][2]; x03 = src->matrix[0][3]; x12 = src->matrix[1][2]; x13 = src->matrix[1][3]; x22 = src->matrix[2][2]; x23 = src->matrix[2][3]; x32 = src->matrix[3][2]; x33 = src->matrix[3][3]; /* compute all 3x3 cofactors for 2nd two columns */ z33 = x02*y12 - x12*y02 + x22*y01; z23 = x12*y03 - x32*y01 - x02*y13; z13 = x02*y23 - x22*y03 + x32*y02; z03 = x22*y13 - x32*y12 - x12*y23; z32 = x13*y02 - x23*y01 - x03*y12; z22 = x03*y13 - x13*y03 + x33*y01; z12 = x23*y03 - x33*y02 - x03*y23; z02 = x13*y23 - x23*y13 + x33*y12; /* compute all six 2x2 determinants of 2nd two columns */ y01 = x02*x13 - x12*x03; y02 = x02*x23 - x22*x03; y03 = x02*x33 - x32*x03; y12 = x12*x23 - x22*x13; y13 = x12*x33 - x32*x13; y23 = x22*x33 - x32*x23; /* read 1st two columns of matrix into registers */ x00 = src->matrix[0][0]; x01 = src->matrix[0][1]; x10 = src->matrix[1][0]; x11 = src->matrix[1][1]; x20 = src->matrix[2][0]; x21 = src->matrix[2][1]; x30 = src->matrix[3][0]; x31 = src->matrix[3][1]; /* compute all 3x3 cofactors for 1st column */ z30 = x11*y02 - x21*y01 - x01*y12; z20 = x01*y13 - x11*y03 + x31*y01; z10 = x21*y03 - x31*y02 - x01*y23; z00 = x11*y23 - x21*y13 + x31*y12; /* compute 4x4 determinant & its reciprocal */ rcp = x30*z30 + x20*z20 + x10*z10 + x00*z00; if (rcp == (float)0) return; rcp = (float)1/rcp; /* compute all 3x3 cofactors for 2nd column */ z31 = x00*y12 - x10*y02 + x20*y01; z21 = x10*y03 - x30*y01 - x00*y13; z11 = x00*y23 - x20*y03 + x30*y02; z01 = x20*y13 - x30*y12 - x10*y23; /* multiply all 3x3 cofactors by reciprocal */ inverse->matrix[0][0] = z00*rcp; inverse->matrix[0][1] = z01*rcp; inverse->matrix[1][0] = z10*rcp; inverse->matrix[0][2] = z02*rcp; inverse->matrix[2][0] = z20*rcp; inverse->matrix[0][3] = z03*rcp; inverse->matrix[3][0] = z30*rcp; inverse->matrix[1][1] = z11*rcp; inverse->matrix[1][2] = z12*rcp; inverse->matrix[2][1] = z21*rcp; inverse->matrix[1][3] = z13*rcp; inverse->matrix[3][1] = z31*rcp; inverse->matrix[2][2] = z22*rcp; inverse->matrix[2][3] = z23*rcp; inverse->matrix[3][2] = z32*rcp; inverse->matrix[3][3] = z33*rcp; if ((inverse->matrix[3][0] == __glZero) && (inverse->matrix[3][1] == __glZero) && (inverse->matrix[3][2] == __glZero)) { if (((rcp <= ((float)1.0 + __GL_MATRIX_UNITY_SCALE_EPSILON)) && (rcp >= ((float)1.0 - __GL_MATRIX_UNITY_SCALE_EPSILON)))) { inverse->nonScaling = GL_TRUE; } else { inverse->nonScaling = GL_FALSE; } } else { inverse->nonScaling = GL_FALSE; } } } /* * Find the 3x3 transpose of a matrix. This is used to calculate the light * vector in object space for fast infinite lighting. */ void __glTranspose3x3(__GLmatrix *dst, __GLmatrix *src) { __GLfloat x00, x01, x02; __GLfloat x10, x11, x12; __GLfloat x20, x21, x22; x00 = src->matrix[0][0]; x01 = src->matrix[0][1]; x02 = src->matrix[0][2]; x10 = src->matrix[1][0]; x11 = src->matrix[1][1]; x12 = src->matrix[1][2]; x20 = src->matrix[2][0]; x21 = src->matrix[2][1]; x22 = src->matrix[2][2]; dst->matrix[0][0] = x00; dst->matrix[1][0] = x01; dst->matrix[2][0] = x02; dst->matrix[3][0] = __glZero; dst->matrix[0][1] = x10; dst->matrix[1][1] = x11; dst->matrix[2][1] = x12; dst->matrix[3][1] = __glZero; dst->matrix[0][2] = x20; dst->matrix[1][2] = x21; dst->matrix[2][2] = x22; dst->matrix[3][2] = __glZero; dst->matrix[0][3] = __glZero; dst->matrix[1][3] = __glZero; dst->matrix[2][3] = __glZero; dst->matrix[3][3] = __glOne; } #ifdef NT /* ** Return the closest integer log based 2 of a number */ static GLubyte logTab[256] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; GLint FASTCALL __glIntLog2(__GLfloat f) { GLuint i = (GLuint) FTOL(f); if (i & 0xffff0000) { if (i & 0xff000000) { return ((GLint)logTab[i >> 24] + 24); } else { return ((GLint)logTab[i >> 16] + 16); } } else { if (i & 0xff00) { return ((GLint)logTab[i >> 8] + 8); } else { return ((GLint)logTab[i]); } } } #else GLint __glIntLog2(__GLfloat f) { return (GLint)(__GL_LOGF(f) * __GL_M_LN2_INV); } #endif GLfloat FASTCALL __glClampf(GLfloat fval, __GLfloat zero, __GLfloat one) { if (fval < zero) return zero; else if (fval > one) return one; else return fval; } /* ** r = vector from p1 to p2 */ #ifndef __GL_ASM_VECSUB4 void FASTCALL __glVecSub4(__GLcoord *r, const __GLcoord *p1, const __GLcoord *p2) { __GLfloat oneOverW; if (p2->w == __glZero) { if (p1->w == __glZero) { r->x = p2->x - p1->x; r->y = p2->y - p1->y; r->z = p2->z - p1->z; } else { r->x = p2->x; r->y = p2->y; r->z = p2->z; } } else if (p1->w == __glZero) { r->x = -p1->x; r->y = -p1->y; r->z = -p1->z; } else{ oneOverW = ((__GLfloat) 1.0) / p2->w; r->x = p2->x * oneOverW; r->y = p2->y * oneOverW; r->z = p2->z * oneOverW; oneOverW = ((__GLfloat) 1.0) / p1->w; r->x -= p1->x * oneOverW; r->y -= p1->y * oneOverW; r->z -= p1->z * oneOverW; } } #endif // !__GL_ASM_VECSUB4