home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / varray.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  20KB  |  670 lines

  1. /* $Id: varray.c,v 1.4 1996/04/30 12:18:21 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995-1996  Brian Paul  (brianp@ssec.wisc.edu)
  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: varray.c,v $
  26.  * Revision 1.4  1996/04/30  12:18:21  brianp
  27.  * typo: replaced sizeof(GLshort) with sizeof(GLint)
  28.  *
  29.  * Revision 1.3  1996/03/02  21:58:45  brianp
  30.  * only use edge flags if GL_TRIANGLES, GL_QUADS, or GL_POLYGON
  31.  *
  32.  * Revision 1.2  1996/02/20  19:48:59  brianp
  33.  * added glVertex3fv() array optimization
  34.  *
  35.  * Revision 1.1  1996/02/15  16:06:05  brianp
  36.  * Initial revision
  37.  *
  38.  */
  39.  
  40.  
  41.  
  42. /*
  43.  * NOTE:  At this time, only three vertex array configurations are optimized:
  44.  *  1.  glVertex3fv(), zero stride
  45.  *  2.  glNormal3fv() with glVertex3fv(), zero stride
  46.  *  3.  glNormal3fv() with glVertex4fv(), zero stride
  47.  *
  48.  * More optimized array configurations can be added.
  49.  */
  50.  
  51.  
  52.  
  53.  
  54. #include <string.h>
  55. #include "draw.h"
  56. #include "context.h"
  57. #include "macros.h"
  58. #include "vb.h"
  59. #include "xform.h"
  60.  
  61.  
  62.  
  63.  
  64. void glVertexPointerEXT( GLint size, GLenum type, GLsizei stride,
  65.                          GLsizei count, const void *ptr )
  66. {
  67.    if (size<2 || size>4) {
  68.       gl_error( GL_INVALID_VALUE, "glVertexPointerEXT(size)" );
  69.       return;
  70.    }
  71.    if (stride<0) {
  72.       gl_error( GL_INVALID_VALUE, "glVertexPointerEXT(stride)" );
  73.       return;
  74.    }
  75.    switch (type) {
  76.       case GL_SHORT:
  77.          CC.Array.VertexStrideB = stride ? stride : size*sizeof(GLshort);
  78.          break;
  79.       case GL_INT:
  80.          CC.Array.VertexStrideB = stride ? stride : size*sizeof(GLint);
  81.          break;
  82.       case GL_FLOAT:
  83.          CC.Array.VertexStrideB = stride ? stride : size*sizeof(GLfloat);
  84.          break;
  85.       case GL_DOUBLE_EXT:
  86.          CC.Array.VertexStrideB = stride ? stride : size*sizeof(GLdouble);
  87.          break;
  88.       default:
  89.          gl_error( GL_INVALID_ENUM, "glVertexPointerEXT(type)" );
  90.          return;
  91.    }
  92.    CC.Array.VertexSize = size;
  93.    CC.Array.VertexType = type;
  94.    CC.Array.VertexStride = stride;
  95.    CC.Array.VertexCount = count;
  96.    CC.Array.VertexPtr = (void *) ptr;
  97. }
  98.  
  99.  
  100.  
  101.  
  102. void glNormalPointerEXT( GLenum type, GLsizei stride,
  103.                          GLsizei count, const void *ptr )
  104. {
  105.    if (stride<0) {
  106.       gl_error( GL_INVALID_VALUE, "glNormalPointerEXT(stride)" );
  107.       return;
  108.    }
  109.    switch (type) {
  110.       case GL_BYTE:
  111.          CC.Array.NormalStrideB = stride ? stride : 3*sizeof(GLbyte);
  112.          break;
  113.       case GL_SHORT:
  114.          CC.Array.NormalStrideB = stride ? stride : 3*sizeof(GLshort);
  115.          break;
  116.       case GL_INT:
  117.          CC.Array.NormalStrideB = stride ? stride : 3*sizeof(GLint);
  118.          break;
  119.       case GL_FLOAT:
  120.          CC.Array.NormalStrideB = stride ? stride : 3*sizeof(GLfloat);
  121.          break;
  122.       case GL_DOUBLE_EXT:
  123.          CC.Array.NormalStrideB = stride ? stride : 3*sizeof(GLdouble);
  124.          break;
  125.       default:
  126.          gl_error( GL_INVALID_ENUM, "glNormalPointerEXT(type)" );
  127.          return;
  128.    }
  129.    CC.Array.NormalType = type;
  130.    CC.Array.NormalStride = stride;
  131.    CC.Array.NormalCount = count;
  132.    CC.Array.NormalPtr = (void *) ptr;
  133. }
  134.  
  135.  
  136.  
  137. void glColorPointerEXT( GLint size, GLenum type, GLsizei stride,
  138.                         GLsizei count, const void *ptr )
  139. {
  140.    if (size<3 || size>4) {
  141.       gl_error( GL_INVALID_VALUE, "glColorPointerEXT(size)" );
  142.       return;
  143.    }
  144.    if (stride<0) {
  145.       gl_error( GL_INVALID_VALUE, "glColorPointerEXT(stride)" );
  146.       return;
  147.    }
  148.    switch (type) {
  149.       case GL_BYTE:
  150.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLbyte);
  151.          break;
  152.       case GL_UNSIGNED_BYTE:
  153.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLubyte);
  154.          break;
  155.       case GL_SHORT:
  156.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLshort);
  157.          break;
  158.       case GL_UNSIGNED_SHORT:
  159.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLushort);
  160.          break;
  161.       case GL_INT:
  162.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLint);
  163.          break;
  164.       case GL_UNSIGNED_INT:
  165.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLuint);
  166.          break;
  167.       case GL_FLOAT:
  168.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLfloat);
  169.          break;
  170.       case GL_DOUBLE_EXT:
  171.          CC.Array.ColorStrideB = stride ? stride : size*sizeof(GLdouble);
  172.          break;
  173.       default:
  174.          gl_error( GL_INVALID_ENUM, "glColorPointerEXT(type)" );
  175.          return;
  176.    }
  177.    CC.Array.ColorSize = size;
  178.    CC.Array.ColorType = type;
  179.    CC.Array.ColorStride = stride;
  180.    CC.Array.ColorCount = count;
  181.    CC.Array.ColorPtr = (void *) ptr;
  182. }
  183.  
  184.  
  185.  
  186. void glIndexPointerEXT( GLenum type, GLsizei stride, GLsizei count,
  187.                         const void *ptr )
  188. {
  189.    if (stride<0) {
  190.       gl_error( GL_INVALID_VALUE, "glIndexPointerEXT(stride)" );
  191.       return;
  192.    }
  193.    switch (type) {
  194.       case GL_SHORT:
  195.          CC.Array.IndexStrideB = stride ? stride : sizeof(GLbyte);
  196.          break;
  197.       case GL_INT:
  198.          CC.Array.IndexStrideB = stride ? stride : sizeof(GLint);
  199.          break;
  200.       case GL_FLOAT:
  201.          CC.Array.IndexStrideB = stride ? stride : sizeof(GLfloat);
  202.          break;
  203.       case GL_DOUBLE_EXT:
  204.          CC.Array.IndexStrideB = stride ? stride : sizeof(GLdouble);
  205.          break;
  206.       default:
  207.          gl_error( GL_INVALID_ENUM, "glIndexPointerEXT(type)" );
  208.          return;
  209.    }
  210.    CC.Array.IndexType = type;
  211.    CC.Array.IndexStride = stride;
  212.    CC.Array.IndexCount = count;
  213.    CC.Array.IndexPtr = (void *) ptr;
  214. }
  215.  
  216.  
  217.  
  218. void glTexCoordPointerEXT( GLint size, GLenum type, GLsizei stride,
  219.                            GLsizei count, const void *ptr )
  220. {
  221.    if (size<1 || size>4) {
  222.       gl_error( GL_INVALID_VALUE, "glTexCoordPointerEXT(size)" );
  223.       return;
  224.    }
  225.    switch (type) {
  226.       case GL_SHORT:
  227.          CC.Array.TexCoordStrideB = stride ? stride : size*sizeof(GLshort);
  228.          break;
  229.       case GL_INT:
  230.          CC.Array.TexCoordStrideB = stride ? stride : size*sizeof(GLint);
  231.          break;
  232.       case GL_FLOAT:
  233.          CC.Array.TexCoordStrideB = stride ? stride : size*sizeof(GLfloat);
  234.          break;
  235.       case GL_DOUBLE_EXT:
  236.          CC.Array.TexCoordStrideB = stride ? stride : size*sizeof(GLdouble);
  237.          break;
  238.       default:
  239.          gl_error( GL_INVALID_ENUM, "glTexCoordPointerEXT(type)" );
  240.          return;
  241.    }
  242.    if (stride<0) {
  243.       gl_error( GL_INVALID_VALUE, "glTexCoordPointerEXT(stride)" );
  244.       return;
  245.    }
  246.    CC.Array.TexCoordSize = size;
  247.    CC.Array.TexCoordType = type;
  248.    CC.Array.TexCoordStride = stride;
  249.    CC.Array.TexCoordCount = count;
  250.    CC.Array.TexCoordPtr = (void *) ptr;
  251. }
  252.  
  253.  
  254.  
  255. void glEdgeFlagPointerEXT( GLsizei stride, GLsizei count,
  256.                            const GLboolean *ptr )
  257. {
  258.    if (stride<0) {
  259.       gl_error( GL_INVALID_VALUE, "glEdgeFlagPointerEXT(stride)" );
  260.       return;
  261.    }
  262.    CC.Array.EdgeFlagStride = stride;
  263.    CC.Array.EdgeFlagStrideB = stride ? stride : sizeof(GLboolean);
  264.    CC.Array.EdgeFlagCount = count;
  265.    CC.Array.EdgeFlagPtr = (GLboolean *) ptr;
  266. }
  267.  
  268.  
  269.  
  270. /*
  271.  * Eventually, this may be moved into get.c
  272.  */
  273. void glGetPointervEXT( GLenum pname, void **params )
  274. {
  275.    switch (pname) {
  276.       case GL_VERTEX_ARRAY_POINTER_EXT:
  277.          *params = CC.Array.VertexPtr;
  278.          break;
  279.       case GL_NORMAL_ARRAY_POINTER_EXT:
  280.          *params = CC.Array.NormalPtr;
  281.          break;
  282.       case GL_COLOR_ARRAY_POINTER_EXT:
  283.          *params = CC.Array.ColorPtr;
  284.          break;
  285.       case GL_INDEX_ARRAY_POINTER_EXT:
  286.          *params = CC.Array.IndexPtr;
  287.          break;
  288.       case GL_TEXTURE_COORD_ARRAY_POINTER_EXT:
  289.          *params = CC.Array.TexCoordPtr;
  290.          break;
  291.       case GL_EDGE_FLAG_ARRAY_POINTER_EXT:
  292.          *params = CC.Array.EdgeFlagPtr;
  293.          break;
  294.       default:
  295.          gl_error( GL_INVALID_ENUM, "glGetPointervEXT" );
  296.          return;
  297.    }
  298. }
  299.  
  300.  
  301. void glArrayElementEXT( GLint i )
  302. {
  303.    if (CC.Array.NormalEnabled) {
  304.       GLbyte *p = (GLbyte*) CC.Array.NormalPtr + i * CC.Array.NormalStrideB;
  305.       switch (CC.Array.NormalType) {
  306.          case GL_BYTE:
  307.             glNormal3bv( (GLbyte*) p );
  308.             break;
  309.          case GL_SHORT:
  310.             glNormal3sv( (GLshort*) p );
  311.             break;
  312.          case GL_INT:
  313.             glNormal3iv( (GLint*) p );
  314.             break;
  315.          case GL_FLOAT:
  316.             glNormal3fv( (GLfloat*) p );
  317.             break;
  318.          case GL_DOUBLE_EXT:
  319.             glNormal3dv( (GLdouble*) p );
  320.             break;
  321.       }
  322.    }
  323.  
  324.    if (CC.Array.ColorEnabled) {
  325.       GLbyte *p = (GLbyte*) CC.Array.ColorPtr + i * CC.Array.ColorStrideB;
  326.       switch (CC.Array.ColorType) {
  327.          case GL_BYTE:
  328.             switch (CC.Array.ColorSize) {
  329.                case 3:   glColor3bv( (GLbyte*) p );   break;
  330.                case 4:   glColor4bv( (GLbyte*) p );   break;
  331.             }
  332.             break;
  333.          case GL_UNSIGNED_BYTE:
  334.             switch (CC.Array.ColorSize) {
  335.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  336.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  337.             }
  338.             break;
  339.          case GL_SHORT:
  340.             switch (CC.Array.ColorSize) {
  341.                case 3:   glColor3sv( (GLshort*) p );   break;
  342.                case 4:   glColor4sv( (GLshort*) p );   break;
  343.             }
  344.             break;
  345.          case GL_UNSIGNED_SHORT:
  346.             switch (CC.Array.ColorSize) {
  347.                case 3:   glColor3usv( (GLushort*) p );   break;
  348.                case 4:   glColor4usv( (GLushort*) p );   break;
  349.             }
  350.             break;
  351.          case GL_INT:
  352.             switch (CC.Array.ColorSize) {
  353.                case 3:   glColor3iv( (GLint*) p );   break;
  354.                case 4:   glColor4iv( (GLint*) p );   break;
  355.             }
  356.             break;
  357.          case GL_UNSIGNED_INT:
  358.             switch (CC.Array.ColorSize) {
  359.                case 3:   glColor3uiv( (GLuint*) p );   break;
  360.                case 4:   glColor4uiv( (GLuint*) p );   break;
  361.             }
  362.             break;
  363.          case GL_FLOAT:
  364.             switch (CC.Array.ColorSize) {
  365.                case 3:   glColor3fv( (GLfloat*) p );   break;
  366.                case 4:   glColor4fv( (GLfloat*) p );   break;
  367.             }
  368.             break;
  369.          case GL_DOUBLE_EXT:
  370.             switch (CC.Array.ColorSize) {
  371.                case 3:   glColor3dv( (GLdouble*) p );   break;
  372.                case 4:   glColor4dv( (GLdouble*) p );   break;
  373.             }
  374.             break;
  375.       }
  376.    }
  377.  
  378.    if (CC.Array.IndexEnabled) {
  379.       GLbyte *p = (GLbyte*) CC.Array.IndexPtr + i * CC.Array.IndexStrideB;
  380.       switch (CC.Array.IndexType) {
  381.          case GL_SHORT:
  382.             glIndexsv( (GLshort*) p );
  383.             break;
  384.          case GL_INT:
  385.             glIndexiv( (GLint*) p );
  386.             break;
  387.          case GL_FLOAT:
  388.             glIndexfv( (GLfloat*) p );
  389.             break;
  390.          case GL_DOUBLE_EXT:
  391.             glIndexdv( (GLdouble*) p );
  392.             break;
  393.       }
  394.    }
  395.  
  396.    if (CC.Array.TexCoordEnabled) {
  397.       GLbyte *p = (GLbyte*) CC.Array.TexCoordPtr + i * CC.Array.TexCoordStrideB;
  398.       switch (CC.Array.TexCoordType) {
  399.          case GL_SHORT:
  400.             switch (CC.Array.TexCoordSize) {
  401.                case 1:   glTexCoord1sv( (GLshort*) p );   break;
  402.                case 2:   glTexCoord2sv( (GLshort*) p );   break;
  403.                case 3:   glTexCoord3sv( (GLshort*) p );   break;
  404.                case 4:   glTexCoord4sv( (GLshort*) p );   break;
  405.             }
  406.             break;
  407.          case GL_INT:
  408.             switch (CC.Array.TexCoordSize) {
  409.                case 1:   glTexCoord1iv( (GLint*) p );   break;
  410.                case 2:   glTexCoord2iv( (GLint*) p );   break;
  411.                case 3:   glTexCoord3iv( (GLint*) p );   break;
  412.                case 4:   glTexCoord4iv( (GLint*) p );   break;
  413.             }
  414.             break;
  415.          case GL_FLOAT:
  416.             switch (CC.Array.TexCoordSize) {
  417.                case 1:   glTexCoord1fv( (GLfloat*) p );   break;
  418.                case 2:   glTexCoord2fv( (GLfloat*) p );   break;
  419.                case 3:   glTexCoord3fv( (GLfloat*) p );   break;
  420.                case 4:   glTexCoord4fv( (GLfloat*) p );   break;
  421.             }
  422.             break;
  423.          case GL_DOUBLE_EXT:
  424.             switch (CC.Array.TexCoordSize) {
  425.                case 1:   glTexCoord1dv( (GLdouble*) p );   break;
  426.                case 2:   glTexCoord2dv( (GLdouble*) p );   break;
  427.                case 3:   glTexCoord3dv( (GLdouble*) p );   break;
  428.                case 4:   glTexCoord4dv( (GLdouble*) p );   break;
  429.             }
  430.             break;
  431.       }
  432.    }
  433.  
  434.    if (CC.Array.EdgeFlagEnabled) {
  435.       GLbyte *b = (GLbyte*) CC.Array.EdgeFlagPtr + i * CC.Array.EdgeFlagStrideB;
  436.       glEdgeFlagv( (GLboolean*) b );
  437.    }
  438.  
  439.    if (CC.Array.VertexEnabled) {
  440.       GLbyte *b = (GLbyte*) CC.Array.VertexPtr + i * CC.Array.VertexStrideB;
  441.       switch (CC.Array.VertexType) {
  442.          case GL_SHORT:
  443.             switch (CC.Array.VertexSize) {
  444.                case 2:   glVertex2sv( (GLshort*) b );   break;
  445.                case 3:   glVertex3sv( (GLshort*) b );   break;
  446.                case 4:   glVertex4sv( (GLshort*) b );   break;
  447.             }
  448.             break;
  449.          case GL_INT:
  450.             switch (CC.Array.VertexSize) {
  451.                case 2:   glVertex2iv( (GLint*) b );   break;
  452.                case 3:   glVertex3iv( (GLint*) b );   break;
  453.                case 4:   glVertex4iv( (GLint*) b );   break;
  454.             }
  455.             break;
  456.          case GL_FLOAT:
  457.             switch (CC.Array.VertexSize) {
  458.                case 2:   glVertex2fv( (GLfloat*) b );   break;
  459.                case 3:   glVertex3fv( (GLfloat*) b );   break;
  460.                case 4:   glVertex4fv( (GLfloat*) b );   break;
  461.             }
  462.             break;
  463.          case GL_DOUBLE_EXT:
  464.             switch (CC.Array.VertexSize) {
  465.                case 2:   glVertex2dv( (GLdouble*) b );   break;
  466.                case 3:   glVertex3dv( (GLdouble*) b );   break;
  467.                case 4:   glVertex4dv( (GLdouble*) b );   break;
  468.             }
  469.             break;
  470.       }
  471.    }
  472. }
  473.  
  474.  
  475.  
  476. void glDrawArraysEXT( GLenum mode, GLint first, GLsizei count )
  477. {
  478.    GLint i;
  479.    GLboolean need_edges;
  480.  
  481.    if (INSIDE_BEGIN_END) {
  482.       gl_error( GL_INVALID_OPERATION, "glDrawArraysEXT" );
  483.       return;
  484.    }
  485.    if (count<0) {
  486.       gl_error( GL_INVALID_VALUE, "glDrawArraysEXT(count)" );
  487.       return;
  488.    }
  489.  
  490.    if (CC.Mode==GL_TRIANGLES || CC.Mode==GL_QUADS || CC.Mode==GL_POLYGON) {
  491.       need_edges = GL_TRUE;
  492.    }
  493.    else {
  494.       need_edges = GL_FALSE;
  495.    }
  496.  
  497.    if (!CC.CompileFlag
  498.        && !CC.Light.Enabled
  499.        && !CC.Texture.Enabled
  500.        && CC.Array.VertexEnabled && CC.Array.VertexType==GL_FLOAT
  501.        && CC.Array.VertexStride==0 && CC.Array.VertexSize==3
  502.        && !CC.Array.NormalEnabled
  503.        && !CC.Array.ColorEnabled
  504.        && !CC.Array.IndexEnabled
  505.        && !CC.Array.TexCoordEnabled
  506.        && !CC.Array.EdgeFlagEnabled) {
  507.       /*
  508.        * SPECIAL CASE:  glVertex3fv() with no lighting
  509.        */
  510.       GLfloat (*vptr)[3];
  511.       GLint remaining;
  512.  
  513.       glBegin( mode );
  514.  
  515.       remaining = count;
  516.       vptr = (GLfloat (*)[3]) CC.Array.VertexPtr + 3 * first;
  517.       while (remaining>0) {
  518.          GLint vbspace, n;
  519.  
  520.          vbspace = VB_MAX - VB.Start;
  521.          n = MIN2( vbspace, remaining );
  522.  
  523.          gl_xform_points_3fv( n, VB.Eye+VB.Start, CC.ModelViewMatrix, vptr );
  524.  
  525.          /* assign vertex colors */
  526.          {
  527.             GLint r = CC.Current.IntColor[0] << CC.ColorShift;
  528.             GLint g = CC.Current.IntColor[1] << CC.ColorShift;
  529.             GLint b = CC.Current.IntColor[2] << CC.ColorShift;
  530.             GLint a = CC.Current.IntColor[3] << CC.ColorShift;
  531.             GLint i, start = VB.Start;
  532.             for (i=0;i<n;i++) {
  533.                ASSIGN_4V( VB.Fcolor[start+i], r, g, b, a );
  534.             }
  535.          }
  536.  
  537.          /* assign polygon edgeflags */
  538.          if (need_edges) {
  539.             GLint i;
  540.             for (i=0;i<n;i++) {
  541.                VB.Edgeflag[VB.Start+i] = CC.Current.EdgeFlag;
  542.             }
  543.          }
  544.  
  545.          remaining -= n;
  546.  
  547.          VB.Count = VB.Start + n;
  548.          gl_transform_vb_part2( remaining==0 ? GL_TRUE : GL_FALSE );
  549.  
  550.          vptr += n;
  551.       }
  552.  
  553.       glEnd();
  554.    }
  555.    else if (!CC.CompileFlag
  556.        && CC.Light.Enabled
  557.        && !CC.Texture.Enabled
  558.        && CC.Array.VertexEnabled && CC.Array.VertexType==GL_FLOAT
  559.        && CC.Array.VertexStride==0 && CC.Array.VertexSize==4
  560.        && CC.Array.NormalEnabled && CC.Array.NormalType==GL_FLOAT
  561.        && CC.Array.NormalStride==0
  562.        && !CC.Array.ColorEnabled
  563.        && !CC.Array.IndexEnabled
  564.        && !CC.Array.TexCoordEnabled
  565.        && !CC.Array.EdgeFlagEnabled) {
  566.       /*
  567.        * SPECIAL CASE:  glNormal3fv();  glVertex4fv();  with lighting
  568.        */
  569.       GLfloat (*vptr)[4], (*nptr)[3];
  570.       GLint remaining;
  571.  
  572.       glBegin( mode );
  573.  
  574.       remaining = count;
  575.       vptr = (GLfloat (*)[4]) CC.Array.VertexPtr + 4 * first;
  576.       nptr = (GLfloat (*)[3]) CC.Array.NormalPtr + 3 * first;
  577.       while (remaining>0) {
  578.          GLint vbspace, n;
  579.  
  580.          vbspace = VB_MAX - VB.Start;
  581.          n = MIN2( vbspace, remaining );
  582.  
  583.          gl_xform_points_4fv( n, VB.Eye+VB.Start, CC.ModelViewMatrix, vptr );
  584.          gl_xform_normals_3fv( n, VB.Normal+VB.Start, CC.ModelViewInv, nptr,
  585.                                CC.Transform.Normalize );
  586.  
  587.          /* assign polygon edgeflags */
  588.          if (need_edges) {
  589.             GLint i;
  590.             for (i=0;i<n;i++) {
  591.                VB.Edgeflag[VB.Start+i] = CC.Current.EdgeFlag;
  592.             }
  593.          }
  594.  
  595.          remaining -= n;
  596.  
  597.          VB.Count = VB.Start + n;
  598.          gl_transform_vb_part2( remaining==0 ? GL_TRUE : GL_FALSE );
  599.  
  600.          vptr += n;
  601.          nptr += n;
  602.       }
  603.  
  604.       glEnd();
  605.    }
  606.    else if (!CC.CompileFlag
  607.        && CC.Light.Enabled
  608.        && !CC.Texture.Enabled
  609.        && CC.Array.VertexEnabled && CC.Array.VertexType==GL_FLOAT
  610.        && CC.Array.VertexStride==0 && CC.Array.VertexSize==3
  611.        && CC.Array.NormalEnabled && CC.Array.NormalType==GL_FLOAT
  612.        && CC.Array.NormalStride==0
  613.        && !CC.Array.ColorEnabled
  614.        && !CC.Array.IndexEnabled
  615.        && !CC.Array.TexCoordEnabled
  616.        && !CC.Array.EdgeFlagEnabled) {
  617.       /*
  618.        * SPECIAL CASE:  glNormal3fv();  glVertex3fv();  with lighting
  619.        */
  620.       GLfloat (*vptr)[3], (*nptr)[3];
  621.       GLint remaining;
  622.  
  623.       glBegin( mode );
  624.  
  625.       remaining = count;
  626.       vptr = (GLfloat (*)[3]) CC.Array.VertexPtr + 3 * first;
  627.       nptr = (GLfloat (*)[3]) CC.Array.NormalPtr + 3 * first;
  628.       while (remaining>0) {
  629.          GLint vbspace, n;
  630.  
  631.          vbspace = VB_MAX - VB.Start;
  632.          n = MIN2( vbspace, remaining );
  633.  
  634.          gl_xform_points_3fv( n, VB.Eye+VB.Start, CC.ModelViewMatrix, vptr );
  635.          gl_xform_normals_3fv( n, VB.Normal+VB.Start, CC.ModelViewInv, nptr,
  636.                                CC.Transform.Normalize );
  637.  
  638.          /* assign polygon edgeflags */
  639.          if (need_edges) {
  640.             GLint i;
  641.             for (i=0;i<n;i++) {
  642.                VB.Edgeflag[VB.Start+i] = CC.Current.EdgeFlag;
  643.             }
  644.          }
  645.  
  646.          remaining -= n;
  647.  
  648.          VB.Count = VB.Start + n;
  649.          gl_transform_vb_part2( remaining==0 ? GL_TRUE : GL_FALSE );
  650.  
  651.          vptr += n;
  652.          nptr += n;
  653.       }
  654.  
  655.       glEnd();
  656.    }
  657.    else {
  658.       /*
  659.        * GENERAL CASE:
  660.        */
  661.       glBegin( mode );
  662.       for (i=0;i<count;i++) {
  663.          glArrayElementEXT( first+i );
  664.       }
  665.       glEnd();
  666.    }
  667. }
  668.  
  669.  
  670.