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

  1. /* $Id: draw.c,v 1.65 1996/05/15 18:19:10 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: draw.c,v $
  26.  * Revision 1.65  1996/05/15  18:19:10  brianp
  27.  * always compute plane equation for polygons
  28.  *
  29.  * Revision 1.64  1996/05/01  20:46:01  brianp
  30.  * added GL_MESA_window_pos extension code
  31.  *
  32.  * Revision 1.63  1996/04/25  20:50:28  brianp
  33.  * call DD.begin in gl_begin() and call DD.end in gl_end()
  34.  *
  35.  * Revision 1.62  1996/04/23  22:09:45  brianp
  36.  * new profiling macros
  37.  * combined clip testing with clip-to-window mapping
  38.  * new, specialized vertex functions
  39.  *
  40.  * Revision 1.61  1996/03/15  16:30:53  brianp
  41.  * don't use MAP_[XYZ] macros in gl_rasterpos() because of RasterOffset[XY]
  42.  *
  43.  * Revision 1.60  1996/02/26  15:06:42  brianp
  44.  * replaced CC.Current.Color with CC.Current.IntColor
  45.  *
  46.  * Revision 1.59  1996/02/15  16:53:46  brianp
  47.  * split xform_vb() into transform_vb_part1() and gl_transform_vb_part2()
  48.  *
  49.  * Revision 1.58  1996/02/14  16:56:50  brianp
  50.  * replaced gl_index_shade() with gl_index_shade_vertices()
  51.  *
  52.  * Revision 1.58  1996/02/14  16:56:50  brianp
  53.  * replaced gl_index_shade() with gl_index_shade_vertices()
  54.  *
  55.  * Revision 1.57  1996/02/13  17:47:35  brianp
  56.  * call gl_color_shade_vertices_fast() for optimized lighting
  57.  *
  58.  * Revision 1.56  1996/02/06  04:13:37  brianp
  59.  * use CC.Polygon.CullBits
  60.  *
  61.  * Revision 1.55  1996/02/06  03:23:54  brianp
  62.  * removed gamma correction code
  63.  *
  64.  * Revision 1.54  1996/02/01  00:57:11  brianp
  65.  * rearranged code for polygons lit with two-sided lighting
  66.  *
  67.  * Revision 1.53  1996/01/29  19:10:28  brianp
  68.  * fixed a bug in using multiple clipping planes
  69.  *
  70.  * Revision 1.52  1996/01/29  19:06:16  brianp
  71.  * set CC.Orientation field for unfilled polygons
  72.  *
  73.  * Revision 1.51  1996/01/22  15:36:35  brianp
  74.  * cleaned up gl_begin() and call PB_INIT() instead of gl_init_pb()
  75.  *
  76.  * Revision 1.50  1996/01/17  19:57:38  brianp
  77.  * fixed a bug involving the VB clip flags and long primitive strips
  78.  *
  79.  * Revision 1.49  1996/01/16  15:06:48  brianp
  80.  * check that polygons have at least 3 vertices per Michael Pichler
  81.  *
  82.  * Revision 1.48  1996/01/07  22:50:03  brianp
  83.  * replaced gl_color_shade() calls with gl_color_shade_vertices()
  84.  *
  85.  * Revision 1.47  1996/01/05  01:23:09  brianp
  86.  * added profiling
  87.  *
  88.  * Revision 1.46  1995/12/30  17:15:11  brianp
  89.  * gl_eval_vertex now takes integer colors
  90.  *
  91.  * Revision 1.45  1995/12/30  00:50:19  brianp
  92.  * now use integer VB.color and ColorShift
  93.  *
  94.  * Revision 1.44  1995/12/21  17:39:22  brianp
  95.  * optimized gl_execute_vertex() function
  96.  *
  97.  * Revision 1.43  1995/12/20  17:28:15  brianp
  98.  * removed gl_index and gl_color, now they're inlined
  99.  *
  100.  * Revision 1.42  1995/12/20  15:26:25  brianp
  101.  * changed VB color indexes to GLuint
  102.  *
  103.  * Revision 1.41  1995/12/19  22:16:42  brianp
  104.  * added CC.RasterOffsetX/Y
  105.  *
  106.  * Revision 1.40  1995/11/22  13:36:18  brianp
  107.  * small optimization to VB.Win[][] computation
  108.  *
  109.  * Revision 1.39  1995/11/03  22:35:08  brianp
  110.  * call new vertex fogging functions
  111.  *
  112.  * Revision 1.38  1995/11/03  17:40:52  brianp
  113.  * removed unused variables
  114.  *
  115.  * Revision 1.37  1995/11/01  21:45:26  brianp
  116.  * use new gl_color_shade_vertices() function
  117.  *
  118.  * Revision 1.36  1995/10/27  21:37:44  brianp
  119.  * implemented glPolygonOffsetEXT
  120.  * optimized computation of CC.Plane[ABCD]
  121.  *
  122.  * Revision 1.35  1995/10/19  15:47:00  brianp
  123.  * added gamma support
  124.  *
  125.  * Revision 1.34  1995/10/17  21:42:55  brianp
  126.  * enabled VB.MonoColor logic
  127.  *
  128.  * Revision 1.33  1995/09/28  19:40:02  brianp
  129.  * replaced ClipFlag[] with Unclipped[]
  130.  *
  131.  * Revision 1.32  1995/09/27  18:33:24  brianp
  132.  * added call to new gl_transform_normals function
  133.  *
  134.  * Revision 1.31  1995/09/26  16:04:55  brianp
  135.  * moved transform_points to xform.c
  136.  *
  137.  * Revision 1.30  1995/09/25  19:23:40  brianp
  138.  * implemented per-vertex glMaterial calls
  139.  *
  140.  * Revision 1.29  1995/09/22  22:12:41  brianp
  141.  * optimized the xform_vb function to unroll loops, use maximum registers
  142.  *
  143.  * Revision 1.28  1995/09/22  16:51:16  brianp
  144.  * fixed Anyclipped typo
  145.  *
  146.  * Revision 1.27  1995/09/22  16:49:42  brianp
  147.  * added VB.AnyClipped logic
  148.  * added conditionals to gl_execute_vertex
  149.  * prototyped VB.MonoColor logic
  150.  *
  151.  * Revision 1.26  1995/09/17  19:31:03  brianp
  152.  * better logic for computing plane eq of polygons, accidental culling fixed
  153.  *
  154.  * Revision 1.25  1995/09/15  18:39:43  brianp
  155.  * complete restructuring to "vectorize" the vertex pipeline
  156.  *
  157.  * Revision 1.24  1995/07/28  21:33:21  brianp
  158.  * code cleanup, adapt gl_index_shade calls for GLfloat result
  159.  *
  160.  * Revision 1.23  1995/06/20  16:29:36  brianp
  161.  * don't scale Z to integer values here
  162.  * introduced new triangle, polygon area code but not used yet
  163.  *
  164.  * Revision 1.22  1995/06/02  18:59:31  brianp
  165.  * added special case for computing plane equation of 3-sided polygon
  166.  *
  167.  * Revision 1.21  1995/06/02  13:55:09  brianp
  168.  * implemented vertex/primitive buffering
  169.  *
  170.  * Revision 1.20  1995/05/26  19:32:02  brianp
  171.  * replace many assignments in gl_color() with macros
  172.  *
  173.  * Revision 1.19  1995/05/22  21:02:41  brianp
  174.  * Release 1.2
  175.  *
  176.  * Revision 1.18  1995/05/22  21:00:36  brianp
  177.  * tried initial vertex buffering
  178.  *
  179.  * Revision 1.17  1995/05/17  13:17:22  brianp
  180.  * changed default CC.Mode value to allow use of real OpenGL headers
  181.  * removed need for CC.MajorMode variable
  182.  *
  183.  * Revision 1.16  1995/05/15  16:07:33  brianp
  184.  * moved StippleCounter init to new place
  185.  *
  186.  * Revision 1.15  1995/05/12  16:29:18  brianp
  187.  * added #define for NULL
  188.  *
  189.  * Revision 1.14  1995/03/27  20:31:26  brianp
  190.  * new Texture.Enabled scheme
  191.  *
  192.  * Revision 1.13  1995/03/24  15:31:23  brianp
  193.  * introduced VB
  194.  *
  195.  * Revision 1.12  1995/03/23  17:10:12  brianp
  196.  * changed render_point() to render_points(n)
  197.  *
  198.  * Revision 1.11  1995/03/09  21:42:09  brianp
  199.  * new ModelViewInv matrix logic
  200.  *
  201.  * Revision 1.10  1995/03/09  20:08:04  brianp
  202.  * introduced TRANSFORM_POINT and TRANSFORM_NORMAL macros
  203.  *
  204.  * Revision 1.9  1995/03/04  19:29:44  brianp
  205.  * 1.1 beta revision
  206.  *
  207.  * Revision 1.8  1995/03/02  19:10:00  brianp
  208.  * fixed a texgen bug
  209.  *
  210.  * Revision 1.7  1995/02/27  22:48:48  brianp
  211.  * modified for PB
  212.  *
  213.  * Revision 1.6  1995/02/27  15:08:04  brianp
  214.  * added Vcolor/Vindex scheme
  215.  *
  216.  * Revision 1.5  1995/02/26  22:58:43  brianp
  217.  * more zero-area polygon work
  218.  *
  219.  * Revision 1.4  1995/02/26  21:59:43  brianp
  220.  * *** empty log message ***
  221.  *
  222.  * Revision 1.3  1995/02/25  22:07:56  brianp
  223.  * relaxed test for zero-area polygons, still not perfect though
  224.  *
  225.  * Revision 1.2  1995/02/24  15:23:36  brianp
  226.  * removed initialization of d from render_point()
  227.  * added RasterColor code to gl_rasterpos()
  228.  *
  229.  * Revision 1.1  1995/02/24  14:20:43  brianp
  230.  * Initial revision
  231.  *
  232.  */
  233.  
  234.  
  235. /*
  236.  * Draw points, lines, and polygons.
  237.  */
  238.  
  239.  
  240. #ifdef DEBUG
  241. #  include <assert.h>
  242. #endif
  243. #include <math.h>
  244. #include <stdio.h>
  245. #include <stdlib.h>
  246. #include <string.h>
  247. #include "clip.h"
  248. #include "context.h"
  249. #include "dd.h"
  250. #include "draw.h"
  251. #include "feedback.h"
  252. #include "fog.h"
  253. #include "light.h"
  254. #include "lines.h"
  255. #include "list.h"
  256. #include "macros.h"
  257. #include "pb.h"
  258. #include "points.h"
  259. #include "polygons.h"
  260. #include "texture.h"
  261. #include "vb.h"
  262. #include "xform.h"
  263.  
  264. /*#include "triangle.h"*/
  265.  
  266.  
  267.  
  268. #ifndef NULL
  269. #  define NULL 0
  270. #endif
  271.  
  272.  
  273. #ifdef DEBUG
  274. #  define ASSERT(X)   assert(X)
  275. #else
  276. #  define ASSERT(X)
  277. #endif
  278.  
  279.  
  280.  
  281. #ifdef PROFILE
  282. #  define START_PROFILE                \
  283.     {                    \
  284.        GLdouble t0 = gl_time();
  285.  
  286. #  define END_PROFILE( TIMER, COUNTER, INCR )    \
  287.        TIMER += (gl_time() - t0);        \
  288.        COUNTER += INCR;            \
  289.     }
  290. #else
  291. #  define START_PROFILE
  292. #  define END_PROFILE( TIMER, COUNTER, INCR )
  293. #endif
  294.  
  295.  
  296.  
  297. /*
  298.  * Check if the global material has to be updated with info that was
  299.  * associated with a vertex via glMaterial.
  300.  */
  301. static void update_material( GLuint i )
  302. {
  303.    if (VB.MaterialMask[i]) {
  304.       if (VB.MaterialMask[i] & FRONT_AMBIENT_BIT) {
  305.          COPY_4V( CC.Light.Material[0].Ambient, VB.Material[i][0].Ambient );
  306.       }
  307.       if (VB.MaterialMask[i] & BACK_AMBIENT_BIT) {
  308.          COPY_4V( CC.Light.Material[1].Ambient, VB.Material[i][1].Ambient );
  309.       }
  310.       if (VB.MaterialMask[i] & FRONT_DIFFUSE_BIT) {
  311.          COPY_4V( CC.Light.Material[0].Diffuse, VB.Material[i][0].Diffuse );
  312.       }
  313.       if (VB.MaterialMask[i] & BACK_DIFFUSE_BIT) {
  314.          COPY_4V( CC.Light.Material[1].Diffuse, VB.Material[i][1].Diffuse );
  315.       }
  316.       if (VB.MaterialMask[i] & FRONT_SPECULAR_BIT) {
  317.          COPY_4V( CC.Light.Material[0].Specular, VB.Material[i][0].Specular );
  318.       }
  319.       if (VB.MaterialMask[i] & BACK_SPECULAR_BIT) {
  320.          COPY_4V( CC.Light.Material[1].Specular, VB.Material[i][1].Specular );
  321.       }
  322.       if (VB.MaterialMask[i] & FRONT_EMISSION_BIT) {
  323.          COPY_4V( CC.Light.Material[0].Emission, VB.Material[i][0].Emission );
  324.       }
  325.       if (VB.MaterialMask[i] & BACK_EMISSION_BIT) {
  326.          COPY_4V( CC.Light.Material[1].Emission, VB.Material[i][1].Emission );
  327.       }
  328.       if (VB.MaterialMask[i] & FRONT_SHININESS_BIT) {
  329.          CC.Light.Material[0].Shininess = VB.Material[i][0].Shininess;
  330.       }
  331.       if (VB.MaterialMask[i] & BACK_SHININESS_BIT) {
  332.          CC.Light.Material[1].Shininess = VB.Material[i][1].Shininess;
  333.       }
  334.       if (VB.MaterialMask[i] & FRONT_INDEXES_BIT) {
  335.          CC.Light.Material[0].AmbientIndex = VB.Material[i][0].AmbientIndex;
  336.          CC.Light.Material[0].DiffuseIndex = VB.Material[i][0].DiffuseIndex;
  337.          CC.Light.Material[0].SpecularIndex = VB.Material[i][0].SpecularIndex;
  338.       }
  339.       if (VB.MaterialMask[i] & BACK_INDEXES_BIT) {
  340.          CC.Light.Material[1].AmbientIndex = VB.Material[i][1].AmbientIndex;
  341.          CC.Light.Material[1].DiffuseIndex = VB.Material[i][1].DiffuseIndex;
  342.          CC.Light.Material[1].SpecularIndex = VB.Material[i][1].SpecularIndex;
  343.       }
  344.       VB.MaterialMask[i] = 0;  /* reset now */
  345.    }
  346. }
  347.  
  348.  
  349.  
  350. /*
  351.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  352.  * endpoints must be clipped.
  353.  */
  354. static void render_clipped_line( GLuint v1, GLuint v2 )
  355. {
  356.    GLfloat d;
  357.    GLfloat ndc_x, ndc_y, ndc_z;
  358.    GLuint provoking_vertex;
  359.  
  360.    /* which vertex dictates the color when flat shading: */
  361.    provoking_vertex = v2;
  362.  
  363.    /*
  364.     * Clipping may introduce new vertices.  New vertices will be stored
  365.     * in the vertex buffer arrays starting with location VB.Free.  After
  366.     * we've rendered the line, these extra vertices can be overwritten.
  367.     */
  368.    VB.Free = VB_MAX;
  369.  
  370.    /* Clip against user clipping planes */
  371.    if (CC.Transform.AnyClip) {
  372.       if (gl_userclip_line( &v1, &v2 )==0)
  373.     return;
  374.    }
  375.  
  376.    /* Apply projection matrix:  clip = Proj * eye */
  377.    TRANSFORM_POINT( VB.Clip[v1], CC.ProjectionMatrix, VB.Eye[v1] );
  378.    TRANSFORM_POINT( VB.Clip[v2], CC.ProjectionMatrix, VB.Eye[v2] );
  379.  
  380.    /* Clip against view volume */
  381.    if (gl_viewclip_line( &v1, &v2 )==0)
  382.       return;
  383.  
  384.    /* Transform from clip coords to ndc:  ndc = clip / W */
  385.    ASSERT( VB.Clip[v1][3] != 0.0 );
  386.    ASSERT( VB.Clip[v2][3] != 0.0 );
  387.    d = 1.0F / VB.Clip[v1][3];
  388.    ndc_x = VB.Clip[v1][0] * d;
  389.    ndc_y = VB.Clip[v1][1] * d;
  390.    ndc_z = VB.Clip[v1][2] * d;
  391.  
  392.    /* Map ndc coord to window coords. */
  393.    VB.Win[v1][0] = MAP_X( ndc_x );
  394.    VB.Win[v1][1] = MAP_Y( ndc_y );
  395.    VB.Win[v1][2] = MAP_Z( ndc_z );
  396.  
  397.    /* Transform from clip coords to ndc:  ndc = clip / W */
  398.    d = 1.0F / VB.Clip[v2][3];
  399.    ndc_x = VB.Clip[v2][0] * d;
  400.    ndc_y = VB.Clip[v2][1] * d;
  401.    ndc_z = VB.Clip[v2][2] * d;
  402.  
  403.    /* Map ndc coord to window coords. */
  404.    VB.Win[v2][0] = MAP_X( ndc_x );
  405.    VB.Win[v2][1] = MAP_Y( ndc_y );
  406.    VB.Win[v2][2] = MAP_Z( ndc_z );
  407.  
  408.    START_PROFILE
  409.    (*CC.LineFunc)( v1, v2, provoking_vertex );
  410.    END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  411. }
  412.  
  413.  
  414.  
  415. #ifdef LEAVEOUT
  416. /*
  417.  * Apply the glPolygonOffsetEXT transformation to the current plane
  418.  * equation.  Basically, we just have to add an offset to the D term.
  419.  */
  420. static void offset_polygon( void )
  421. {
  422.    GLfloat ac, bc, m, offset;
  423.    ac = CC.PlaneA / CC.PlaneC;
  424.    bc = CC.PlaneB / CC.PlaneC;
  425.    if (ac<0.0F)  ac = -ac;
  426.    if (bc<0.0F)  bc = -bc;
  427.    m = MAX2( ac, bc );
  428. /*
  429.    m = sqrt( ac*ac + bc*bc );
  430. */
  431.    offset = m * CC.Polygon.OffsetFactor + CC.Polygon.OffsetBias;
  432.    CC.PlaneD = CC.PlaneD + CC.PlaneC * offset;
  433. }
  434. #endif
  435.  
  436.  
  437. #define OFFSET_POLYGON( A, B, C, D )                    \
  438.     {                                \
  439.        GLfloat m, ac = (A)/(C), bc = (B)/(C);            \
  440.        if (ac<0.0F)  ac = -ac;                    \
  441.        if (bc<0.0F)  bc = -bc;                    \
  442.        m = MAX2( ac, bc );                        \
  443.        D += (C) * (m * CC.Polygon.OffsetFactor + CC.Polygon.OffsetBias); \
  444.     }
  445.  
  446.  
  447.  
  448.  
  449. /*
  450.  * Render a polygon in which at least one vertex has to be clipped.
  451.  * Input:  n - number of vertices
  452.  *         vlist - list of vertices in the polygon.
  453.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  454.  */
  455. static void render_clipped_polygon( GLuint n, GLuint vlist[], GLuint odd_flag )
  456. {
  457.    GLuint i, j;
  458.    GLuint provoking_vertex;
  459.  
  460.    /* which vertex dictates the color when flat shading: */
  461.    provoking_vertex = (CC.Mode==GL_POLYGON) ? vlist[0] : vlist[n-1];
  462.  
  463.    /*
  464.     * Clipping may introduce new vertices.  New vertices will be stored
  465.     * in the vertex buffer arrays starting with location VB.Free.  After
  466.     * we've rendered the polygon, these extra vertices can be overwritten.
  467.     */
  468.    VB.Free = VB_MAX;
  469.  
  470.    /* Clip against user clipping planes in eye coord space. */
  471.    if (CC.Transform.AnyClip) {
  472.       n = gl_userclip_polygon( n, vlist );
  473.       if (n<3)
  474.          return;
  475.    }
  476.  
  477.    /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  478.    for (i=0;i<n;i++) {
  479.       j = vlist[i];
  480.       TRANSFORM_POINT( VB.Clip[j], CC.ProjectionMatrix, VB.Eye[j] );
  481.    }
  482.  
  483.    /* Clip against view volume in clip coord space */
  484.    n = gl_viewclip_polygon( n, vlist );
  485.    if (n<3)
  486.       return;
  487.  
  488.    /* Transform vertices from clip to ndc:  ndc = clip / W */
  489.    for (i=0;i<n;i++) {
  490.       GLfloat d, ndc_x, ndc_y, ndc_z;
  491.       j = vlist[i];
  492.       ASSERT( VB.Clip[j][3] != 0.0 );
  493.       d = 1.0F / VB.Clip[j][3];
  494.       ndc_x = VB.Clip[j][0] * d;
  495.       ndc_y = VB.Clip[j][1] * d;
  496.       ndc_z = VB.Clip[j][2] * d;
  497.  
  498.       /* Transform ndc coord to a window coord.  Note that window Z values */
  499.       /* are scaled to integer Z buffer values. */
  500.       VB.Win[j][0] = MAP_X( ndc_x );
  501.       VB.Win[j][1] = MAP_Y( ndc_y );
  502.       VB.Win[j][2] = MAP_Z( ndc_z );
  503.  
  504. #ifdef NEW
  505.       VB.WinX[j] = (GLint) (MAP_X( ndc_x ) * SUB_PIX_SCALE);
  506.       VB.WinY[j] = (GLint) (MAP_Y( ndc_y ) * SUB_PIX_SCALE);
  507.       VB.WinZ[j] = (GLint) (MAP_Z( ndc_z ) * DEPTH_SCALE);
  508. #endif
  509.    }
  510.  
  511.    /* Compute the plane equation of polygon: ax + by + cz = d */
  512.    {
  513.       GLuint j0 = vlist[0];
  514.       GLuint j1 = vlist[1];
  515.       GLuint j2 = vlist[2];
  516.       GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  517.       GLfloat ex = VB.Win[j1][0] - VB.Win[j3][0];
  518.       GLfloat ey = VB.Win[j1][1] - VB.Win[j3][1];
  519.       GLfloat fx = VB.Win[j2][0] - VB.Win[j0][0];
  520.       GLfloat fy = VB.Win[j2][1] - VB.Win[j0][1];
  521.       GLfloat c = ex*fy-ey*fx;
  522.  
  523.       if (c==0.0F) {
  524.          /* polygon is perpindicular to view plane, don't draw it */
  525.          return;
  526.       }
  527.       else {
  528.          /* compute orientation:  0=front, 1=back */
  529.          GLuint facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  530.  
  531.          if ((facing+1) & CC.Polygon.CullBits) {
  532.             return;   /* culled */
  533.          }
  534.          else {
  535.             GLfloat ez = VB.Win[j1][2] - VB.Win[j3][2];
  536.             GLfloat fz = VB.Win[j2][2] - VB.Win[j0][2];
  537.             GLfloat a = ey*fz-ez*fy;
  538.             GLfloat b = ez*fx-ex*fz;
  539.             GLfloat d = a*VB.Win[j0][0] + b*VB.Win[j0][1] + c*VB.Win[j0][2];
  540.  
  541.             if (CC.Polygon.OffsetEnabled) {
  542.                OFFSET_POLYGON( a, b, c, d );
  543.             }
  544.  
  545.             CC.PlaneA = a;
  546.             CC.PlaneB = b;
  547.             CC.PlaneC = c;
  548.             CC.PlaneD = d;
  549.             CC.Orientation = facing;
  550.  
  551.             if (CC.Light.Model.TwoSide) {
  552.                if (facing==1 && CC.Light.Enabled) {
  553.                   /* use back color or index */
  554.                   VB.Color = VB.Bcolor;
  555.                   VB.Index = VB.Bindex;
  556.                }
  557.                else {
  558.                   /* use front color or index */
  559.                   VB.Color = VB.Fcolor;
  560.                   VB.Index = VB.Findex;
  561.                }
  562.             }
  563.  
  564.             /* Render the polygon! */
  565.             START_PROFILE
  566.             (*CC.PolygonFunc)( n, vlist, provoking_vertex );
  567.             END_PROFILE( CC.PolygonTime, CC.PolygonCount, 1 )
  568.          }
  569.       }
  570.    }
  571. }
  572.  
  573.  
  574.  
  575. /*
  576.  * Render a polygon in which doesn't have to be clipped.
  577.  * Input:  n - number of vertices
  578.  *         vlist - list of vertices in the polygon.
  579.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  580.  */
  581. static void render_polygon( GLuint n, GLuint vlist[], GLuint odd_flag )
  582. {
  583.    GLuint provoking_vertex;
  584.    GLuint facing;
  585.  
  586.    /* which vertex dictates the color when flat shading: */
  587.    provoking_vertex = (CC.Mode==GL_POLYGON) ? vlist[0] : vlist[n-1];
  588.  
  589.    /* Compute the plane equation of polygon: ax + by + cz = d */
  590.    {
  591.       GLuint j0 = vlist[0];
  592.       GLuint j1 = vlist[1];
  593.       GLuint j2 = vlist[2];
  594.       GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  595.       GLfloat ex = VB.Win[j1][0] - VB.Win[j3][0];
  596.       GLfloat ey = VB.Win[j1][1] - VB.Win[j3][1];
  597.       GLfloat fx = VB.Win[j2][0] - VB.Win[j0][0];
  598.       GLfloat fy = VB.Win[j2][1] - VB.Win[j0][1];
  599.       GLfloat c = ex*fy-ey*fx;
  600.  
  601.       if (c==0.0F) {
  602.          /* polygon is perpindicular to view plane, don't draw it */
  603.          return;
  604.       }
  605.       else {
  606.          /* compute orientation:  0=front, 1=back */
  607.          GLuint facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  608.  
  609.          if ((facing+1) & CC.Polygon.CullBits) {
  610.             return;   /* culled */
  611.          }
  612.          else {
  613.             GLfloat ez = VB.Win[j1][2] - VB.Win[j3][2];
  614.             GLfloat fz = VB.Win[j2][2] - VB.Win[j0][2];
  615.             GLfloat a = ey*fz-ez*fy;
  616.             GLfloat b = ez*fx-ex*fz;
  617.             GLfloat d = a*VB.Win[j0][0] + b*VB.Win[j0][1] + c*VB.Win[j0][2];
  618.  
  619.             if (CC.Polygon.OffsetEnabled) {
  620.                OFFSET_POLYGON( a, b, c, d );
  621.             }
  622.  
  623.             CC.PlaneA = a;
  624.             CC.PlaneB = b;
  625.             CC.PlaneC = c;
  626.             CC.PlaneD = d;
  627.             CC.Orientation = facing;
  628.  
  629.             if (CC.Light.Model.TwoSide) {
  630.                if (facing==1 && CC.Light.Enabled) {
  631.                   /* use back color or index */
  632.                   VB.Color = VB.Bcolor;
  633.                   VB.Index = VB.Bindex;
  634.                }
  635.                else {
  636.                   /* use front color or index */
  637.                   VB.Color = VB.Fcolor;
  638.                   VB.Index = VB.Findex;
  639.                }
  640.             }
  641.  
  642.             /* Render the polygon! */
  643.             START_PROFILE
  644.             (*CC.PolygonFunc)( n, vlist, provoking_vertex );
  645.             END_PROFILE( CC.PolygonTime, CC.PolygonCount, 1 )
  646.          }
  647.       }
  648.    }
  649. }
  650.  
  651.  
  652.  
  653.  
  654. /*
  655.  * Render an un-clipped triangle.
  656.  */
  657. static void render_triangle( GLuint v0, GLuint v1, GLuint v2, GLuint pv,
  658.                              GLuint odd_flag )
  659. {
  660.    /* Compute the plane equation of polygon: ax + by + cz = d */
  661.    GLfloat ex = VB.Win[v1][0] - VB.Win[v0][0];
  662.    GLfloat ey = VB.Win[v1][1] - VB.Win[v0][1];
  663.    GLfloat fx = VB.Win[v2][0] - VB.Win[v0][0];
  664.    GLfloat fy = VB.Win[v2][1] - VB.Win[v0][1];
  665.    GLfloat c = ex*fy-ey*fx;
  666.  
  667.    if (c==0.0F) {
  668.       /* polygon is perpindicular to view plane, don't draw it */
  669.       return;
  670.    }
  671.    else {
  672.       /* compute orientation:  0=front, 1=back */
  673.       GLuint facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  674.  
  675.       if ((facing+1) & CC.Polygon.CullBits) {
  676.      return;   /* culled */
  677.       }
  678.       else {
  679.          GLfloat fz = VB.Win[v2][2] - VB.Win[v0][2];
  680.          GLfloat ez = VB.Win[v1][2] - VB.Win[v0][2];
  681.          GLfloat a = ey*fz-ez*fy;
  682.          GLfloat b = ez*fx-ex*fz;
  683.          GLfloat d = a*VB.Win[v0][0] + b*VB.Win[v0][1] + c*VB.Win[v0][2];
  684.  
  685.          if (CC.Polygon.OffsetEnabled) {
  686.             OFFSET_POLYGON( a, b, c, d );
  687.          }
  688.  
  689.          CC.PlaneA = a;
  690.          CC.PlaneB = b;
  691.          CC.PlaneC = c;
  692.          CC.PlaneD = d;
  693.          CC.Orientation = facing;
  694.  
  695.          if (CC.Light.Model.TwoSide) {
  696.             if (facing==1 && CC.Light.Enabled) {
  697.                /* use back color or index */
  698.                VB.Color = VB.Bcolor;
  699.                VB.Index = VB.Bindex;
  700.             }
  701.             else {
  702.                /* use front color or index */
  703.                VB.Color = VB.Fcolor;
  704.                VB.Index = VB.Findex;
  705.             }
  706.          }
  707.  
  708.          /* Render the triangle! */
  709.          {
  710.             GLuint vlist[3];
  711.             vlist[0] = v0;
  712.             vlist[1] = v1;
  713.             vlist[2] = v2;
  714.             START_PROFILE
  715.             (*CC.PolygonFunc)( 3, vlist, pv );
  716.             END_PROFILE( CC.PolygonTime, CC.PolygonCount, 1 )
  717.          }
  718.       }
  719.    }
  720. }
  721.  
  722.  
  723.  
  724. /*
  725.  * Render an un-clipped quadrilateral.
  726.  */
  727. static void render_quad( GLuint v0, GLuint v1, GLuint v2, GLuint v3,
  728.                          GLuint pv, GLuint odd_flag )
  729. {
  730.    /* Compute the plane equation of polygon: ax + by + cz = d */
  731.    GLfloat ex = VB.Win[v2][0] - VB.Win[v0][0];
  732.    GLfloat ey = VB.Win[v2][1] - VB.Win[v0][1];
  733.    GLfloat fx = VB.Win[v3][0] - VB.Win[v1][0];
  734.    GLfloat fy = VB.Win[v3][1] - VB.Win[v1][1];
  735.    GLfloat c = ex*fy-ey*fx;
  736.  
  737.    if (c==0.0F) {
  738.       /* polygon is perpindicular to view plane, don't draw it */
  739.       return;
  740.    }
  741.    else {
  742.       /* compute orientation:  0=front, 1=back */
  743.       GLuint facing = (c<0.0F) ^ odd_flag ^ (CC.Polygon.FrontFace==GL_CW);
  744.  
  745.       if ((facing+1) & CC.Polygon.CullBits) {
  746.      return;   /* culled */
  747.       }
  748.       else {
  749.          GLfloat ez = VB.Win[v2][2] - VB.Win[v0][2];
  750.          GLfloat fz = VB.Win[v3][2] - VB.Win[v1][2];
  751.          GLfloat a = ey*fz-ez*fy;
  752.          GLfloat b = ez*fx-ex*fz;
  753.          GLfloat d = a*VB.Win[v0][0] + b*VB.Win[v0][1] + c*VB.Win[v0][2];
  754.  
  755.          if (CC.Polygon.OffsetEnabled) {
  756.             OFFSET_POLYGON( a, b, c, d );
  757.          }
  758.  
  759.          CC.PlaneA = a;
  760.          CC.PlaneB = b;
  761.          CC.PlaneC = c;
  762.          CC.PlaneD = d;
  763.          CC.Orientation = facing;
  764.  
  765.          if (CC.Light.Model.TwoSide) {
  766.             if (facing==1 && CC.Light.Enabled) {
  767.                /* use back color or index */
  768.                VB.Color = VB.Bcolor;
  769.                VB.Index = VB.Bindex;
  770.             }
  771.             else {
  772.                /* use front color or index */
  773.                VB.Color = VB.Fcolor;
  774.                VB.Index = VB.Findex;
  775.             }
  776.          }
  777.  
  778.          /* Render the quad! */
  779.          {
  780.             GLuint vlist[4];
  781.             vlist[0] = v0;
  782.             vlist[1] = v1;
  783.             vlist[2] = v2;
  784.             vlist[3] = v3;
  785.             START_PROFILE
  786.             (*CC.PolygonFunc)( 4, vlist, pv );
  787.             END_PROFILE( CC.PolygonTime, CC.PolygonCount, 1 )
  788.          }
  789.       }
  790.    }
  791. }
  792.  
  793.  
  794.  
  795. /*
  796.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  797.  * have to copy the last vertex (or two) to the front of the vertex list
  798.  * to "continue" the primitive.  For example:  line or triangle strips.
  799.  * This function is a helper for that.
  800.  */
  801. static void copy_vertex( GLuint dst, GLuint src )
  802. {
  803.    COPY_3V( VB.Win[dst], VB.Win[src] );
  804.    COPY_4V( VB.Eye[dst], VB.Eye[src] );
  805.    COPY_4V( VB.Fcolor[dst], VB.Fcolor[src] );
  806.    COPY_4V( VB.Bcolor[dst], VB.Bcolor[src] );
  807.    VB.Findex[dst] = VB.Findex[src];
  808.    VB.Bindex[dst] = VB.Bindex[src];
  809.    VB.Edgeflag[dst] = VB.Edgeflag[src];
  810.    COPY_4V( VB.TexCoord[dst], VB.TexCoord[src] );
  811.    VB.Unclipped[dst] = VB.Unclipped[src];
  812. }
  813.  
  814.  
  815.  
  816.  
  817. /*
  818.  * Either the vertex buffer is full (VB.Count==VB_MAX) or glEnd() has been
  819.  * called.  Render the primitives defined by the vertices and reset the
  820.  * buffer.
  821.  * Input:  alldone - GL_TRUE = caller is glEnd()
  822.  *                   GL_FALSE = calling because buffer is full.
  823.  */
  824. static void render_vb( GLboolean alldone )
  825. {
  826.    GLuint vlist[VB_MAX];
  827.  
  828.    switch (CC.Mode) {
  829.       case GL_POINTS:
  830.          START_PROFILE
  831.          (*CC.PointsFunc)( 0, VB.Count-1 );
  832.          END_PROFILE( CC.PointTime, CC.PointCount, VB.Count )
  833.      VB.Count = 0;
  834.          VB.AnyClipped = GL_FALSE;
  835.      break;
  836.  
  837.       case GL_LINES:
  838.          if (VB.AnyClipped) {
  839.             GLuint i;
  840.             for (i=1;i<VB.Count;i+=2) {
  841.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  842.                   START_PROFILE
  843.                   (*CC.LineFunc)( i-1, i, i );
  844.                   END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  845.                }
  846.                else {
  847.                   render_clipped_line( i-1, i );
  848.                }
  849.                CC.StippleCounter = 0;
  850.             }
  851.          }
  852.          else {
  853.             GLuint i;
  854.             for (i=1;i<VB.Count;i+=2) {
  855.                START_PROFILE
  856.                (*CC.LineFunc)( i-1, i, i );
  857.                END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  858.                CC.StippleCounter = 0;
  859.             }
  860.          }
  861.      VB.Count = 0;
  862.          VB.AnyClipped = GL_FALSE;
  863.      break;
  864.  
  865.       case GL_LINE_STRIP:
  866.          if (VB.AnyClipped) {
  867.             GLuint i;
  868.         for (i=1;i<VB.Count;i++) {
  869.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  870.                   START_PROFILE
  871.                   (*CC.LineFunc)( i-1, i, i );
  872.                   END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  873.                }
  874.                else {
  875.                   render_clipped_line( i-1, i );
  876.                }
  877.         }
  878.          }
  879.          else {
  880.             /* no clipping needed */
  881.             GLuint i;
  882.         for (i=1;i<VB.Count;i++) {
  883.                START_PROFILE
  884.                (*CC.LineFunc)( i-1, i, i );
  885.                END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  886.             }
  887.          }
  888.          if (!alldone) {
  889.             copy_vertex( 0, VB.Count-1 );  /* copy last vertex to front */
  890.             VB.Count = 1;
  891.             VB.AnyClipped = VB.Unclipped[0] ? GL_FALSE : GL_TRUE;
  892.      }
  893.          break;
  894.  
  895.       case GL_LINE_LOOP:
  896.          {
  897.             GLuint i;
  898.             if (VB.Start==0) {
  899.                i = 1;  /* start at 0th vertex */
  900.             }
  901.             else {
  902.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  903.             }
  904.             while (i<VB.Count) {
  905.                if (VB.Unclipped[i-1] & VB.Unclipped[i]) {
  906.                   START_PROFILE
  907.                   (*CC.LineFunc)( i-1, i, i );
  908.                   END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  909.                }
  910.                else {
  911.                   render_clipped_line( i-1, i );
  912.                }
  913.                i++;
  914.             }
  915.          }
  916.      if (alldone) {
  917.             if (VB.Unclipped[VB.Count-1] & VB.Unclipped[0]) {
  918.                START_PROFILE
  919.                (*CC.LineFunc)( VB.Count-1, 0, 0 );
  920.                END_PROFILE( CC.LineTime, CC.LineCount, 1 )
  921.             }
  922.             else {
  923.                render_clipped_line( VB.Count-1, 0 );
  924.             }
  925.      }
  926.      else {
  927.         ASSERT(VB.Count==VB_MAX);
  928.         /* recycle the vertex list */
  929.             copy_vertex( 1, VB_MAX-1 );
  930.         VB.Count = 2;
  931.             VB.AnyClipped = !VB.Unclipped[0] || !VB.Unclipped[1];
  932.      }
  933.          break;
  934.  
  935.       case GL_TRIANGLES:
  936.          if (VB.AnyClipped) {
  937.             GLuint i;
  938.             for (i=2;i<VB.Count;i+=3) {
  939.                if (VB.Unclipped[i-2] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  940.                   render_triangle( i-2, i-1, i, i, 0 );
  941.                }
  942.                else {
  943.                   vlist[0] = i-2;
  944.                   vlist[1] = i-1;
  945.                   vlist[2] = i-0;
  946.                   render_clipped_polygon( 3, vlist, 0 );
  947.                }
  948.             }
  949.          }
  950.          else {
  951.             /* no clipping needed */
  952.             GLuint i;
  953.             for (i=2;i<VB.Count;i+=3) {
  954.                render_triangle( i-2, i-1, i, i, 0 );
  955.             }
  956.          }
  957.      VB.Count = 0;
  958.          VB.AnyClipped = GL_FALSE;
  959.      break;
  960.  
  961.       case GL_TRIANGLE_STRIP:
  962.          if (VB.AnyClipped) {
  963.             GLuint i;
  964.             for (i=2;i<VB.Count;i++) {
  965.                if (VB.Unclipped[i-2] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  966.                   render_triangle( i-2, i-1, i, i, i&1 );
  967.                }
  968.                else {
  969.                   vlist[0] = i-2;
  970.                   vlist[1] = i-1;
  971.                   vlist[2] = i-0;
  972.                   render_clipped_polygon( 3, vlist, i&1 );
  973.                }
  974.             }
  975.          }
  976.          else {
  977.             /* no vertices were clipped */
  978.             GLuint i;
  979.             for (i=2;i<VB.Count;i++) {
  980.                /*(*CC.TriangleFunc)( i-2, i-1, i, i );*/
  981.                render_triangle( i-2, i-1, i, i, i&1 );
  982.             }
  983.          }
  984.          if (!alldone) {
  985.             /* get ready for more vertices in this triangle strip */
  986.             copy_vertex( 0, VB_MAX-2 );
  987.             copy_vertex( 1, VB_MAX-1 );
  988.             VB.Count = 2;
  989.             VB.AnyClipped = !VB.Unclipped[0] || !VB.Unclipped[1];
  990.          }
  991.      break;
  992.  
  993.       case GL_TRIANGLE_FAN:
  994.          if (VB.AnyClipped) {
  995.             GLuint i;
  996.             for (i=2;i<VB.Count;i++) {
  997.                if (VB.Unclipped[0] & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  998.                   render_triangle( 0, i-1, i, i, 0 );
  999.                }
  1000.                else {
  1001.                   vlist[0] = 0;
  1002.                   vlist[1] = i-1;
  1003.                   vlist[2] = i;
  1004.                   render_clipped_polygon( 3, vlist, 0 );
  1005.                }
  1006.             }
  1007.          }
  1008.          else {
  1009.             /* no clipping needed */
  1010.             GLuint i;
  1011.             for (i=2;i<VB.Count;i++) {
  1012.                render_triangle( 0, i-1, i, i, 0 );
  1013.             }
  1014.          }
  1015.          if (!alldone) {
  1016.             /* get ready for more vertices in this triangle fan */
  1017.             copy_vertex( 1, VB_MAX-1 );
  1018.             VB.Count = 2;
  1019.             VB.AnyClipped = !VB.Unclipped[0] || !VB.Unclipped[1];
  1020.      }
  1021.      break;
  1022.  
  1023.       case GL_QUADS:
  1024.          if (VB.AnyClipped) {
  1025.             GLuint i;
  1026.             for (i=3;i<VB.Count;i+=4) {
  1027.                if (  VB.Unclipped[i-3] & VB.Unclipped[i-2]
  1028.                    & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  1029.                   render_quad( i-3, i-2, i-1, i, i, 0 );
  1030.                }
  1031.                else {
  1032.                   vlist[0] = i-3;
  1033.                   vlist[1] = i-2;
  1034.                   vlist[2] = i-1;
  1035.                   vlist[3] = i-0;
  1036.                   render_clipped_polygon( 4, vlist, 0 );
  1037.                }
  1038.             }
  1039.          }
  1040.          else {
  1041.             /* no vertices were clipped */
  1042.             GLuint i;
  1043.             for (i=3;i<VB.Count;i+=4) {
  1044.                render_quad( i-3, i-2, i-1, i, i, 0 );
  1045.             }
  1046.          }
  1047.      VB.Count = 0;
  1048.          VB.AnyClipped = GL_FALSE;
  1049.      break;
  1050.  
  1051.       case GL_QUAD_STRIP:
  1052.          if (VB.AnyClipped) {
  1053.             GLuint i;
  1054.             for (i=3;i<VB.Count;i+=2) {
  1055.                if (  VB.Unclipped[i-2] & VB.Unclipped[i-3]
  1056.                    & VB.Unclipped[i-1] & VB.Unclipped[i]) {
  1057.                   render_quad( i-2, i-3, i-1, i, i, 1 );
  1058.                }
  1059.                else {
  1060.                   vlist[0] = i-2;
  1061.                   vlist[1] = i-3;
  1062.                   vlist[2] = i-1;
  1063.                   vlist[3] = i-0;
  1064.                   render_clipped_polygon( 4, vlist, 1 );
  1065.                }
  1066.             }
  1067.          }
  1068.          else {
  1069.             /* no clipping needed */
  1070.             GLuint i;
  1071.             for (i=3;i<VB.Count;i+=2) {
  1072.                render_quad( i-2, i-3, i-1, i, i, 1 );
  1073.             }
  1074.          }
  1075.          if (!alldone) {
  1076.             /* get ready for more vertices in this quad strip */
  1077.             copy_vertex( 0, VB_MAX-2 );
  1078.             copy_vertex( 1, VB_MAX-1 );
  1079.             VB.Count = 2;
  1080.             VB.AnyClipped = !VB.Unclipped[0] || !VB.Unclipped[1];
  1081.          }
  1082.      break;
  1083.  
  1084.       case GL_POLYGON:
  1085.          if (VB.Count>2) {
  1086.             GLuint i;
  1087.             for (i=0;i<VB.Count;i++) {
  1088.                vlist[i] = i;
  1089.             }
  1090.             if (VB.AnyClipped) {
  1091.                render_clipped_polygon( VB.Count, vlist, 0 );
  1092.             }
  1093.             else {
  1094.                render_polygon( VB.Count, vlist, 0 );
  1095.             }
  1096.          }
  1097.      if (!alldone) {
  1098.             /* get ready for more vertices just like a triangle fan */
  1099.             copy_vertex( 1, VB_MAX-1 );
  1100.             VB.Count = 2;
  1101.             VB.AnyClipped = !VB.Unclipped[0] || !VB.Unclipped[1];
  1102.      }
  1103.      break;
  1104.  
  1105.       default:
  1106.          /* should never get here */
  1107.      abort();
  1108.    }
  1109.  
  1110.    /* Start = first vertex which hasn't been transformed yet */
  1111.    VB.Start = VB.Count;
  1112. }
  1113.  
  1114.  
  1115.  
  1116. /*
  1117.  * Part 2 of Vertex Buffer transformation:  compute lighting, clipflags,
  1118.  * fog, texture coords, etc.  Then call render_vb()...
  1119.  * The function is called either by xform_vb_part1() or by glDrawArraysEXT().
  1120.  */
  1121. void gl_transform_vb_part2( GLboolean alldone )
  1122. {
  1123. #ifdef PROFILE
  1124.    GLdouble t0 = gl_time();
  1125. #endif
  1126.  
  1127.    ASSERT( VB.Count>0 );
  1128.  
  1129.    /* Lighting */
  1130.    if (CC.Light.Enabled) {
  1131.       if (CC.RGBAflag) {
  1132.          if (VB.MaterialChanges) {
  1133.             GLuint i;
  1134.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1135.              * is called after the last glVertex inside a glBegin/glEnd pair.
  1136.              */
  1137.         for (i=VB.Start;i<=VB.Count;i++) {
  1138.                update_material( i );
  1139.            gl_color_shade_vertices( 1, &VB.Eye[i], &VB.Normal[i],
  1140.                                         CC.LightTwoSide,
  1141.                                         &VB.Fcolor[i], &VB.Bcolor[i] );
  1142.         }
  1143.      }
  1144.          else {
  1145.             if (CC.Light.Fast) {
  1146.                /* call optimized shader */
  1147.                gl_color_shade_vertices_fast( VB.Count-VB.Start,
  1148.                                              VB.Eye + VB.Start,
  1149.                                              VB.Normal + VB.Start,
  1150.                                              CC.LightTwoSide,
  1151.                                              VB.Fcolor + VB.Start,
  1152.                                              VB.Bcolor + VB.Start );
  1153.             }
  1154.             else {
  1155.                /* call full-featured shader */
  1156.                gl_color_shade_vertices( VB.Count-VB.Start,
  1157.                                         VB.Eye + VB.Start,
  1158.                                         VB.Normal + VB.Start,
  1159.                                         CC.LightTwoSide,
  1160.                                         VB.Fcolor + VB.Start,
  1161.                                         VB.Bcolor + VB.Start );
  1162.             }
  1163.      }
  1164.       }
  1165.       else {
  1166.          if (VB.MaterialChanges) {
  1167.             GLuint i;
  1168.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1169.              * is called after the last glVertex inside a glBegin/glEnd pair.
  1170.              */
  1171.             for (i=VB.Start;i<=VB.Count;i++) {
  1172.                update_material( i );
  1173.                gl_index_shade_vertices( 1, &VB.Eye[i], &VB.Normal[i],
  1174.                                         CC.LightTwoSide,
  1175.                                         &VB.Findex[i], &VB.Bindex[i] );
  1176.             }
  1177.          }
  1178.          else {
  1179.             gl_index_shade_vertices( VB.Count-VB.Start,
  1180.                                      VB.Eye + VB.Start, VB.Normal + VB.Start,
  1181.                                      CC.LightTwoSide,
  1182.                                      VB.Findex + VB.Start, VB.Bindex + VB.Start );
  1183.          }
  1184.       }
  1185.    }
  1186.  
  1187.    /* Per-vertex fog */
  1188.    if (CC.Fog.Enabled && CC.Hint.Fog!=GL_NICEST) {
  1189.       if (CC.RGBAflag) {
  1190.          /* Fog RGB colors */
  1191.          gl_fog_color_vertices( VB.Count - VB.Start,
  1192.                                 VB.Eye + VB.Start,
  1193.                                 VB.Fcolor + VB.Start );
  1194.          if (CC.LightTwoSide) {
  1195.             gl_fog_color_vertices( VB.Count - VB.Start,
  1196.                                    VB.Eye + VB.Start,
  1197.                                    VB.Bcolor + VB.Start );
  1198.          }
  1199.       }
  1200.       else {
  1201.          /* Fog color indexes */
  1202.          gl_fog_index_vertices( VB.Count - VB.Start,
  1203.                                 VB.Eye + VB.Start,
  1204.                                 VB.Findex + VB.Start );
  1205.          if (CC.LightTwoSide) {
  1206.             gl_fog_index_vertices( VB.Count - VB.Start,
  1207.                                    VB.Eye + VB.Start,
  1208.                                    VB.Bindex + VB.Start );
  1209.          }
  1210.       }
  1211.    }
  1212.  
  1213.    /* Compute/transform texture coords */
  1214.    if (CC.Texture.Enabled) {
  1215.       GLuint i;
  1216.       for (i=VB.Start;i<VB.Count;i++) {
  1217.          if (CC.Texture.TexGenEnabled) {
  1218.             gl_do_texgen( VB.Obj[i], VB.Eye[i], VB.Normal[i], VB.TexCoord[i] );
  1219.          }
  1220.          if (!CC.IdentityTexMat) {
  1221.             /* transform current texture coordinate by texture matrix */
  1222.             /* tc = TexMat * TexCoord */
  1223.             GLfloat tc[4];
  1224.             TRANSFORM_POINT( tc, CC.TextureMatrix, VB.TexCoord[i] );
  1225.             COPY_4V( VB.TexCoord[i], tc );
  1226.          }
  1227.       }
  1228.    }
  1229.  
  1230.    /* Initialize clip flags */
  1231.    MEMSET( VB.Unclipped+VB.Start, GL_TRUE, VB.Count-VB.Start );
  1232.  
  1233.    if (CC.Transform.AnyClip) {
  1234.       /* Clip against user-defined clip planes */
  1235.       GLuint p;
  1236.       for (p=0;p<MAX_CLIP_PLANES;p++) {
  1237.          if (CC.Transform.ClipEnabled[p]) {
  1238.             GLuint i;
  1239.             GLfloat a = CC.Transform.ClipEquation[p][0];
  1240.             GLfloat b = CC.Transform.ClipEquation[p][1];
  1241.             GLfloat c = CC.Transform.ClipEquation[p][2];
  1242.             GLfloat d = CC.Transform.ClipEquation[p][3];
  1243.             for (i=VB.Start;i<VB.Count;i++) {
  1244.                GLfloat dot = VB.Eye[i][0] * a + VB.Eye[i][1] * b
  1245.                            + VB.Eye[i][2] * c + VB.Eye[i][3] * d;
  1246.                if (dot < 0.0F) {
  1247.                   VB.Unclipped[i] = GL_FALSE;
  1248.                   VB.AnyClipped = GL_TRUE;
  1249.                }
  1250.             }
  1251.          }
  1252.       }
  1253.    }
  1254.  
  1255.    /* Transform vertices from eye to clip coords */
  1256.    /* Even transform clipped vertices because it's usually faster. */
  1257.    gl_xform_points_4fv( VB.Count-VB.Start, VB.Clip+VB.Start,
  1258.                         CC.ProjectionMatrix, VB.Eye+VB.Start );
  1259.  
  1260.    /*
  1261.     * Combined clip testing with clip-to-window coordinate mapping.
  1262.     */
  1263.    {
  1264.       GLfloat sx = CC.Viewport.Sx,  tx = CC.Viewport.Tx + CC.RasterOffsetX;
  1265.       GLfloat sy = CC.Viewport.Sy,  ty = CC.Viewport.Ty + CC.RasterOffsetY;
  1266.       GLfloat sz = CC.Viewport.Sz,  tz = CC.Viewport.Tz;
  1267.       GLuint i, start = VB.Start, n = VB.Count;
  1268.       for (i=start;i<n;i++) {
  1269.          GLfloat clipx = VB.Clip[i][0], clipy = VB.Clip[i][1];
  1270.          GLfloat clipz = VB.Clip[i][2], clipw = VB.Clip[i][3];
  1271.          if (clipx > clipw || clipx < -clipw ||
  1272.              clipy > clipw || clipy < -clipw ||
  1273.              clipz > clipw || clipz < -clipw ) {
  1274.             /* vertex is clipped */
  1275.             VB.Unclipped[i] = GL_FALSE;
  1276.             VB.AnyClipped = GL_TRUE;
  1277.          }
  1278.          else {
  1279.             /* vertex not clipped */
  1280.             GLfloat d = 1.0F / clipw;
  1281.             VB.Win[i][0] = clipx * d * sx + tx;
  1282.             VB.Win[i][1] = clipy * d * sy + ty;
  1283.             VB.Win[i][2] = clipz * d * sz + tz;
  1284.          }
  1285.       }
  1286.    }
  1287.  
  1288. #ifdef PROFILE
  1289.    CC.VertexTime += gl_time() - t0;
  1290.    CC.VertexCount += VB.Count - VB.Start;
  1291. #endif
  1292.  
  1293.    /* Render the primitives */
  1294.    render_vb( alldone );
  1295. }
  1296.  
  1297.  
  1298.  
  1299. /*
  1300.  * When the Vertex Buffer is full, this function transforms all the
  1301.  * vertices and normals then calls xform_vb_part2()...
  1302.  */
  1303. static void transform_vb_part1( GLboolean alldone )
  1304. {
  1305. #ifdef PROFILE
  1306.    GLdouble t0 = gl_time();
  1307. #endif
  1308.  
  1309.    ASSERT( VB.Count>0 );
  1310.  
  1311.  
  1312.    /* Transform vertexes from object to eye coords */
  1313.    gl_xform_points_4fv( VB.Count-VB.Start, VB.Eye+VB.Start,
  1314.                         CC.ModelViewMatrix, VB.Obj+VB.Start );
  1315.  
  1316.    /* Transform normals from object to eye coords */
  1317.    if (CC.NeedNormals) {
  1318.       gl_xform_normals_3fv( VB.Count-VB.Start,
  1319.                             VB.Normal+VB.Start, CC.ModelViewInv,
  1320.                             VB.Normal+VB.Start, CC.Transform.Normalize );
  1321.    }
  1322.  
  1323. #ifdef PROFILE
  1324.    CC.VertexTime += gl_time() - t0;
  1325. #endif
  1326.  
  1327.    gl_transform_vb_part2( alldone );
  1328. }
  1329.  
  1330.  
  1331.  
  1332. /*
  1333.  * Save a glVertex call into a display list AND execute it.
  1334.  */
  1335. void gl_save_and_execute_vertex( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1336. {
  1337.    GLuint count = VB.Count;   /* copy to local var to encourage optimization */
  1338.  
  1339.    /* Put vertex into display list */
  1340.    gl_save_vertex( x, y, z, w );
  1341.  
  1342.    /* Exectue vertex command */
  1343.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1344.    if (CC.RGBAflag) {
  1345.       if (CC.Light.Enabled) {
  1346.          /* need normal vector, vertex color is computed from material */
  1347.          COPY_3V( VB.Normal[count], CC.Current.Normal );
  1348.       }
  1349.       else {
  1350.          /* not lighting, need vertex color */
  1351.          GLint shift = CC.ColorShift;
  1352.          VB.Fcolor[count][0] = CC.Current.IntColor[0] << shift;
  1353.          VB.Fcolor[count][1] = CC.Current.IntColor[1] << shift;
  1354.          VB.Fcolor[count][2] = CC.Current.IntColor[2] << shift;
  1355.          VB.Fcolor[count][3] = CC.Current.IntColor[3] << shift;
  1356.       }
  1357.       if (CC.Texture.Enabled) {
  1358.          COPY_4V( VB.TexCoord[count], CC.Current.TexCoord );
  1359.       }
  1360.    }
  1361.    else {
  1362.       if (CC.Light.Enabled) {
  1363.          /* need normal vector, vertex color index computed from material*/
  1364.          COPY_3V( VB.Normal[count], CC.Current.Normal );
  1365.       }
  1366.       else {
  1367.          /* not lighting, new vertex color index */
  1368.          VB.Findex[count] = CC.Current.Index;
  1369.       }
  1370.    }
  1371.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1372.  
  1373.    count++;
  1374.    VB.Count = count;
  1375.    if (count==VB_MAX) {
  1376.       transform_vb_part1( GL_FALSE );
  1377.    }
  1378. }
  1379.  
  1380.  
  1381. /* RGB, lit, textured vertex */
  1382. static void vertex_normal_texture( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1383. {
  1384.    GLuint count = VB.Count;
  1385.  
  1386.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1387.    COPY_3V( VB.Normal[count], CC.Current.Normal );
  1388.    COPY_4V( VB.TexCoord[count], CC.Current.TexCoord );
  1389.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1390.  
  1391.    count++;
  1392.    VB.Count = count;
  1393.    if (count==VB_MAX) {
  1394.       transform_vb_part1( GL_FALSE );
  1395.    }
  1396. }
  1397.  
  1398.  
  1399. /* RGB or CI, lit, untextured vertex */
  1400. static void vertex_normal( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1401. {
  1402.    GLuint count = VB.Count;
  1403.  
  1404.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1405.    COPY_3V( VB.Normal[count], CC.Current.Normal );
  1406.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1407.  
  1408.    count++;
  1409.    VB.Count = count;
  1410.    if (count==VB_MAX) {
  1411.       transform_vb_part1( GL_FALSE );
  1412.    }
  1413. }
  1414.  
  1415.  
  1416. /* RGB, unlit, textured vertex */
  1417. static void vertex_texture( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1418. {
  1419.    GLuint count = VB.Count;
  1420.    GLint shift = CC.ColorShift;
  1421.  
  1422.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1423.    VB.Fcolor[count][0] = CC.Current.IntColor[0] << shift;
  1424.    VB.Fcolor[count][1] = CC.Current.IntColor[1] << shift;
  1425.    VB.Fcolor[count][2] = CC.Current.IntColor[2] << shift;
  1426.    VB.Fcolor[count][3] = CC.Current.IntColor[3] << shift;
  1427.    COPY_4V( VB.TexCoord[count], CC.Current.TexCoord );
  1428.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1429.  
  1430.    count++;
  1431.    VB.Count = count;
  1432.    if (count==VB_MAX) {
  1433.       transform_vb_part1( GL_FALSE );
  1434.    }
  1435. }
  1436.  
  1437.  
  1438. /* RGB, unlit, untextured vertex */
  1439. static void vertex_color( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1440. {
  1441.    GLuint count = VB.Count;
  1442.    GLint shift = CC.ColorShift;
  1443.  
  1444.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1445.    VB.Fcolor[count][0] = CC.Current.IntColor[0] << shift;
  1446.    VB.Fcolor[count][1] = CC.Current.IntColor[1] << shift;
  1447.    VB.Fcolor[count][2] = CC.Current.IntColor[2] << shift;
  1448.    VB.Fcolor[count][3] = CC.Current.IntColor[3] << shift;
  1449.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1450.  
  1451.    count++;
  1452.    VB.Count = count;
  1453.    if (count==VB_MAX) {
  1454.       transform_vb_part1( GL_FALSE );
  1455.    }
  1456. }
  1457.  
  1458.  
  1459. /* CI, unlit vertex */
  1460. static void vertex_index( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1461. {
  1462.    GLuint count = VB.Count;
  1463.  
  1464.    ASSIGN_4V( VB.Obj[count], x, y, z, w );
  1465.    VB.Findex[count] = CC.Current.Index;
  1466.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1467.  
  1468.    count++;
  1469.    VB.Count = count;
  1470.    if (count==VB_MAX) {
  1471.       transform_vb_part1( GL_FALSE );
  1472.    }
  1473. }
  1474.  
  1475.  
  1476. /*
  1477.  * Called when outside glBegin/glEnd, raises an error.
  1478.  */
  1479. void gl_nop_vertex( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1480. {
  1481.    gl_error( GL_INVALID_OPERATION, "glVertex" );
  1482. }
  1483.  
  1484.  
  1485.  
  1486. /*
  1487.  * This function examines the current GL state and sets the CC.VertexFunc
  1488.  * pointer to point at the appropriate vertex function.
  1489.  */
  1490. static void setup_vertex_pointer( void )
  1491. {
  1492.    ASSERT( !INSIDE_BEGIN_END );
  1493.    if (CC.RGBAflag) {
  1494.       if (CC.Light.Enabled) {
  1495.          if (CC.Texture.Enabled) {
  1496.             CC.VertexFunc = vertex_normal_texture;
  1497.          }
  1498.          else {
  1499.             CC.VertexFunc = vertex_normal;
  1500.          }
  1501.       }
  1502.       else {
  1503.          /* not lighting, need vertex color */
  1504.          if (CC.Texture.Enabled) {
  1505.             CC.VertexFunc = vertex_texture;
  1506.          }
  1507.          else {
  1508.             CC.VertexFunc = vertex_color;
  1509.          }
  1510.       }
  1511.    }
  1512.    else {
  1513.       if (CC.Light.Enabled) {
  1514.          CC.VertexFunc = vertex_normal;
  1515.       }
  1516.       else {
  1517.          CC.VertexFunc = vertex_index;
  1518.       }
  1519.    }
  1520. }
  1521.  
  1522.  
  1523.  
  1524. /*
  1525.  * Process a vertex produced by an evaluator.
  1526.  * Input:  vertex - the X,Y,Z,W vertex
  1527.  *         normal - normal vector
  1528.  *         color - 4 integer color components
  1529.  *         index - color index
  1530.  *         texcoord - texture coordinate
  1531.  */
  1532. void gl_eval_vertex( const GLfloat vertex[4], const GLfloat normal[3],
  1533.              const GLint color[4], GLuint index,
  1534.                      const GLfloat texcoord[4] )
  1535. {
  1536.    GLuint count = VB.Count;   /* copy to local var to encourage optimization */
  1537.    GLint shift = CC.ColorShift;
  1538.  
  1539.    COPY_4V( VB.Obj[count], vertex );
  1540.    COPY_3V( VB.Normal[count], normal );
  1541.    VB.Fcolor[count][0] = color[0] << shift;
  1542.    VB.Fcolor[count][1] = color[1] << shift;
  1543.    VB.Fcolor[count][2] = color[2] << shift;
  1544.    VB.Fcolor[count][3] = color[3] << shift;
  1545.    VB.Findex[count] = index;
  1546.    COPY_4V( VB.TexCoord[count], texcoord );
  1547.    VB.Edgeflag[count] = CC.Current.EdgeFlag;
  1548.  
  1549.    count++;
  1550.    VB.Count = count;
  1551.    if (count==VB_MAX) {
  1552.       transform_vb_part1( GL_FALSE );
  1553.    }
  1554. }
  1555.  
  1556.  
  1557.  
  1558.  
  1559. void gl_rasterpos( const GLfloat v[4] )
  1560. {
  1561.    GLfloat eye[4], clip[4], ndc[3], d;
  1562.  
  1563.    /* transform v to eye coords:  eye = ModelView * v */
  1564.    TRANSFORM_POINT( eye, CC.ModelViewMatrix, v );
  1565.  
  1566.    /* raster color */
  1567.    if (CC.Light.Enabled) {
  1568.       GLfloat eyenorm[3];
  1569.       if (!CC.ModelViewInvValid) {
  1570.      gl_compute_modelview_inverse();
  1571.       }
  1572.       TRANSFORM_NORMAL( eyenorm[0], eyenorm[1], eyenorm[2], CC.Current.Normal,
  1573.                         CC.ModelViewInv );
  1574.       CC.ColorShift = 0;  /* Colors only shifted when smooth shading */
  1575.       if (CC.RGBAflag) {
  1576.          GLfixed color[4];  /* not really fixed point but integers */
  1577.          GLfixed bcolor[4]; /* not used, dummy arg */
  1578.          gl_color_shade_vertices( 1, &eye, &eyenorm, 0, &color, &bcolor );
  1579.          CC.Current.RasterColor[0] = (GLfloat) color[0] / CC.RedScale;
  1580.          CC.Current.RasterColor[1] = (GLfloat) color[1] / CC.GreenScale;
  1581.          CC.Current.RasterColor[2] = (GLfloat) color[2] / CC.BlueScale;
  1582.          CC.Current.RasterColor[3] = (GLfloat) color[3] / CC.AlphaScale;
  1583.       }
  1584.       else {
  1585.          GLuint dummy;
  1586.      gl_index_shade_vertices( 1, &eye, &eyenorm, 0,
  1587.                                   &CC.Current.RasterIndex, &dummy );
  1588.       }
  1589.    }
  1590.    else {
  1591.       /* use current color or index */
  1592.       if (CC.RGBAflag) {
  1593.          CC.Current.RasterColor[0] = CC.Current.IntColor[0] / CC.RedScale;
  1594.          CC.Current.RasterColor[1] = CC.Current.IntColor[1] / CC.GreenScale;
  1595.          CC.Current.RasterColor[2] = CC.Current.IntColor[2] / CC.BlueScale;
  1596.          CC.Current.RasterColor[3] = CC.Current.IntColor[3] / CC.AlphaScale;
  1597.       }
  1598.       else {
  1599.      CC.Current.RasterIndex = CC.Current.Index;
  1600.       }
  1601.    }
  1602.  
  1603.    /* clip to user clipping planes */
  1604.    if (gl_userclip_point(eye)==0) {
  1605.       CC.Current.RasterPosValid = GL_FALSE;
  1606.       return;
  1607.    }
  1608.  
  1609.    /* compute raster distance */
  1610.    CC.Current.RasterDistance = (GLfloat)
  1611.                       sqrt( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
  1612.  
  1613.    /* apply projection matrix:  clip = Proj * eye */
  1614.    TRANSFORM_POINT( clip, CC.ProjectionMatrix, eye );
  1615.  
  1616.    /* clip to view volume */
  1617.    if (gl_viewclip_point( clip )==0) {
  1618.       CC.Current.RasterPosValid = GL_FALSE;
  1619.       return;
  1620.    }
  1621.  
  1622.    /* ndc = clip / W */
  1623.    ASSERT( clip[3]!=0.0 );
  1624.    d = 1.0F / clip[3];
  1625.    ndc[0] = clip[0] * d;
  1626.    ndc[1] = clip[1] * d;
  1627.    ndc[2] = clip[2] * d;
  1628.  
  1629.    CC.Current.RasterPos[0] = ndc[0] * CC.Viewport.Sx + CC.Viewport.Tx;
  1630.    CC.Current.RasterPos[1] = ndc[1] * CC.Viewport.Sy + CC.Viewport.Ty;
  1631.    CC.Current.RasterPos[2] = ndc[2] * CC.Viewport.Sz + CC.Viewport.Tz;
  1632.    CC.Current.RasterPos[3] = clip[3];
  1633.    CC.Current.RasterPosValid = GL_TRUE;
  1634.  
  1635.    /* FOG??? */
  1636.  
  1637.    if (CC.Texture.Enabled) {
  1638.       COPY_4V( CC.Current.RasterTexCoord, CC.Current.TexCoord );
  1639.    }
  1640.  
  1641.    if (CC.RenderMode==GL_SELECT) {
  1642.       /* TODO: is this correct? */
  1643.       CC.HitFlag = GL_TRUE;
  1644.       if (CC.Current.RasterPos[2] < CC.HitMinZ) {
  1645.      CC.HitMinZ = CC.Current.RasterPos[2];
  1646.       }
  1647.       if (CC.Current.RasterPos[2] < CC.HitMaxZ) {
  1648.      CC.HitMaxZ = CC.Current.RasterPos[2];
  1649.       }
  1650.    }
  1651.  
  1652. }
  1653.  
  1654.  
  1655.  
  1656.  
  1657. void gl_windowpos( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1658. {
  1659.  
  1660.    /* set raster position */
  1661.    CC.Current.RasterPos[0] = x;
  1662.    CC.Current.RasterPos[1] = y;
  1663.    CC.Current.RasterPos[2] = CLAMP( z, 0.0F, 1.0F );
  1664.    CC.Current.RasterPos[3] = w;
  1665.  
  1666.    CC.Current.RasterPosValid = GL_TRUE;
  1667.  
  1668.    /* raster color */
  1669.    if (CC.Light.Enabled) {
  1670.       GLfloat eye[4];
  1671.       GLfloat eyenorm[3];
  1672.       COPY_4V( eye, CC.Current.RasterPos );
  1673.       if (!CC.ModelViewInvValid) {
  1674.      gl_compute_modelview_inverse();
  1675.       }
  1676.       TRANSFORM_NORMAL( eyenorm[0], eyenorm[1], eyenorm[2], CC.Current.Normal,
  1677.                         CC.ModelViewInv );
  1678.       CC.ColorShift = 0;  /* Colors only shifted when smooth shading */
  1679.       if (CC.RGBAflag) {
  1680.          GLfixed color[4];  /* not really fixed point but integers */
  1681.          GLfixed bcolor[4]; /* not used, dummy arg */
  1682.          gl_color_shade_vertices( 1, &eye, &eyenorm, 0, &color, &bcolor );
  1683.          CC.Current.RasterColor[0] = (GLfloat) color[0] / CC.RedScale;
  1684.          CC.Current.RasterColor[1] = (GLfloat) color[1] / CC.GreenScale;
  1685.          CC.Current.RasterColor[2] = (GLfloat) color[2] / CC.BlueScale;
  1686.          CC.Current.RasterColor[3] = (GLfloat) color[3] / CC.AlphaScale;
  1687.       }
  1688.       else {
  1689.          GLuint dummy;
  1690.      gl_index_shade_vertices( 1, &eye, &eyenorm, 0,
  1691.                                   &CC.Current.RasterIndex, &dummy );
  1692.       }
  1693.    }
  1694.    else {
  1695.       /* use current color or index */
  1696.       if (CC.RGBAflag) {
  1697.          CC.Current.RasterColor[0] = CC.Current.IntColor[0] / CC.RedScale;
  1698.          CC.Current.RasterColor[1] = CC.Current.IntColor[1] / CC.GreenScale;
  1699.          CC.Current.RasterColor[2] = CC.Current.IntColor[2] / CC.BlueScale;
  1700.          CC.Current.RasterColor[3] = CC.Current.IntColor[3] / CC.AlphaScale;
  1701.       }
  1702.       else {
  1703.      CC.Current.RasterIndex = CC.Current.Index;
  1704.       }
  1705.    }
  1706.  
  1707.    CC.Current.RasterDistance = 0.0;
  1708.  
  1709.    if (CC.Texture.Enabled) {
  1710.       COPY_4V( CC.Current.RasterTexCoord, CC.Current.TexCoord );
  1711.    }
  1712.  
  1713.    if (CC.RenderMode==GL_SELECT) {
  1714.       /* TODO: is this correct? */
  1715.       CC.HitFlag = GL_TRUE;
  1716.       if (CC.Current.RasterPos[2] < CC.HitMinZ) {
  1717.      CC.HitMinZ = CC.Current.RasterPos[2];
  1718.       }
  1719.       if (CC.Current.RasterPos[2] < CC.HitMaxZ) {
  1720.      CC.HitMaxZ = CC.Current.RasterPos[2];
  1721.       }
  1722.    }
  1723. }
  1724.  
  1725.  
  1726.  
  1727.  
  1728. #ifdef PROFILE
  1729. static GLdouble begin_time;
  1730. #endif
  1731.  
  1732.  
  1733. void gl_begin( GLenum p )
  1734. {
  1735. #ifdef PROFILE
  1736.    begin_time = gl_time();
  1737. #endif
  1738.  
  1739.    if (!CC.ModelViewInvValid) {
  1740.       gl_compute_modelview_inverse();
  1741.    }
  1742.    if (CC.NewState) {
  1743.       gl_update_state();
  1744.    }
  1745.    if (CC.VertexFunc==gl_nop_vertex) {
  1746.       setup_vertex_pointer();
  1747.    }
  1748.    if (DD.begin) {
  1749.       (*DD.begin)( p );
  1750.    }
  1751.  
  1752.    CC.Mode = p;
  1753.    VB.Start = VB.Count = 0;
  1754.    VB.AnyClipped = GL_FALSE;
  1755.  
  1756.    VB.MonoColor = CC.MonoPixels;
  1757.    if (VB.MonoColor) {
  1758.       /* All pixels generated are likely to be the same color so have
  1759.        * the device driver set the "monocolor" now.
  1760.        */
  1761.       if (CC.RGBAflag) {
  1762.          GLubyte r = CC.Current.IntColor[0];
  1763.          GLubyte g = CC.Current.IntColor[1];
  1764.          GLubyte b = CC.Current.IntColor[2];
  1765.          GLubyte a = CC.Current.IntColor[3];
  1766.          (*DD.color)( r, g, b, a );
  1767.       }
  1768.       else {
  1769.          (*DD.index)(CC.Current.Index);
  1770.       }
  1771.    }
  1772.  
  1773.    /*
  1774.     * If flat shading, save integer vertex colors
  1775.     * else, save fixed-point (scaled) vertex colors
  1776.     */
  1777.    CC.ColorShift = (CC.Light.ShadeModel==GL_FLAT) ? 0 : FIXED_SHIFT;
  1778.  
  1779.    /* By default use front color/index.  Two-sided lighting may override. */
  1780.    VB.Color = VB.Fcolor;
  1781.    VB.Index = VB.Findex;
  1782.  
  1783.    switch (CC.Mode) {
  1784.       case GL_POINTS:
  1785.      CC.LightTwoSide = 0;
  1786.      PB_INIT( GL_POINT );
  1787.          CC.RasterOffsetX = CC.RasterOffsetY = 0.5F;
  1788.      break;
  1789.       case GL_LINES:
  1790.       case GL_LINE_STRIP:
  1791.       case GL_LINE_LOOP:
  1792.      CC.LightTwoSide = 0;
  1793.      CC.StippleCounter = 0;
  1794.      PB_INIT( GL_LINE );
  1795.          CC.RasterOffsetX = CC.RasterOffsetY = 0.5F;
  1796.          break;
  1797.       case GL_TRIANGLES:
  1798.       case GL_TRIANGLE_STRIP:
  1799.       case GL_TRIANGLE_FAN:
  1800.       case GL_QUADS:
  1801.       case GL_QUAD_STRIP:
  1802.       case GL_POLYGON:
  1803.      CC.LightTwoSide = (GLuint) CC.Light.Model.TwoSide;
  1804.      PB_INIT( GL_POLYGON );
  1805.          CC.RasterOffsetX = CC.RasterOffsetY = -0.5F;
  1806.          break;
  1807.       default:
  1808.      gl_error( GL_INVALID_ENUM, "glBegin" );
  1809.      CC.Mode = GL_BITMAP;
  1810.    }
  1811. }
  1812.  
  1813.  
  1814.  
  1815. void gl_end( void )
  1816. {
  1817.    if (CC.Mode==GL_BITMAP) {
  1818.       /* glEnd without glBegin */
  1819.       gl_error( GL_INVALID_OPERATION, "glEnd" );
  1820.       return;
  1821.    }
  1822.  
  1823.    if (VB.Count>VB.Start) {
  1824.       transform_vb_part1( GL_TRUE );
  1825.    }
  1826.    if (PB.count>0) {
  1827.       gl_flush_pb();
  1828.    }
  1829.    PB.primitive = CC.Mode = GL_BITMAP;  /* Default mode */
  1830.    VB.MaterialChanges = GL_FALSE;
  1831.  
  1832.    if (DD.end) {
  1833.       (*DD.end)();
  1834.    }
  1835.  
  1836. #ifdef PROFILE
  1837.    CC.BeginEndTime += gl_time() - begin_time;
  1838.    CC.BeginEndCount++;
  1839. #endif
  1840. }
  1841.  
  1842.  
  1843.  
  1844.  
  1845. /*
  1846.  *
  1847.  * Public functions
  1848.  *
  1849.  */
  1850.  
  1851. void glBegin( GLenum p )
  1852. {
  1853.    if (CC.CompileFlag) {
  1854.       gl_save_begin( p );
  1855.    }
  1856.    if (CC.ExecuteFlag) {
  1857.       gl_begin( p );
  1858.    }
  1859. }
  1860.  
  1861.  
  1862.  
  1863. void glEnd( void )
  1864. {
  1865.    if (CC.CompileFlag) {
  1866.       gl_save_end();
  1867.    }
  1868.    if (CC.ExecuteFlag) {
  1869.       gl_end();
  1870.    }
  1871. }
  1872.