home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / matrix.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  13KB  |  484 lines

  1. /* $Id: matrix.c,v 1.45 2002/10/24 23:57:21 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Matrix operations
  30.  *
  31.  * NOTES:
  32.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  33.  * 2. Points/vertices are to be thought of as column vectors.
  34.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  35.  */
  36.  
  37.  
  38. #include "glheader.h"
  39. #include "imports.h"
  40. #include "buffers.h"
  41. #include "context.h"
  42. #include "enums.h"
  43. #include "macros.h"
  44. #include "matrix.h"
  45. #include "mmath.h"
  46. #include "mtypes.h"
  47. #include "math/m_matrix.h"
  48.  
  49.  
  50.  
  51. void
  52. _mesa_Frustum( GLdouble left, GLdouble right,
  53.                GLdouble bottom, GLdouble top,
  54.                GLdouble nearval, GLdouble farval )
  55. {
  56.    GET_CURRENT_CONTEXT(ctx);
  57.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  58.  
  59.    if (nearval <= 0.0 ||
  60.        farval <= 0.0 ||
  61.        nearval == farval ||
  62.        left == right ||
  63.        top == bottom)
  64.    {
  65.       _mesa_error( ctx,  GL_INVALID_VALUE, "glFrustum" );
  66.       return;
  67.    }
  68.  
  69.    _math_matrix_frustum( ctx->CurrentStack->Top,
  70.                          (GLfloat) left, (GLfloat) right, 
  71.              (GLfloat) bottom, (GLfloat) top, 
  72.              (GLfloat) nearval, (GLfloat) farval );
  73.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  74. }
  75.  
  76.  
  77. void
  78. _mesa_Ortho( GLdouble left, GLdouble right,
  79.              GLdouble bottom, GLdouble top,
  80.              GLdouble nearval, GLdouble farval )
  81. {
  82.    GET_CURRENT_CONTEXT(ctx);
  83.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  84.  
  85.    if (MESA_VERBOSE & VERBOSE_API)
  86.       _mesa_debug(ctx, "glFrustum(%f, %f, %f, %f, %f, %f)\n",
  87.                   left, right, bottom, top, nearval, farval);
  88.  
  89.    if (left == right ||
  90.        bottom == top ||
  91.        nearval == farval)
  92.    {
  93.       _mesa_error( ctx,  GL_INVALID_VALUE, "glOrtho" );
  94.       return;
  95.    }
  96.  
  97.    _math_matrix_ortho( ctx->CurrentStack->Top,
  98.                        (GLfloat) left, (GLfloat) right, 
  99.                (GLfloat) bottom, (GLfloat) top, 
  100.                (GLfloat) nearval, (GLfloat) farval );
  101.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  102. }
  103.  
  104.  
  105. void
  106. _mesa_MatrixMode( GLenum mode )
  107. {
  108.    GET_CURRENT_CONTEXT(ctx);
  109.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  110.  
  111.    if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE)
  112.       return;
  113.    FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
  114.  
  115.    switch (mode) {
  116.    case GL_MODELVIEW:
  117.       ctx->CurrentStack = &ctx->ModelviewMatrixStack;
  118.       break;
  119.    case GL_PROJECTION:
  120.       ctx->CurrentStack = &ctx->ProjectionMatrixStack;
  121.       break;
  122.    case GL_TEXTURE:
  123.       ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit];
  124.       break;
  125.    case GL_COLOR:
  126.       ctx->CurrentStack = &ctx->ColorMatrixStack;
  127.       break;
  128.    case GL_MATRIX0_NV:
  129.    case GL_MATRIX1_NV:
  130.    case GL_MATRIX2_NV:
  131.    case GL_MATRIX3_NV:
  132.    case GL_MATRIX4_NV:
  133.    case GL_MATRIX5_NV:
  134.    case GL_MATRIX6_NV:
  135.    case GL_MATRIX7_NV:
  136.       if (!ctx->Extensions.NV_vertex_program) {
  137.          _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode" );
  138.          return;
  139.       }
  140.       ctx->CurrentStack = &ctx->ProgramMatrixStack[mode - GL_MATRIX0_NV];
  141.       break;
  142.    default:
  143.       _mesa_error( ctx,  GL_INVALID_ENUM, "glMatrixMode" );
  144.       return;
  145.    }
  146.  
  147.    ctx->Transform.MatrixMode = mode;
  148. }
  149.  
  150.  
  151.  
  152. void
  153. _mesa_PushMatrix( void )
  154. {
  155.    GET_CURRENT_CONTEXT(ctx);
  156.    struct matrix_stack *stack = ctx->CurrentStack;
  157.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  158.  
  159.    if (MESA_VERBOSE&VERBOSE_API)
  160.       _mesa_debug(ctx, "glPushMatrix %s\n",
  161.                   _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  162.  
  163.    if (stack->Depth + 1 >= stack->MaxDepth) {
  164.       _mesa_error( ctx,  GL_STACK_OVERFLOW, "glPushMatrix" );
  165.       return;
  166.    }
  167.    _math_matrix_copy( &stack->Stack[stack->Depth + 1],
  168.                       &stack->Stack[stack->Depth] );
  169.    stack->Depth++;
  170.    stack->Top = &(stack->Stack[stack->Depth]);
  171.    ctx->NewState |= stack->DirtyFlag;
  172. }
  173.  
  174.  
  175.  
  176. void
  177. _mesa_PopMatrix( void )
  178. {
  179.    GET_CURRENT_CONTEXT(ctx);
  180.    struct matrix_stack *stack = ctx->CurrentStack;
  181.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  182.  
  183.    if (MESA_VERBOSE&VERBOSE_API)
  184.       _mesa_debug(ctx, "glPopMatrix %s\n",
  185.                   _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode));
  186.  
  187.    if (stack->Depth == 0) {
  188.       _mesa_error( ctx,  GL_STACK_UNDERFLOW, "glPopMatrix" );
  189.       return;
  190.    }
  191.    stack->Depth--;
  192.    stack->Top = &(stack->Stack[stack->Depth]);
  193.    ctx->NewState |= stack->DirtyFlag;
  194. }
  195.  
  196.  
  197.  
  198. void
  199. _mesa_LoadIdentity( void )
  200. {
  201.    GET_CURRENT_CONTEXT(ctx);
  202.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  203.  
  204.    if (MESA_VERBOSE & VERBOSE_API)
  205.       _mesa_debug(ctx, "glLoadIdentity()");
  206.  
  207.    _math_matrix_set_identity( ctx->CurrentStack->Top );
  208.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  209. }
  210.  
  211.  
  212. void
  213. _mesa_LoadMatrixf( const GLfloat *m )
  214. {
  215.    GET_CURRENT_CONTEXT(ctx);
  216.    if (!m) return;
  217.    if (MESA_VERBOSE & VERBOSE_API)
  218.       _mesa_debug(ctx,
  219.           "glLoadMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
  220.           m[0], m[4], m[8], m[12],
  221.           m[1], m[5], m[9], m[13],
  222.           m[2], m[6], m[10], m[14],
  223.           m[3], m[7], m[11], m[15]);
  224.  
  225.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  226.    _math_matrix_loadf( ctx->CurrentStack->Top, m );
  227.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  228. }
  229.  
  230.  
  231. void
  232. _mesa_LoadMatrixd( const GLdouble *m )
  233. {
  234.    GLint i;
  235.    GLfloat f[16];
  236.    if (!m) return;
  237.    for (i = 0; i < 16; i++)
  238.       f[i] = (GLfloat) m[i];
  239.    _mesa_LoadMatrixf(f);
  240. }
  241.  
  242.  
  243.  
  244. /*
  245.  * Multiply the active matrix by an arbitary matrix.
  246.  */
  247. void
  248. _mesa_MultMatrixf( const GLfloat *m )
  249. {
  250.    GET_CURRENT_CONTEXT(ctx);
  251.    if (!m) return;
  252.    if (MESA_VERBOSE & VERBOSE_API)
  253.       _mesa_debug(ctx,
  254.           "glMultMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n",
  255.           m[0], m[4], m[8], m[12],
  256.           m[1], m[5], m[9], m[13],
  257.           m[2], m[6], m[10], m[14],
  258.           m[3], m[7], m[11], m[15]);
  259.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  260.    _math_matrix_mul_floats( ctx->CurrentStack->Top, m );
  261.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  262. }
  263.  
  264.  
  265. /*
  266.  * Multiply the active matrix by an arbitary matrix.
  267.  */
  268. void
  269. _mesa_MultMatrixd( const GLdouble *m )
  270. {
  271.    GLint i;
  272.    GLfloat f[16];
  273.    if (!m) return;
  274.    for (i = 0; i < 16; i++)
  275.       f[i] = (GLfloat) m[i];
  276.    _mesa_MultMatrixf( f );
  277. }
  278.  
  279.  
  280.  
  281.  
  282. /*
  283.  * Execute a glRotate call
  284.  */
  285. void
  286. _mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
  287. {
  288.    GET_CURRENT_CONTEXT(ctx);
  289.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  290.    if (angle != 0.0F) {
  291.       _math_matrix_rotate( ctx->CurrentStack->Top, angle, x, y, z);
  292.       ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  293.    }
  294. }
  295.  
  296. void
  297. _mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
  298. {
  299.    _mesa_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
  300. }
  301.  
  302.  
  303. /*
  304.  * Execute a glScale call
  305.  */
  306. void
  307. _mesa_Scalef( GLfloat x, GLfloat y, GLfloat z )
  308. {
  309.    GET_CURRENT_CONTEXT(ctx);
  310.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  311.    _math_matrix_scale( ctx->CurrentStack->Top, x, y, z);
  312.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  313. }
  314.  
  315.  
  316. void
  317. _mesa_Scaled( GLdouble x, GLdouble y, GLdouble z )
  318. {
  319.    _mesa_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
  320. }
  321.  
  322.  
  323. /*
  324.  * Execute a glTranslate call
  325.  */
  326. void
  327. _mesa_Translatef( GLfloat x, GLfloat y, GLfloat z )
  328. {
  329.    GET_CURRENT_CONTEXT(ctx);
  330.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  331.    _math_matrix_translate( ctx->CurrentStack->Top, x, y, z);
  332.    ctx->NewState |= ctx->CurrentStack->DirtyFlag;
  333. }
  334.  
  335.  
  336. void
  337. _mesa_Translated( GLdouble x, GLdouble y, GLdouble z )
  338. {
  339.    _mesa_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
  340. }
  341.  
  342.  
  343. void
  344. _mesa_LoadTransposeMatrixfARB( const GLfloat *m )
  345. {
  346.    GLfloat tm[16];
  347.    if (!m) return;
  348.    _math_transposef(tm, m);
  349.    _mesa_LoadMatrixf(tm);
  350. }
  351.  
  352.  
  353. void
  354. _mesa_LoadTransposeMatrixdARB( const GLdouble *m )
  355. {
  356.    GLfloat tm[16];
  357.    if (!m) return;
  358.    _math_transposefd(tm, m);
  359.    _mesa_LoadMatrixf(tm);
  360. }
  361.  
  362.  
  363. void
  364. _mesa_MultTransposeMatrixfARB( const GLfloat *m )
  365. {
  366.    GLfloat tm[16];
  367.    if (!m) return;
  368.    _math_transposef(tm, m);
  369.    _mesa_MultMatrixf(tm);
  370. }
  371.  
  372.  
  373. void
  374. _mesa_MultTransposeMatrixdARB( const GLdouble *m )
  375. {
  376.    GLfloat tm[16];
  377.    if (!m) return;
  378.    _math_transposefd(tm, m);
  379.    _mesa_MultMatrixf(tm);
  380. }
  381.  
  382.  
  383. /*
  384.  * Called via glViewport or display list execution.
  385.  */
  386. void
  387. _mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height )
  388. {
  389.    GET_CURRENT_CONTEXT(ctx);
  390.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  391.    _mesa_set_viewport(ctx, x, y, width, height);
  392. }
  393.  
  394.  
  395. /*
  396.  * Define a new viewport and reallocate auxillary buffers if the size of
  397.  * the window (color buffer) has changed.
  398.  */
  399. void
  400. _mesa_set_viewport( GLcontext *ctx, GLint x, GLint y,
  401.                     GLsizei width, GLsizei height )
  402. {
  403.    const GLfloat n = ctx->Viewport.Near;
  404.    const GLfloat f = ctx->Viewport.Far;
  405.  
  406.    if (MESA_VERBOSE & VERBOSE_API)
  407.       _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height);
  408.  
  409.    if (width < 0 || height < 0) {
  410.       _mesa_error( ctx,  GL_INVALID_VALUE,
  411.                    "glViewport(%d, %d, %d, %d)", x, y, width, height );
  412.       return;
  413.    }
  414.  
  415.    /* clamp width, and height to implementation dependent range */
  416.    width  = CLAMP( width,  1, MAX_WIDTH );
  417.    height = CLAMP( height, 1, MAX_HEIGHT );
  418.  
  419.    /* Save viewport */
  420.    ctx->Viewport.X = x;
  421.    ctx->Viewport.Width = width;
  422.    ctx->Viewport.Y = y;
  423.    ctx->Viewport.Height = height;
  424.  
  425.    /* compute scale and bias values :: This is really driver-specific
  426.     * and should be maintained elsewhere if at all.
  427.     */
  428.    ctx->Viewport._WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F;
  429.    ctx->Viewport._WindowMap.m[MAT_TX] = ctx->Viewport._WindowMap.m[MAT_SX] + x;
  430.    ctx->Viewport._WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F;
  431.    ctx->Viewport._WindowMap.m[MAT_TY] = ctx->Viewport._WindowMap.m[MAT_SY] + y;
  432.    ctx->Viewport._WindowMap.m[MAT_SZ] = ctx->DepthMaxF * ((f - n) / 2.0F);
  433.    ctx->Viewport._WindowMap.m[MAT_TZ] = ctx->DepthMaxF * ((f - n) / 2.0F + n);
  434.    ctx->Viewport._WindowMap.flags = MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION;
  435.    ctx->Viewport._WindowMap.type = MATRIX_3D_NO_ROT;
  436.    ctx->NewState |= _NEW_VIEWPORT;
  437.  
  438.    /* Check if window/buffer has been resized and if so, reallocate the
  439.     * ancillary buffers.
  440.     */
  441.    _mesa_ResizeBuffersMESA();
  442.  
  443.    if (ctx->Driver.Viewport) {
  444.       (*ctx->Driver.Viewport)( ctx, x, y, width, height );
  445.    }
  446. }
  447.  
  448.  
  449.  
  450. void
  451. _mesa_DepthRange( GLclampd nearval, GLclampd farval )
  452. {
  453.    /*
  454.     * nearval - specifies mapping of the near clipping plane to window
  455.     *   coordinates, default is 0
  456.     * farval - specifies mapping of the far clipping plane to window
  457.     *   coordinates, default is 1
  458.     *
  459.     * After clipping and div by w, z coords are in -1.0 to 1.0,
  460.     * corresponding to near and far clipping planes.  glDepthRange
  461.     * specifies a linear mapping of the normalized z coords in
  462.     * this range to window z coords.
  463.     */
  464.    GLfloat n, f;
  465.    GET_CURRENT_CONTEXT(ctx);
  466.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  467.  
  468.    if (MESA_VERBOSE&VERBOSE_API)
  469.       _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval);
  470.  
  471.    n = (GLfloat) CLAMP( nearval, 0.0, 1.0 );
  472.    f = (GLfloat) CLAMP( farval, 0.0, 1.0 );
  473.  
  474.    ctx->Viewport.Near = n;
  475.    ctx->Viewport.Far = f;
  476.    ctx->Viewport._WindowMap.m[MAT_SZ] = ctx->DepthMaxF * ((f - n) / 2.0F);
  477.    ctx->Viewport._WindowMap.m[MAT_TZ] = ctx->DepthMaxF * ((f - n) / 2.0F + n);
  478.    ctx->NewState |= _NEW_VIEWPORT;
  479.  
  480.    if (ctx->Driver.DepthRange) {
  481.       (*ctx->Driver.DepthRange)( ctx, nearval, farval );
  482.    }
  483. }
  484.