/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ #include "displaylists.h" #include "sysinc.h" #include #include #include "util.h" #include "altivec_math.h" int strcmp(const char *s1, const char *s2); int strcasecmp(const char *s1, const char *s2); BOOL useVectorUnit = FALSE; #ifndef PI #ifdef M_PI #define PI M_PI #else #define PI 3.1415927 #endif #endif static char rcsid[] UNUSED = "$Id$"; INLINE void m_MatCopy(Matrix *pA, Matrix *pB); INLINE void m_MatMultGeneral(Matrix *pA, float *pB, Matrix *pC); INLINE void m_MatMultB0001(Matrix *pA, float *pB, Matrix *pC); INLINE void m_MatMultA0001(Matrix *pA, float *pB, Matrix *pC); INLINE void m_MatMultATrans(Matrix *pA, float *pB, Matrix *pC); INLINE void m_MatMultBTrans(Matrix *pA, float *pB, Matrix *pC); INLINE void m_LoadMatrixf(Matrix *pA, const float *v); INLINE void m_LoadMatrixd(Matrix *pA, const double *v); INLINE void m_LoadIdentity(Matrix *pA); INLINE void m_Mult(Matrix *pA, float *v, int vtype, Matrix *pC); void m_CombineMatrices(GLcontext context); void GLMatrixInit(GLcontext context); void m_PrintMatrix(Matrix *pA); /* I am too lazy to convert our old code */ #define CM_0 OF_11 #define CM_1 OF_12 #define CM_2 OF_13 #define CM_3 OF_21 #define CM_4 OF_22 #define CM_5 OF_23 #define CM_6 OF_31 #define CM_7 OF_32 #define CM_8 OF_33 /* ** Computes the determinant of the upper 3x3 submatrix block ** of the supplied matrix */ INLINE GLfloat m_Determinant(Matrix *pA) { #define a(x) (pA->v[CM_##x]) float a0 = a(0); float a1 = a(1); float a2 = a(2); float a3 = a(3); float a4 = a(4); float a5 = a(5); float a6 = a(6); float a7 = a(7); float a8 = a(8); return ( a0*a4*a8 + a1*a5*a6 + a2*a3*a7 - a0*a5*a7 - a1*a3*a8 - a2*a4*a6); #undef a } /* * Compute determinant of 3x3 matrix resulting from pA dropping * column i and line j * (Adapted from the Matrix and Quaternion FAQ, at * http://skal.planet-d.net/demo/matrixfaq.htm) */ INLINE GLfloat m_Determinant3(Matrix *pA, int i, int j) { float a[9]; int di, dj, si, sj; for (di = 0; di < 3; di++) { for (dj = 0; dj < 3; dj++) { si = di + ((di >= i) ? 1 : 0); sj = dj + ((dj >= j) ? 1 : 0); a[di * 3 + dj] = pA->v[sj * 4 + si]; } } return a[0] * ( a[4] * a[8] - a[7] * a[5]) - a[1] * ( a[3] * a[8] - a[6] * a[5]) + a[2] * ( a[3] * a[7] - a[6] * a[4]); } GLfloat m_Determinant4(Matrix *pA) { GLfloat res = 0.0, i = 1; int n; for (n = 0; n < 4; n++) { res += pA->v[n*4] * m_Determinant3(pA, 0, n) * i; i *= -1.0; } return res; } /* ** Builds the inverse of the upper 3x3 submatrix block of the ** supplied matrix for the backtransformation of the normals */ void m_DoInvert(Matrix *pA, GLfloat *out) { GLfloat det = 1.f / m_Determinant(pA); #define a(x) (pA->v[CM_##x]) float a0 = a(0); float a1 = a(1); float a2 = a(2); float a3 = a(3); float a4 = a(4); float a5 = a(5); float a6 = a(6); float a7 = a(7); float a8 = a(8); *out++ = (GLfloat)(a4*a8 - a5*a7)*det; *out++ = (GLfloat)(a2*a7 - a1*a8)*det; *out++ = (GLfloat)(a1*a5 - a2*a4)*det; *out++ = (GLfloat)(a5*a6 - a3*a8)*det; *out++ = (GLfloat)(a0*a8 - a2*a6)*det; *out++ = (GLfloat)(a2*a3 - a0*a5)*det; *out++ = (GLfloat)(a3*a7 - a4*a6)*det; *out++ = (GLfloat)(a1*a6 - a0*a7)*det; *out++ = (GLfloat)(a0*a4 - a1*a3)*det; #undef a } void m_BuildInverted(GLcontext context) { context->InvRotValid = GL_TRUE; m_DoInvert(CurrentMV, context->InvRot); } void m_BuildInvertedFull(GLcontext context) { int i, j, sign; context->InverseModelViewValid = GL_TRUE; GLfloat mdet = m_Determinant4(CurrentMV); if (fast_fabs(mdet) < 0.0005) { m_LoadIdentity(&context->InverseModelView); } else { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { sign = 1 - ((i + j) % 2) * 2; context->InverseModelView.v[i*4+j] = (m_Determinant3(CurrentMV, i, j) * (GLfloat)sign) / mdet; } } } } /* ** Copy matrix B to matrix A ** A = B */ INLINE void m_MatCopy(Matrix *pA, Matrix *pB) { int i; for (i=0; i<16; i++) pA->v[i] = pB->v[i]; pA->flags = pB->flags; pA->Inverse = pB->Inverse; } /* ** General case: Matrix multiply ** Multiply matrix A by float field, storing the result in matrix C */ INLINE void m_MatMultGeneral(Matrix *pA, float *pB, Matrix *pC) { #define a(x) (pA->v[OF_##x]) #define b(x) (pB[OF_##x]) #define c(x) (pC->v[OF_##x]) float a11 = a(11), b11 = b(11); float a12 = a(12), b12 = b(12); float a13 = a(13), b13 = b(13); float a14 = a(14), b14 = b(14); float a21 = a(21), b21 = b(21); float a22 = a(22), b22 = b(22); float a23 = a(23), b23 = b(23); float a24 = a(24), b24 = b(24); float a31 = a(31), b31 = b(31); float a32 = a(32), b32 = b(32); float a33 = a(33), b33 = b(33); float a34 = a(34), b34 = b(34); float a41 = a(41), b41 = b(41); float a42 = a(42), b42 = b(42); float a43 = a(43), b43 = b(43); float a44 = a(44), b44 = b(44); c(11) = a11*b11 + a12*b21 + a13*b31 + a14*b41; c(12) = a11*b12 + a12*b22 + a13*b32 + a14*b42; c(13) = a11*b13 + a12*b23 + a13*b33 + a14*b43; c(14) = a11*b14 + a12*b24 + a13*b34 + a14*b44; c(21) = a21*b11 + a22*b21 + a23*b31 + a24*b41; c(22) = a21*b12 + a22*b22 + a23*b32 + a24*b42; c(23) = a21*b13 + a22*b23 + a23*b33 + a24*b43; c(24) = a21*b14 + a22*b24 + a23*b34 + a24*b44; c(31) = a31*b11 + a32*b21 + a33*b31 + a34*b41; c(32) = a31*b12 + a32*b22 + a33*b32 + a34*b42; c(33) = a31*b13 + a32*b23 + a33*b33 + a34*b43; c(34) = a31*b14 + a32*b24 + a33*b34 + a34*b44; c(41) = a41*b11 + a42*b21 + a43*b31 + a44*b41; c(42) = a41*b12 + a42*b22 + a43*b32 + a44*b42; c(43) = a41*b13 + a42*b23 + a43*b33 + a44*b43; c(44) = a41*b14 + a42*b24 + a43*b34 + a44*b44; pC->flags = 0; #undef a #undef b #undef c } /* ** Matrix B has three rows ** Multiply matrix A by float field, storing the result in matrix C */ INLINE void m_MatMultB0001(Matrix *pA, float *pB, Matrix *pC) { #define a(x) (pA->v[OF_##x]) #define b(x) (pB[OF_##x]) #define c(x) (pC->v[OF_##x]) float a11 = a(11), b11 = b(11); float a12 = a(12), b12 = b(12); float a13 = a(13), b13 = b(13); float a14 = a(14), b14 = b(14); float a21 = a(21), b21 = b(21); float a22 = a(22), b22 = b(22); float a23 = a(23), b23 = b(23); float a24 = a(24), b24 = b(24); float a31 = a(31), b31 = b(31); float a32 = a(32), b32 = b(32); float a33 = a(33), b33 = b(33); float a34 = a(34), b34 = b(34); float a41 = a(41); float a42 = a(42); float a43 = a(43); float a44 = a(44); c(11) = a11*b11 + a12*b21 + a13*b31; c(12) = a11*b12 + a12*b22 + a13*b32; c(13) = a11*b13 + a12*b23 + a13*b33; c(14) = a11*b14 + a12*b24 + a13*b34 + a14; c(21) = a21*b11 + a22*b21 + a23*b31; c(22) = a21*b12 + a22*b22 + a23*b32; c(23) = a21*b13 + a22*b23 + a23*b33; c(24) = a21*b14 + a22*b24 + a23*b34 + a24; c(31) = a31*b11 + a32*b21 + a33*b31; c(32) = a31*b12 + a32*b22 + a33*b32; c(33) = a31*b13 + a32*b23 + a33*b33; c(34) = a31*b14 + a32*b24 + a33*b34 + a34; c(41) = a41*b11 + a42*b21 + a43*b31; c(42) = a41*b12 + a42*b22 + a43*b32; c(43) = a41*b13 + a42*b23 + a43*b33; c(44) = a41*b14 + a42*b24 + a43*b34 + a44; pC->flags = 0; #undef a #undef b } /* ** Matrix A has three rows ** Multiply matrix A by float field, storing the result in matrix C */ INLINE void m_MatMultA0001(Matrix *pA, float *pB, Matrix *pC) { #define a(x) (pA->v[OF_##x]) #define b(x) (pB[OF_##x]) #define c(x) (pC->v[OF_##x]) float a11 = a(11), b11 = b(11); float a12 = a(12), b12 = b(12); float a13 = a(13), b13 = b(13); float a14 = a(14), b14 = b(14); float a21 = a(21), b21 = b(21); float a22 = a(22), b22 = b(22); float a23 = a(23), b23 = b(23); float a24 = a(24), b24 = b(24); float a31 = a(31), b31 = b(31); float a32 = a(32), b32 = b(32); float a33 = a(33), b33 = b(33); float a34 = a(34), b34 = b(34); float b41 = b(41); float b42 = b(42); float b43 = b(43); float b44 = b(44); c(11) = a11*b11 + a12*b21 + a13*b31 + a14*b41; c(12) = a11*b12 + a12*b22 + a13*b32 + a14*b42; c(13) = a11*b13 + a12*b23 + a13*b33 + a14*b43; c(14) = a11*b14 + a12*b24 + a13*b34 + a14*b44; c(21) = a21*b11 + a22*b21 + a23*b31 + a24*b41; c(22) = a21*b12 + a22*b22 + a23*b32 + a24*b42; c(23) = a21*b13 + a22*b23 + a23*b33 + a24*b43; c(24) = a21*b14 + a22*b24 + a23*b34 + a24*b44; c(31) = a31*b11 + a32*b21 + a33*b31 + a34*b41; c(32) = a31*b12 + a32*b22 + a33*b32 + a34*b42; c(33) = a31*b13 + a32*b23 + a33*b33 + a34*b43; c(34) = a31*b14 + a32*b24 + a33*b34 + a34*b44; c(41) = b41; c(42) = b42; c(43) = b43; c(44) = b44; pC->flags = 0; #undef a #undef b } /* ** Matrix A is a translation matrix ** Multiply matrix A by float field, storing the result in matrix C */ INLINE void m_MatMultATrans(Matrix *pA, float *pB, Matrix *pC) { #define a(x) (pA->v[OF_##x]) #define b(x) (pB[OF_##x]) #define c(x) (pC->v[OF_##x]) float b11 = b(11); float b12 = b(12); float b13 = b(13); float a14 = a(14), b14 = b(14); float b21 = b(21); float b22 = b(22); float b23 = b(23); float a24 = a(24), b24 = b(24); float b31 = b(31); float b32 = b(32); float b33 = b(33); float a34 = a(34), b34 = b(34); float b41 = b(41); float b42 = b(42); float b43 = b(43); float b44 = b(44); c(11) = b11 + a14*b41; c(12) = b12 + a14*b42; c(13) = b13 + a14*b43; c(14) = b14 + a14*b44; c(21) = b21 + a24*b41; c(22) = b22 + a24*b42; c(23) = b23 + a24*b43; c(24) = b24 + a24*b44; c(31) = b31 + a34*b41; c(32) = b32 + a34*b42; c(33) = b33 + a34*b43; c(34) = b34 + a34*b44; c(41) = b41; c(42) = b42; c(43) = b43; c(44) = b44; pC->flags = 0; #undef a #undef b } /* ** Matrix B is a translation matrix ** Multiply matrix A by float field, storing the result in matrix C */ INLINE void m_MatMultBTrans(Matrix *pA, float *pB, Matrix *pC) { #define a(x) (pA->v[OF_##x]) #define b(x) (pB[OF_##x]) #define c(x) (pC->v[OF_##x]) float a11 = a(11); float a12 = a(12); float a13 = a(13); float a14 = a(14), b14 = b(14); float a21 = a(21); float a22 = a(22); float a23 = a(23); float a24 = a(24), b24 = b(24); float a31 = a(31); float a32 = a(32); float a33 = a(33); float a34 = a(34), b34 = b(34); float a41 = a(41); float a42 = a(42); float a43 = a(43); float a44 = a(44); c(11) = a11; c(12) = a12; c(13) = a13; c(14) = a14*b14 + a12*b24 + a13*b34 + a14; c(21) = a21; c(22) = a22; c(23) = a22; c(24) = a21*b14 + a22*b24 + a23*b34 + a24; c(31) = a31; c(32) = a32; c(33) = a33; c(34) = a31*b14 + a32*b24 + a33*b34 + a34; c(41) = a41; c(42) = a42; c(43) = a43; c(44) = a41*b14 + a42*b24 + a43*b34 + a44; pC->flags = 0; #undef a #undef b } INLINE void m_LoadMatrixf(Matrix *pA, const float *v) { #define a(x) pA->v[OF_##x] = *v++ a(11); a(21); a(31); a(41); a(12); a(22); a(32); a(42); a(13); a(23); a(33); a(43); a(14); a(24); a(34); a(44); if (*(v-4) == 0.f && *(v-3) == 0.f && *(v-2) == 0.f && *(v-1) == 1.f) { pA->flags = MGLMAT_0001; } else { pA->flags = 0; } #undef a } INLINE void m_LoadMatrixd(Matrix *pA, const double *v) { #define a(x) pA->v[OF_##x] = (float)*v++ a(11); a(21); a(31); a(41); a(12); a(22); a(32); a(42); a(13); a(23); a(33); a(43); a(14); a(24); a(34); a(44); if (*(v-4) == 0.0 && *(v-3) == 0.0 && *(v-2) == 0.0 && *(v-1) == 1.0) { pA->flags = MGLMAT_0001; } else { pA->flags = 0; } #undef a } INLINE void m_LoadIdentity(Matrix *pA) { #define a(x) pA->v[OF_##x] = 0.f; #define b(x) pA->v[OF_##x] = 1.f; b(11); a(21); a(31); a(41); a(12); b(22); a(32); a(42); a(13); a(23); b(33); a(43); a(14); a(24); a(34); b(44); pA->flags = MGLMAT_IDENTITY; #undef a #undef b } /* ** Multiply matrix A by the matrix passed by v. ** The vtype specifies what kind of matrix v points to, so that ** this routine may select an optimized matrix multiplication routine. */ INLINE void m_Mult(Matrix *pA, float *v, int vtype, Matrix *pC) { #if 1 #ifdef MGL_USE_ALTIVEC if (useVectorUnit) { m_Mult_altivec(pA, v, vtype, pC); return; } #endif if ((pA->flags & vtype) == 0) { m_MatMultGeneral(pA, v, pC); } else if (vtype == MGLMAT_TRANSLATION) { m_MatMultBTrans(pA, v, pC); } else if (vtype == MGLMAT_ROTATION || vtype == MGLMAT_0001) { m_MatMultB0001(pA, v, pC); } else if (pA->flags == MGLMAT_TRANSLATION) { m_MatMultATrans(pA, v, pC); } else if (pA->flags == MGLMAT_0001) { m_MatMultA0001(pA, v, pC); } else { m_MatMultGeneral(pA, v, pC); } pC->flags = 0; if (vtype & MGLMASK_0001) { if (pA->flags & MGLMASK_0001) { pC->flags = MGLMAT_0001; } } #else //FIXME: Put those special case mults back. m_MatMultGeneral(pA, v, pC); #endif } void m_CombineMatrices(GLcontext context) { m_Mult(CurrentP, CurrentMV->v, CurrentMV->flags, &(context->CombinedMatrix)); context->CombinedValid = GL_TRUE; } void m_PrintMatrix(Matrix *pA) { #define a(x) (pA->v[OF_##x]) IExec->DebugPrintF("Matrix at 0x%lX\n", (uint32)pA); IExec->DebugPrintF(" | %6.3f %6.3f %6.3f %6.3f |\n", a(11), a(12), a(13), a(14)); IExec->DebugPrintF(" | %6.3f %6.3f %6.3f %6.3f |\n", a(21), a(22), a(23), a(24)); IExec->DebugPrintF("A = | %6.3f %6.3f %6.3f %6.3f |\n", a(31), a(32), a(33), a(34)); IExec->DebugPrintF(" | %6.3f %6.3f %6.3f %6.3f |\n", a(41), a(42), a(43), a(44)); #undef a } // Interface functions void cgl_GLMatrixMode(struct GLContextIFace *Self, GLenum mode) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(MatrixMode(Self, mode)) GLASSERT(mode == GL_PROJECTION || mode == GL_MODELVIEW || mode == GL_TEXTURE); GLASSERT(context != NULL); context->transform.CurrentMatrixMode = mode; } void cgl_GLLoadIdentity(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(LoadIdentity(Self)) GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); switch (context->transform.CurrentMatrixMode) { case GL_MODELVIEW: m_LoadIdentity(CurrentMV); context->CombinedValid = GL_FALSE; context->InvRotValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; break; case GL_PROJECTION: m_LoadIdentity(CurrentP); context->CombinedValid = GL_FALSE; context->InvRotValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; break; case GL_TEXTURE: m_LoadIdentity(CurrentT); context->TexFrameCode++; break; } } void cgl_GLLoadMatrixf(struct GLContextIFace *Self, const GLfloat *m) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(LoadMatrixf(Self, m)) GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->CombinedValid = GL_FALSE; context->InvRotValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; } m_LoadMatrixf(CMATRIX(context), m); if (context->transform.CurrentMatrixMode == GL_TEXTURE) { context->TexFrameCode++; } else { context->FrameCode++; } } void cgl_GLLoadMatrixd(struct GLContextIFace *Self, const GLdouble *m) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(LoadMatrixd(Self, m)) GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->CombinedValid = GL_FALSE; context->InvRotValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; } m_LoadMatrixd(CMATRIX(context), m); if (context->transform.CurrentMatrixMode == GL_TEXTURE) { context->TexFrameCode++; } else { context->FrameCode++; } } void cgl_GLPushMatrix(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(PushMatrix(Self)) GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); switch (context->transform.CurrentMatrixMode) { case GL_PROJECTION: GLFlagError(context, context->ProjectionStackPointer >= MGL_PROJECTION_STACK_SIZE, GL_STACK_OVERFLOW); m_MatCopy(&(context->ProjectionStack[context->ProjectionStackPointer]), CurrentP); context->ProjectionStackPointer ++; break; case GL_MODELVIEW: GLFlagError(context, context->ModelViewStackPointer >= MGL_MODELVIEW_STACK_SIZE, GL_STACK_OVERFLOW); m_MatCopy(&(context->ModelViewStack[context->ModelViewStackPointer]), CurrentMV); context->ModelViewStackPointer ++; break; case GL_TEXTURE: { uint32 tmu; tmu = context->texture.ActiveTexture; GLFlagError(context, context->TextureStackPointer[tmu] >= MGL_TEXTURE_STACK_SIZE, GL_STACK_OVERFLOW); m_MatCopy(&(context->TextureStack[context->TextureStackPointer[tmu]][tmu]), CurrentT); context->TextureStackPointer[tmu] ++; break; } } } void cgl_GLPopMatrix(struct GLContextIFace *Self) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(PopMatrix(Self)) uint32 tmu; GLASSERT(context != NULL); tmu = context->texture.ActiveTexture; GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; } switch (context->transform.CurrentMatrixMode) { case GL_PROJECTION: if (context->ProjectionStackPointer <= 0) { context->CurrentError = GL_INVALID_OPERATION; return; } context->ProjectionStackPointer --; m_MatCopy(CurrentP, &(context->ProjectionStack[context->ProjectionStackPointer])); context->FrameCode++; break; case GL_MODELVIEW: if (context->ModelViewStackPointer <= 0) { context->CurrentError = GL_INVALID_OPERATION; return; } context->ModelViewStackPointer --; m_MatCopy(CurrentMV, &(context->ModelViewStack[context->ModelViewStackPointer])); context->FrameCode++; break; case GL_TEXTURE: if (context->TextureStackPointer[tmu] <= 0) { context->CurrentError = GL_INVALID_OPERATION; return; } context->TextureStackPointer[tmu] --; m_MatCopy(CurrentT, &(context->TextureStack[context->TextureStackPointer[tmu]][tmu])); context->TexFrameCode++; break; } } void cgl_GLFrustum(struct GLContextIFace *Self, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Frustum(Self, left, right, bottom, top, zNear, zFar)) float v[16]; float n2 = 2.0*zNear; float rli = 1.f / (float)(right-left); float tbi = 1.f / (float)(top-bottom); float fni = 1.f / (float)(zFar-zNear); //LOG(3, glFrustum, "%lf &lf %lf %lf %lf %lf", left, right, bottom, top, zNear, zFar); GLASSERT(context != NULL); GLFlagError(context, zFar<=0.0 || zNear <=0.0, GL_INVALID_VALUE); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } v[OF_11] = n2*rli; v[OF_21] = 0.0; v[OF_31] = 0.0; v[OF_41] = 0.0; v[OF_22] = n2*tbi; v[OF_12] = 0.0; v[OF_32] = 0.0; v[OF_42] = 0.0; v[OF_13] = (right+left)*rli; v[OF_23] = (top+bottom)*tbi; v[OF_33] = -(zFar+zNear)*fni; v[OF_43] = -1.0; v[OF_14] = 0.0; v[OF_24] = 0.0; v[OF_34] = -(2.0*zFar*zNear)*fni; v[OF_44] = 0.0; m_Mult(CMATRIX(context), v, MGLMAT_PERSPECTIVE, OMATRIX(context) ); SMATRIX(context); } void cgl_GLOrtho(struct GLContextIFace *Self, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Ortho(Self, left, right, bottom, top, zNear, zFar)) float rli = 1.0 / (right-left); float tbi = 1.0 / (top-bottom); float fni = 1.0 / (zFar-zNear); float v[16]; //LOG(3, glOrtho, "%lf %lf %lf %lf %lf %lf", left, right, bottom, top, zNear, zFar); GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); GLFlagError(context, left == right || bottom == top || zNear == zFar, GL_INVALID_VALUE); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } v[OF_11] = 2.0*rli; v[OF_12] = 0.0; v[OF_13] = 0.0; v[OF_14] = -(right+left)*rli; v[OF_21] = 0.0; v[OF_22] = 2.0*tbi; v[OF_23] = 0.0; v[OF_24] = -(top+bottom)*tbi; v[OF_31] = 0.0; v[OF_32] = 0.0; v[OF_33] = -2.0*fni; v[OF_34] = -(zFar+zNear)*fni; v[OF_41] = 0.0; v[OF_42] = 0.0; v[OF_43] = 0.0; v[OF_44] = 1.0; m_Mult(CMATRIX(context), v, MGLMAT_ORTHO, OMATRIX(context)); SMATRIX(context); } void cgl_GLMultMatrixf(struct GLContextIFace *Self, const GLfloat *mat) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(MultMatrixf(Self, mat)) GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } m_Mult(CMATRIX(context), (float *)mat, 0, OMATRIX(context)); SMATRIX(context); } void cgl_GLMultMatrixd(struct GLContextIFace *Self, const GLdouble *mat) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(MultMatrixd(Self, mat)) GLfloat v[16]; int i; GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } for (i=0; i<16; i++) { v[i] = (GLfloat) *mat++; } m_Mult(CMATRIX(context), v, 0, OMATRIX(context)); SMATRIX(context); } /* ** The following routine was ripped from the Mesa source code. ** I did use this because it is much better than my original design. The code ** is just modified a bit to adapt to my code layout, but otherwise is unmodified. ** This code is included with the kind permission of Brian Paul, the author of Mesa. */ void cgl_GLRotatef(struct GLContextIFace *Self, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Rotatef(Self, angle, x, y, z)) float v[16]; #define v(x) v[OF_##x] float recMag, s, c; float xx,yy,zz,xy,yz,zx,xs,ys,zs,one_c; //LOG(3, glRotatef, "%f %f %f %f", angle, x,y,z); GLASSERT(context != NULL); GLFlagError(context, context->CurrentPrimitive != GL_BASE, GL_INVALID_OPERATION); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } s = (float)sin(angle * PI/180.0); c = (float)cos(angle * PI/180.0); float lenSq = x*x+y*y+z*z; if (lenSq == 0.0f) return; if (lenSq != 1.0) { recMag = fast_reciprocal_sqrt(lenSq); x *= recMag; y *= recMag; z *= recMag; } xx = x*x; yy = y*y; zz = z*z; xy = x*y; yz = y*z; zx = z*x; xs = x*s; ys = y*s; zs = z*s; one_c = 1.f - c; v(11) = one_c*xx + c; v(12) = one_c*xy - zs; v(13) = one_c*zx + ys; v(14) = 0.f; v(21) = one_c*xy + zs; v(22) = one_c*yy + c; v(23) = one_c*yz - xs; v(24) = 0.f; v(31) = one_c*zx - ys; v(32) = one_c*yz + xs; v(33) = one_c*zz + c; v(34) = 0.f; v(41) = 0.f; v(42) = 0.f; v(43) = 0.f; v(44) = 1.f; m_Mult(CMATRIX(context), v, MGLMAT_ROTATION, OMATRIX(context)); SMATRIX(context); #undef v } void cgl_GLScalef(struct GLContextIFace *Self, GLfloat x, GLfloat y, GLfloat z) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Scalef(Self, x, y, z)) float v[16]; //LOG(3, glScalef, "%f %f %f", x,y,z); GLASSERT(context!=NULL); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } #define v(x) v[OF_##x] v(11) = x; v(12) = 0.0; v(13) = 0.0; v(14) = 0.0; v(21) = 0.0; v(22) = y; v(23) = 0.0; v(24) = 0.0; v(31) = 0.0; v(32) = 0.0; v(33) = z; v(34) = 0.0; v(41) = 0.0; v(42) = 0.0; v(43) = 0.0; v(44) = 1.0; m_Mult(CMATRIX(context), v, MGLMAT_GENERAL_SCALE, OMATRIX(context)); SMATRIX(context); #undef v } void cgl_GLTranslatef(struct GLContextIFace *Self, GLfloat x, GLfloat y, GLfloat z) { float vv[16]; GLcontext context = GET_INSTANCE(Self); DL_CHECK(Translatef(Self, x, y, z)) GLASSERT(context != NULL); if (context->transform.CurrentMatrixMode != GL_TEXTURE) { context->InvRotValid = GL_FALSE; context->CombinedValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; context->FrameCode++; } else { context->TexFrameCode++; } #define v(x) vv[OF_##x] v(11) = v(22) = v(33) = v(44) = 1.f; v(21) = v(31) = v(41) = v(12) = v(32) = v(42) = v(13) = v(23) = v(43) = 0.f; v(14) = (float)x; v(24) = (float)y; v(34) = (float)z; #undef v m_Mult(CMATRIX(context), vv, MGLMAT_TRANSLATION, OMATRIX(context)); SMATRIX(context); } void GLMatrixInit(GLcontext context) { int i; uint32 current = context->texture.ActiveTexture; struct GLContextIFace *Self = context->Self; context->ModelViewStackPointer = 0; context->ProjectionStackPointer = 0; context->ModelViewNr = 0; context->ProjectionNr = 0; // m_LoadIdentity(&context->ModelView[0]); // m_LoadIdentity(&context->ModelView[1]); for (i = 0; i < MAX_TEXTURE_UNITS; i++) { context->texture.ActiveTexture = i; context->TextureStackPointer[i] = 0; context->TextureNr[i] = 0; Self->GLMatrixMode(GL_TEXTURE); Self->GLLoadIdentity(); } context->texture.ActiveTexture = current; context->CombinedValid = GL_FALSE; context->InvRotValid = GL_FALSE; context->InverseModelViewValid = GL_FALSE; Self->GLMatrixMode(GL_PROJECTION); Self->GLLoadIdentity(); Self->GLMatrixMode(GL_MODELVIEW); Self->GLLoadIdentity(); useVectorUnit = FALSE; #ifdef MGL_USE_ALTIVEC char buffer[10]; uint32 vectorUnit; IExec->GetCPUInfoTags(GCIT_VectorUnit, &vectorUnit, TAG_DONE); BOOL varExists = IDOS->GetVar("MiniGL/UseVectorUnit", buffer, sizeof(buffer), 0) != -1; if (vectorUnit != VECTORTYPE_NONE) { useVectorUnit = TRUE; if (varExists && (strcmp(buffer, "0") == 0 || strcasecmp(buffer, "off") == 0)) { useVectorUnit = FALSE; } } if (useVectorUnit) { disableDenormalizedException(); } #endif } void cgl_GLRotatefv(struct GLContextIFace *Self, const GLfloat *angle_xyz) { cgl_GLRotatef(Self,angle_xyz[0],angle_xyz[1],angle_xyz[2],angle_xyz[3]); } void cgl_GLScalefv(struct GLContextIFace *Self, const GLfloat *xyz) { cgl_GLScalef(Self,xyz[0],xyz[1],xyz[2]); } void cgl_GLTranslatefv(struct GLContextIFace *Self, const GLfloat *xyz) { cgl_GLTranslatef(Self,xyz[0],xyz[1],xyz[2]); }