aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/do_iter.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/do_iter.cpp
downloadopenparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz
openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip
initial importHEADmain
Diffstat (limited to 'src/parsec/do_iter.cpp')
-rw-r--r--src/parsec/do_iter.cpp1772
1 files changed, 1772 insertions, 0 deletions
diff --git a/src/parsec/do_iter.cpp b/src/parsec/do_iter.cpp
new file mode 100644
index 0000000..d1d46b4
--- /dev/null
+++ b/src/parsec/do_iter.cpp
@@ -0,0 +1,1772 @@
+/*
+ * PARSEC - Iterated Primitives Drawing Code
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:33 $
+ *
+ * Orginally written by:
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 1999-2000
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+// subsystem headers
+#include "vid_defs.h"
+
+// drawing subsystem
+#include "d_iter.h"
+
+// subsystem linkage info
+#include "linkinfo.h"
+
+// mathematics header
+#include "utl_math.h"
+
+// model header
+#include "utl_model.h"
+
+// local module header
+#include "do_iter.h"
+
+// proprietary module headers
+#include "con_aux.h"
+#include "ro_api.h"
+#include "ro_supp.h"
+
+
+// flags
+#define ALLOW_LINE_STRIP_RESTARTS
+#define PERFORM_PRE_CLIPPING
+#define EXPLICIT_GL_ORTHO
+
+
+
+//NOTE:
+// the 2-D iter functions don't do any clipping. the user
+// must ensure that drawing works correctly without
+// clipping. (e.g., clipping them before if they are not
+// already known to be contained in the frustum.)
+// but OpenGL does clipping anyway.
+
+
+
+// set bias for iterated depth (polygon offset) -------------------------------
+//
+void D_BiasIterDepth( int bias )
+{
+ #define NO_DEPTH_BIAS 0
+
+ // reset bias?
+ if ( bias == NO_DEPTH_BIAS ) {
+
+ glDisable( GL_POLYGON_OFFSET_FILL );
+
+ } else {
+
+ glEnable( GL_POLYGON_OFFSET_FILL );
+ glPolygonOffset( (GLfloat) 0, (GLfloat) 0 );
+// glPolygonOffset( (GLfloat) 0, (GLfloat) bias );
+// glPolygonOffset( (GLfloat) bias, (GLfloat) bias );
+ }
+}
+
+
+// storage for currently active transformation matrix -------------------------
+//
+static Xmatrx _iter_matrix;
+static Xmatrx *iter_matrix = NULL; // NULL means identity matrix
+static Xmatrx *prev_matrix;
+static GLfloat gl_cur_matrix[ 16 ];
+
+
+// load transformation matrix to use for iterated primitives drawing ----------
+//
+void D_LoadIterMatrix( Xmatrx matrix )
+{
+ if ( matrix != NULL ) {
+
+ iter_matrix = &_iter_matrix;
+ memcpy( iter_matrix, matrix, sizeof( Xmatrx ) );
+
+ gl_cur_matrix[ 0 ] = GEOMV_TO_FLOAT( matrix[ 0 ][ 0 ] );
+ gl_cur_matrix[ 1 ] = GEOMV_TO_FLOAT( matrix[ 1 ][ 0 ] );
+ gl_cur_matrix[ 2 ] = GEOMV_TO_FLOAT( matrix[ 2 ][ 0 ] );
+ gl_cur_matrix[ 3 ] = GEOMV_0;
+ gl_cur_matrix[ 4 ] = GEOMV_TO_FLOAT( matrix[ 0 ][ 1 ] );
+ gl_cur_matrix[ 5 ] = GEOMV_TO_FLOAT( matrix[ 1 ][ 1 ] );
+ gl_cur_matrix[ 6 ] = GEOMV_TO_FLOAT( matrix[ 2 ][ 1 ] );
+ gl_cur_matrix[ 7 ] = GEOMV_0;
+ gl_cur_matrix[ 8 ] = GEOMV_TO_FLOAT( matrix[ 0 ][ 2 ] );
+ gl_cur_matrix[ 9 ] = GEOMV_TO_FLOAT( matrix[ 1 ][ 2 ] );
+ gl_cur_matrix[ 10 ] = GEOMV_TO_FLOAT( matrix[ 2 ][ 2 ] );
+ gl_cur_matrix[ 11 ] = GEOMV_0;
+ gl_cur_matrix[ 12 ] = GEOMV_TO_FLOAT( matrix[ 0 ][ 3 ] );
+ gl_cur_matrix[ 13 ] = GEOMV_TO_FLOAT( matrix[ 1 ][ 3 ] );
+ gl_cur_matrix[ 14 ] = GEOMV_TO_FLOAT( matrix[ 2 ][ 3 ] );
+ gl_cur_matrix[ 15 ] = GEOMV_1;
+
+ } else {
+
+ iter_matrix = NULL;
+ }
+}
+
+
+// static vertex buffers for intermediate storage -----------------------------
+//
+#define VERTEX_BUFFERS_SIZE 256
+
+struct iter_prim_s {
+
+ word flags;
+ short NumVerts;
+ dword itertype;
+ word raststate;
+ word rastmask;
+ Plane3* plane;
+ TextureMap* texmap;
+ IterVertex3 Vtxs[ VERTEX_BUFFERS_SIZE ];
+};
+
+static iter_prim_s _iter_prim[ 1 ];
+static iter_prim_s *iter_prim = _iter_prim;
+static GLVertex3 _gl_array_vtxs[ VERTEX_BUFFERS_SIZE ];
+static GLVertex3 *gl_array_vtxs = _gl_array_vtxs;
+
+
+// current vertex array info --------------------------------------------------
+//
+static GLTexInfo gl_array_texinfo;
+static IterArray3* gl_array_current = NULL;
+static dword gl_lockrange_base;
+static dword gl_lockrange_beyond;
+static int gl_array_zcmpstate;
+static int gl_array_zwritestate;
+
+
+// determine whether primitive needs texture ----------------------------------
+//
+#define ITERPRIM_TEXTURED(p) ( ( (p)->itertype & iter_base_mask ) >= iter_texonly )
+
+
+// opengl vertex array macros -------------------------------------------------
+//
+#define INIT_GL_ARRAYS(p,i,c) { \
+ \
+ if ( ITERPRIM_TEXTURED( p ) ) { \
+ RO_ClientState( VTXARRAY_VERTICES | VTXARRAY_COLORS | VTXARRAY_TEXCOORDS ); \
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_4, gl_array_vtxs ) ) { \
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x ); \
+ glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( GLVertex3 ), &gl_array_vtxs->r ); \
+ glTexCoordPointer( 4, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->s ); \
+ } \
+ } else { \
+ RO_ClientState( VTXARRAY_VERTICES | VTXARRAY_COLORS ); \
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_2, gl_array_vtxs ) ) { \
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x ); \
+ glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( GLVertex3 ), &gl_array_vtxs->r ); \
+ } \
+ } \
+}
+
+#define DEINIT_GL_ARRAYS(p) { \
+ \
+}
+
+
+// retrieve texture info and select texture -----------------------------------
+//
+PRIVATE
+void DO_SelectTexture( TextureMap *texmap, GLTexInfo *texinfo )
+{
+ ASSERT( texmap != NULL );
+ ASSERT( texinfo != NULL );
+
+ // fill texinfo structure and determine coscale/aratio
+ RO_TextureMap2GLTexInfo( texinfo, texmap );
+
+ // enforce texel source
+ RO_SelectTexelSource( texinfo );
+}
+
+
+// prepare vertices for use by gl (convert to gl format) ----------------------
+//
+PRIVATE
+void DO_PrepVertices2( dword flags, IterVertex2 *vtxs, int numverts, GLTexInfo *texinfo )
+{
+ ASSERT( vtxs != NULL );
+ ASSERT( numverts > 0 );
+
+ ASSERT( gl_array_vtxs == _gl_array_vtxs );
+ ASSERT( iter_prim == _iter_prim );
+
+ // allocate dynamic array if static storage too small
+ if ( numverts > VERTEX_BUFFERS_SIZE ) {
+ gl_array_vtxs = (GLVertex3 *) ALLOCMEM( numverts * sizeof( GLVertex3 ) );
+ if ( gl_array_vtxs == NULL ) {
+ OUTOFMEM( "DO_ITER::DO_PrepVertices2(): no mem for vertex array." );
+ }
+ }
+
+ // convert vertex info into opengl format
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+ IterVertex2 **refs = (IterVertex2 **) vtxs;
+ RO_IterVertex2GLVertexRef( gl_array_vtxs, refs, numverts, texinfo );
+ } else {
+ RO_IterVertex2GLVertex( gl_array_vtxs, vtxs, numverts, texinfo );
+ }
+}
+
+
+// prepare vertices for use by gl (project and convert to gl format) ----------
+//
+PRIVATE
+void DO_PrepVertices3( dword flags, IterVertex3 *vtxs, int numverts, GLTexInfo *texinfo )
+{
+ ASSERT( vtxs != NULL );
+ ASSERT( numverts > 0 );
+
+ ASSERT( gl_array_vtxs == _gl_array_vtxs );
+ ASSERT( ( iter_prim == _iter_prim ) ||
+ ( ( flags & ITERFLAG_NONDESTRUCTIVE ) == 0 ) );
+
+ // allocate dynamic array if static storage too small
+ if ( numverts > VERTEX_BUFFERS_SIZE ) {
+ gl_array_vtxs = (GLVertex3 *) ALLOCMEM( numverts * sizeof( GLVertex3 ) );
+ if ( gl_array_vtxs == NULL ) {
+ OUTOFMEM( "DO_ITER::DO_PrepVertices3(): no mem for vertex array." );
+ }
+ }
+
+ IterVertex3 **refs = (IterVertex3 **) vtxs;
+
+ // project vertices/texture coordinates if specified
+ if ( flags & ( ITERFLAG_Z_DIV_XYZ | ITERFLAG_Z_DIV_UVW ) ) {
+
+ // make local copy if nondestructive specified
+ if ( flags & ITERFLAG_NONDESTRUCTIVE ) {
+
+ if ( numverts > VERTEX_BUFFERS_SIZE ) {
+ iter_prim = (iter_prim_s *)
+ ALLOCMEM( (size_t)&((iter_prim_s*)0)->Vtxs[ numverts ] );
+ if ( iter_prim == NULL ) {
+ OUTOFMEM( "DO_ITER::DO_PrepVertices3(): no mem for vertex copies." );
+ }
+ }
+
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+ for ( int vtx = numverts - 1; vtx >= 0 ; vtx-- )
+ iter_prim->Vtxs[ vtx ] = *refs[ vtx ];
+ flags &= ~ITERFLAG_VERTEXREFS;
+ } else {
+ memcpy( iter_prim->Vtxs, vtxs, numverts * sizeof( IterVertex3 ) );
+ }
+
+ vtxs = iter_prim->Vtxs;
+ }
+
+ // project vertices/texture coordinates
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ geomv_t ooz = SCREENSPACE_OOZ( *refs[ v ] );
+ if ( flags & ITERFLAG_Z_DIV_XYZ ) {
+ refs[ v ]->X = COORD_TO_GEOMV( SCREENSPACE_XOZ( *refs[ v ], ooz ) );
+ refs[ v ]->Y = COORD_TO_GEOMV( SCREENSPACE_YOZ( *refs[ v ], ooz ) );
+ refs[ v ]->Z = ( flags & ITERFLAG_Z_TO_DEPTH ) ?
+ DEPTH_TO_GEOMV( DEPTHBUFF_VALUE( ooz ) ) : GEOMV_1;
+ }
+ if ( flags & ITERFLAG_Z_DIV_UVW ) {
+ refs[ v ]->U = GEOMV_MUL( refs[ v ]->U, ooz );
+ refs[ v ]->V = GEOMV_MUL( refs[ v ]->V, ooz );
+ refs[ v ]->W = ( flags & ITERFLAG_W_NOT_ONE ) ?
+ GEOMV_MUL( refs[ v ]->W, ooz ) : ooz;
+ }
+ }
+
+ } else {
+
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ geomv_t ooz = SCREENSPACE_OOZ( vtxs[ v ] );
+ if ( flags & ITERFLAG_Z_DIV_XYZ ) {
+ vtxs[ v ].X = COORD_TO_GEOMV( SCREENSPACE_XOZ( vtxs[ v ], ooz ) );
+ vtxs[ v ].Y = COORD_TO_GEOMV( SCREENSPACE_YOZ( vtxs[ v ], ooz ) );
+ vtxs[ v ].Z = ( flags & ITERFLAG_Z_TO_DEPTH ) ?
+ DEPTH_TO_GEOMV( DEPTHBUFF_VALUE( ooz ) ) : GEOMV_1;
+ }
+ if ( flags & ITERFLAG_Z_DIV_UVW ) {
+ vtxs[ v ].U = GEOMV_MUL( vtxs[ v ].U, ooz );
+ vtxs[ v ].V = GEOMV_MUL( vtxs[ v ].V, ooz );
+ vtxs[ v ].W = ( flags & ITERFLAG_W_NOT_ONE ) ?
+ GEOMV_MUL( vtxs[ v ].W, ooz ) : ooz;
+ }
+ }
+ }
+ }
+
+ // convert vertex info into opengl format
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+ RO_IterVertex3GLVertexRef( gl_array_vtxs, refs, numverts, texinfo );
+ } else {
+ RO_IterVertex3GLVertex( gl_array_vtxs, vtxs, numverts, texinfo );
+ }
+}
+
+
+// transform vertices using current transformation matrix ---------------------
+//
+PRIVATE
+iter_prim_s *DO_TransformVertices3( iter_prim_s *itprim, int numverts )
+{
+ ASSERT( itprim != NULL );
+ ASSERT( numverts > 0 );
+
+ if ( itprim->flags & ITERFLAG_NONDESTRUCTIVE ) {
+
+ // allocate dynamic array if static storage too small
+ if ( numverts > VERTEX_BUFFERS_SIZE ) {
+ iter_prim = (iter_prim_s *)
+ ALLOCMEM( (size_t)&((iter_prim_s*)0)->Vtxs[ numverts ] );
+ if ( iter_prim == NULL ) {
+ OUTOFMEM( "DO_ITER::DO_TransformVertices3(): no mem for primitive copy." );
+ }
+ }
+
+ // transform vertices into copy
+ if ( itprim->flags & ITERFLAG_VERTEXREFS ) {
+
+ IterVertex3 **refs = (IterVertex3 **) itprim->Vtxs;
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ memcpy( &iter_prim->Vtxs[ v ], refs[ v ], sizeof( IterVertex3 ) );
+ MtxVctMUL( *iter_matrix, (Vertex3 *)refs[ v ],
+ (Vertex3 *)&iter_prim->Vtxs[ v ] );
+ }
+
+ } else {
+
+ IterVertex3 *vtxs = itprim->Vtxs;
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ memcpy( &iter_prim->Vtxs[ v ], &vtxs[ v ], sizeof( IterVertex3 ) );
+ MtxVctMUL( *iter_matrix, (Vertex3 *)&vtxs[ v ],
+ (Vertex3 *)&iter_prim->Vtxs[ v ] );
+ }
+ }
+
+ // copy header, use copy from here on
+ memcpy( iter_prim, itprim, (size_t)((iter_prim_s*)0)->Vtxs );
+ itprim = iter_prim;
+
+ // no refs anymore, avoid second copy (copy may be destroyed)
+ itprim->flags &= ( ~ITERFLAG_VERTEXREFS & ~ITERFLAG_NONDESTRUCTIVE );
+
+ } else {
+
+ // transform vertices in place
+ Vertex3 tempvert;
+ if ( itprim->flags & ITERFLAG_VERTEXREFS ) {
+
+ IterVertex3 **refs = (IterVertex3 **) itprim->Vtxs;
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ MtxVctMUL( *iter_matrix, (Vertex3 *)refs[ v ], &tempvert );
+ refs[ v ]->X = tempvert.X;
+ refs[ v ]->Y = tempvert.Y;
+ refs[ v ]->Z = tempvert.Z;
+ }
+
+ } else {
+
+ IterVertex3 *vtxs = itprim->Vtxs;
+ for ( int v = numverts - 1; v >= 0 ; v-- ) {
+ MtxVctMUL( *iter_matrix, (Vertex3 *)&vtxs[ v ], &tempvert );
+ vtxs[ v ].X = tempvert.X;
+ vtxs[ v ].Y = tempvert.Y;
+ vtxs[ v ].Z = tempvert.Z;
+ }
+ }
+ }
+
+ return itprim;
+}
+
+
+// free intermediate storage (temp primitive, converted vertex array) ---------
+//
+INLINE
+void DO_KillTemporaries()
+{
+ // fall back to static storage
+ if ( gl_array_vtxs != _gl_array_vtxs ) {
+ FREEMEM( gl_array_vtxs );
+ gl_array_vtxs = _gl_array_vtxs;
+ }
+
+ if ( iter_prim != _iter_prim ) {
+ FREEMEM( iter_prim );
+ iter_prim = _iter_prim;
+ }
+}
+
+
+// setup gl projection matrix -------------------------------------------------
+//
+PRIVATE
+void DO_PrepProjection( dword flags, IterVertex3 *vtxs, int numverts, GLTexInfo *texinfo )
+{
+ ASSERT( vtxs != NULL );
+ ASSERT( numverts > 0 );
+
+ ASSERT( gl_array_vtxs == _gl_array_vtxs );
+ ASSERT( iter_prim == _iter_prim );
+
+ // allocate dynamic array if static storage too small
+ if ( numverts > VERTEX_BUFFERS_SIZE ) {
+ gl_array_vtxs = (GLVertex3 *) ALLOCMEM( numverts * sizeof( GLVertex3 ) );
+ if ( gl_array_vtxs == NULL ) {
+ OUTOFMEM( "DO_ITER::DO_PrepProjection(): no mem for vertex array." );
+ }
+ }
+
+ // convert vertex info into opengl format
+ GLVertex3 *glvtxs = gl_array_vtxs;
+ IterVertex3 *itervtxs = vtxs;
+ int num = numverts;
+
+ if ( texinfo != NULL ) {
+
+ float scale_u = texinfo->coscale;
+ float scale_v = texinfo->aratio * scale_u;
+
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+
+ // convert specified number of vertices
+ for ( int v = 0; v < num; v++ ) {
+
+ IterVertex3 *itervtx = ((IterVertex3 **)itervtxs)[ v ];
+ ASSERT( itervtx != NULL );
+
+ glvtxs[ v ].x = GEOMV_TO_FLOAT( itervtx->X );
+ glvtxs[ v ].y = GEOMV_TO_FLOAT( itervtx->Y );
+ glvtxs[ v ].z = GEOMV_TO_FLOAT( itervtx->Z );
+
+ *(dword*)&glvtxs[ v ].r = *(dword*)&itervtx->R;
+
+ glvtxs[ v ].s = GEOMV_TO_FLOAT( itervtx->U ) * scale_u;
+ glvtxs[ v ].t = GEOMV_TO_FLOAT( itervtx->V ) * scale_v;
+ glvtxs[ v ].p = 0.0f;
+ glvtxs[ v ].q = GEOMV_TO_FLOAT( itervtx->W );
+ }
+
+ } else {
+
+ // convert specified number of vertices
+ for ( int v = 0; v < num; v++ ) {
+
+ glvtxs[ v ].x = GEOMV_TO_FLOAT( itervtxs[ v ].X );
+ glvtxs[ v ].y = GEOMV_TO_FLOAT( itervtxs[ v ].Y );
+ glvtxs[ v ].z = GEOMV_TO_FLOAT( itervtxs[ v ].Z );
+
+ *(dword*)&glvtxs[ v ].r = *(dword*)&itervtxs[ v ].R;
+
+ glvtxs[ v ].s = GEOMV_TO_FLOAT( itervtxs[ v ].U ) * scale_u;
+ glvtxs[ v ].t = GEOMV_TO_FLOAT( itervtxs[ v ].V ) * scale_v;
+ glvtxs[ v ].p = 0.0f;
+ glvtxs[ v ].q = GEOMV_TO_FLOAT( itervtxs[ v ].W );
+ }
+ }
+
+ } else {
+
+ if ( flags & ITERFLAG_VERTEXREFS ) {
+
+ // convert specified number of vertices
+ for ( int v = 0; v < num; v++ ) {
+
+ IterVertex3 *itervtx = ((IterVertex3 **)itervtxs)[ v ];
+ ASSERT( itervtx != NULL );
+
+ glvtxs[ v ].x = GEOMV_TO_FLOAT( itervtx->X );
+ glvtxs[ v ].y = GEOMV_TO_FLOAT( itervtx->Y );
+ glvtxs[ v ].z = GEOMV_TO_FLOAT( itervtx->Z );
+
+ *(dword*)&glvtxs[ v ].r = *(dword*)&itervtx->R;
+ }
+
+ } else {
+
+ // convert specified number of vertices
+ for ( int v = 0; v < num; v++ ) {
+
+ glvtxs[ v ].x = GEOMV_TO_FLOAT( itervtxs[ v ].X );
+ glvtxs[ v ].y = GEOMV_TO_FLOAT( itervtxs[ v ].Y );
+ glvtxs[ v ].z = GEOMV_TO_FLOAT( itervtxs[ v ].Z );
+
+ *(dword*)&glvtxs[ v ].r = *(dword*)&itervtxs[ v ].R;
+ }
+ }
+ }
+
+ // configure modelview matrix
+ if ( iter_matrix != NULL ) {
+ glMatrixMode( GL_MODELVIEW );
+ glLoadMatrixf( gl_cur_matrix );
+ }
+
+ // configure projection matrix
+ glMatrixMode( GL_PROJECTION );
+ extern GLfloat gl_projective_matrix[];
+ glLoadMatrixf( gl_projective_matrix );
+}
+
+
+// restore standard gl projection matrix, disable transformation --------------
+//
+PRIVATE
+void DO_KillProjection()
+{
+ // set projection to screen coordinate identity
+ glMatrixMode( GL_PROJECTION );
+#ifdef EXPLICIT_GL_ORTHO
+ glLoadIdentity();
+ extern GLfloat gl_orthogonal_params[];
+ //SDL_CalcOrthogonalMatrix();
+ glOrtho( gl_orthogonal_params[ 0 ], gl_orthogonal_params[ 1 ],
+ gl_orthogonal_params[ 2 ], gl_orthogonal_params[ 3 ],
+ gl_orthogonal_params[ 4 ], gl_orthogonal_params[ 5 ] );
+#else
+ extern GLfloat gl_orthogonal_matrix[];
+ glLoadMatrixf( gl_orthogonal_matrix );
+#endif
+
+ // set modelview identity
+ if ( iter_matrix != NULL ) {
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ }
+}
+
+
+// draw 2-D point (point-set) using iterated vertex attributes ----------------
+//
+void D_DrawIterPoint2( IterPoint2 *itpoint )
+{
+ ASSERT( itpoint != NULL );
+ ASSERT( itpoint->NumVerts > 0 );
+
+ ASSERT( !ITERPRIM_TEXTURED( itpoint ) );
+ ASSERT( gl_array_current == NULL );
+
+ // convert vertex info into opengl format
+ dword flags = itpoint->flags;
+ DO_PrepVertices2( flags, itpoint->Vtxs, itpoint->NumVerts, NULL );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itpoint->itertype, itpoint->raststate, itpoint->rastmask );
+
+ // set line antialiasing mode
+ if ( flags & ITERFLAG_PS_ANTIALIASED )
+ RO_PointSmooth( TRUE );
+
+ // set point size
+ RO_PointSize( itpoint->pointsize );
+
+ // draw line strip/loop
+ INIT_GL_ARRAYS( itpoint, 0, itpoint->NumVerts );
+ glDrawArrays( GL_POINTS, 0, itpoint->NumVerts );
+ DEINIT_GL_ARRAYS( itpoint );
+
+ // set rasterizer state to default
+ if ( flags & ITERFLAG_PS_ANTIALIASED )
+ RO_PointSmooth( FALSE );
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+ DO_KillTemporaries();
+}
+
+
+// draw 3-D point (point-set) using iterated vertex attributes ----------------
+//
+void D_DrawIterPoint3( IterPoint3 *itpoint, dword cullmask )
+{
+}
+
+
+// draw 2-D line (line-strip) using iterated vertex attributes ----------------
+//
+void D_DrawIterLine2( IterLine2 *itline )
+{
+ ASSERT( itline != NULL );
+ ASSERT( itline->NumVerts > 1 );
+ ASSERT( itline->NumVerts <= MAX_ITERLINE_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itline ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itline->texmap, texinfo );
+ }
+
+ // convert vertex info into opengl format
+ dword flags = itline->flags;
+ DO_PrepVertices2( flags, itline->Vtxs, itline->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itline->itertype, itline->raststate, itline->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // set line antialiasing mode
+ if ( flags & ITERFLAG_LS_ANTIALIASED )
+ RO_LineSmooth( TRUE );
+
+ GLenum glmode = ( flags & ITERFLAG_LS_CLOSE_STRIP ) ? GL_LINE_LOOP : GL_LINE_STRIP;
+
+#ifdef ALLOW_LINE_STRIP_RESTARTS
+
+ int stripbase = 0;
+
+ INIT_GL_ARRAYS( itline, 0, itline->NumVerts );
+
+ // draw all strips but last
+ int subx = 1;
+ for ( subx = 1; subx < itline->NumVerts; subx++ ) {
+ if ( itline->Vtxs[ subx ].flags & ITERVTXFLAG_RESTART ) {
+ // draw sub-strip
+ glDrawArrays( GL_LINE_STRIP, stripbase, subx - stripbase );
+ stripbase = subx;
+ }
+ }
+
+ // looping works only correctly with a single strip
+ ASSERT( ( ( flags & ITERFLAG_LS_CLOSE_STRIP ) == 0 ) ||
+ ( stripbase == 0 ) );
+
+ // draw last strip/loop
+ glDrawArrays( glmode, stripbase, subx - stripbase );
+
+ DEINIT_GL_ARRAYS( itline );
+
+#else // ALLOW_LINE_STRIP_RESTARTS
+
+ // draw line strip/loop
+ INIT_GL_ARRAYS( itline, 0, itline->NumVerts );
+ glDrawArrays( glmode, 0, itline->NumVerts );
+ DEINIT_GL_ARRAYS( itline );
+
+#endif // ALLOW_LINE_STRIP_RESTARTS
+
+ // set rasterizer state to default
+ if ( flags & ITERFLAG_LS_ANTIALIASED )
+ RO_LineSmooth( FALSE );
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 3-D line (line-strip) using iterated vertex attributes ----------------
+//
+void D_DrawIterLine3( IterLine3 *itline, dword cullmask )
+{
+ ASSERT( itline != NULL );
+ ASSERT( itline->NumVerts > 1 );
+ ASSERT( itline->NumVerts <= MAX_ITERLINE_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ // transform vertices
+ if ( iter_matrix != NULL ) {
+ itline = (IterLine3 *)
+ DO_TransformVertices3( (iter_prim_s *)itline, itline->NumVerts );
+ }
+
+#ifdef PERFORM_PRE_CLIPPING
+
+ // clip if necessary
+ if ( cullmask != 0x00 ) {
+
+ //TODO:
+ ASSERT( 0 );
+ return;
+/*
+ IterLine3 *clipline =
+ CLIP_VolumeIterLine3( itline, View_Volume, cullmask );
+ if ( clipline == NULL )
+ return;
+ itline = clipline;
+*/
+ }
+
+#endif // PERFORM_PRE_CLIPPING
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itline ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itline->texmap, texinfo );
+ }
+
+ // project and convert vertices
+ dword flags = itline->flags;
+ DO_PrepVertices3( flags, itline->Vtxs, itline->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itline->itertype, itline->raststate, itline->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // set line antialiasing mode
+ if ( flags & ITERFLAG_LS_ANTIALIASED )
+ RO_LineSmooth( TRUE );
+
+ GLenum glmode = ( flags & ITERFLAG_LS_CLOSE_STRIP ) ?
+ GL_LINE_LOOP : GL_LINE_STRIP;
+
+#ifdef ALLOW_LINE_STRIP_RESTARTS
+
+ int stripbase = 0;
+
+ INIT_GL_ARRAYS( itline, 0, itline->NumVerts );
+
+ // draw all strips but last
+ int subx = 1;
+ for ( subx = 1; subx < itline->NumVerts; subx++ ) {
+ if ( itline->Vtxs[ subx ].flags & ITERVTXFLAG_RESTART ) {
+ // draw sub-strip
+ glDrawArrays( GL_LINE_STRIP, stripbase, subx - stripbase );
+ stripbase = subx;
+ }
+ }
+
+ // looping works only correctly with a single strip
+ ASSERT( ( ( flags & ITERFLAG_LS_CLOSE_STRIP ) == 0 ) ||
+ ( stripbase == 0 ) );
+
+ // draw last strip/loop
+ glDrawArrays( glmode, stripbase, subx - stripbase );
+
+ DEINIT_GL_ARRAYS( itline );
+
+#else // ALLOW_LINE_STRIP_RESTARTS
+
+ // draw line strip/loop
+ INIT_GL_ARRAYS( itline, 0, itline->NumVerts );
+ glDrawArrays( glmode, 0, itline->NumVerts );
+ DEINIT_GL_ARRAYS( itline );
+
+#endif // ALLOW_LINE_STRIP_RESTARTS
+
+ // set rasterizer state to default
+ if ( flags & ITERFLAG_LS_ANTIALIASED )
+ RO_LineSmooth( FALSE );
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 2-D triangle using iterated vertex attributes -------------------------
+//
+void D_DrawIterTriangle2( IterTriangle2 *ittri )
+{
+ ASSERT( ittri != NULL );
+ ASSERT( gl_array_current == NULL );
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( ittri ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( ittri->texmap, texinfo );
+ }
+
+ // convert vertex info into opengl format
+ DO_PrepVertices2( ittri->flags, ittri->Vtxs, 3, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( ittri->itertype, ittri->raststate, ittri->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw triangle
+ INIT_GL_ARRAYS( ittri, 0, 3 );
+ glDrawArrays( GL_TRIANGLES, 0, 3 );
+ DEINIT_GL_ARRAYS( ittri );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 3-D triangle using iterated vertex attributes -------------------------
+//
+void D_DrawIterTriangle3( IterTriangle3 *ittri, dword cullmask )
+{
+ ASSERT( ittri != NULL );
+ ASSERT( gl_array_current == NULL );
+
+ // face sidedness culling (front/back)
+ if ( ittri->flags & ITERFLAG_ONESIDED ) {
+
+ //NOTE:
+ // the ITERFLAG_BACKFACES flag means that
+ // backfaces are _drawn_ not _culled_. the
+ // bit for this is one in order for drawing
+ // of frontfaces to be the default.
+
+ ASSERT( ittri->plane != NULL );
+ if ( ( PLANE_OFFSET( ittri->plane ) <= 0 ) ==
+ ( ittri->flags & ITERFLAG_BACKFACES ) ) {
+
+ // cull faces if eye-point (origin) in
+ // wrong half-space according to plane
+ return;
+ }
+ }
+
+ // transform vertices
+ if ( iter_matrix != NULL ) {
+ ittri = (IterTriangle3 *)
+ DO_TransformVertices3( (iter_prim_s *)ittri, 3 );
+ }
+
+#ifdef PERFORM_PRE_CLIPPING
+
+ // clip if necessary
+ if ( cullmask != 0x00 ) {
+
+ IterPolygon3 *clippoly =
+ CLIP_VolumeIterTriangle3( ittri, View_Volume, cullmask );
+ if ( clippoly == NULL )
+ return;
+ if ( clippoly != (IterPolygon3 *) ittri ) {
+ prev_matrix = iter_matrix;
+ iter_matrix = NULL;
+ D_DrawIterPolygon3( clippoly, 0x00 );
+ iter_matrix = prev_matrix;
+ return;
+ }
+ }
+
+#endif // PERFORM_PRE_CLIPPING
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( ittri ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( ittri->texmap, texinfo );
+ }
+
+ // project and convert vertices
+ DO_PrepVertices3( ittri->flags, ittri->Vtxs, 3, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( ittri->itertype, ittri->raststate, ittri->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw triangle
+ INIT_GL_ARRAYS( ittri, 0, 3 );
+ glDrawArrays( GL_TRIANGLES, 0, 3 );
+ DEINIT_GL_ARRAYS( ittri );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 2-D rectangle using iterated vertex attributes ------------------------
+//
+void D_DrawIterRectangle2( IterRectangle2 *itrect )
+{
+ ASSERT( itrect != NULL );
+ ASSERT( gl_array_current == NULL );
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itrect ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itrect->texmap, texinfo );
+ }
+
+ // convert vertex info into opengl format
+ DO_PrepVertices2( itrect->flags, itrect->Vtxs, 4, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itrect->itertype, itrect->raststate, itrect->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw rectangle
+ INIT_GL_ARRAYS( itrect, 0, 4 );
+ glDrawArrays( GL_QUADS, 0, 4 );
+ DEINIT_GL_ARRAYS( itrect );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 3-D rectangle using iterated vertex attributes ------------------------
+//
+void D_DrawIterRectangle3( IterRectangle3 *itrect, dword cullmask )
+{
+ ASSERT( itrect != NULL );
+ ASSERT( gl_array_current == NULL );
+
+ // face sidedness culling (front/back)
+ if ( itrect->flags & ITERFLAG_ONESIDED ) {
+
+ //NOTE:
+ // the ITERFLAG_BACKFACES flag means that
+ // backfaces are _drawn_ not _culled_. the
+ // bit for this is one in order for drawing
+ // of frontfaces to be the default.
+
+ ASSERT( itrect->plane != NULL );
+ if ( ( PLANE_OFFSET( itrect->plane ) <= 0 ) ==
+ ( itrect->flags & ITERFLAG_BACKFACES ) ) {
+
+ // cull faces if eye-point (origin) in
+ // wrong half-space according to plane
+ return;
+ }
+ }
+
+ // transform vertices
+ if ( iter_matrix != NULL ) {
+ itrect = (IterRectangle3 *)
+ DO_TransformVertices3( (iter_prim_s *)itrect, 4 );
+ }
+
+#ifdef PERFORM_PRE_CLIPPING
+
+ // clip if necessary
+ if ( cullmask != 0x00 ) {
+
+ IterPolygon3 *clippoly =
+ CLIP_VolumeIterRectangle3( itrect, View_Volume, cullmask );
+ if ( clippoly == NULL )
+ return;
+ if ( clippoly != (IterPolygon3 *) itrect ) {
+ prev_matrix = iter_matrix;
+ iter_matrix = NULL;
+ D_DrawIterPolygon3( clippoly, 0x00 );
+ iter_matrix = prev_matrix;
+ return;
+ }
+ }
+
+#endif // PERFORM_PRE_CLIPPING
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itrect ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itrect->texmap, texinfo );
+ }
+
+ // project and convert vertices
+ DO_PrepVertices3( itrect->flags, itrect->Vtxs, 4, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itrect->itertype, itrect->raststate, itrect->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw rectangle
+ INIT_GL_ARRAYS( itrect, 0, 4 );
+ glDrawArrays( GL_QUADS, 0, 4 );
+ DEINIT_GL_ARRAYS( itrect );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 2-D n-gon using iterated vertex attributes ----------------------------
+//
+void D_DrawIterPolygon2( IterPolygon2 *itpoly )
+{
+ ASSERT( itpoly != NULL );
+ ASSERT( itpoly->NumVerts > 2 );
+ ASSERT( itpoly->NumVerts <= MAX_ITERPOLY_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itpoly ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itpoly->texmap, texinfo );
+ }
+
+ // convert vertex info into opengl format
+ DO_PrepVertices2( itpoly->flags, itpoly->Vtxs, itpoly->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itpoly->itertype, itpoly->raststate, itpoly->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw n-gon
+ INIT_GL_ARRAYS( itpoly, 0, itpoly->NumVerts );
+ glDrawArrays( GL_POLYGON, 0, itpoly->NumVerts );
+ DEINIT_GL_ARRAYS( itpoly );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 3-D n-gon using iterated vertex attributes ----------------------------
+//
+void D_DrawIterPolygon3( IterPolygon3 *itpoly, dword cullmask )
+{
+ ASSERT( itpoly != NULL );
+ ASSERT( itpoly->NumVerts > 2 );
+ ASSERT( itpoly->NumVerts <= MAX_ITERPOLY_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ // face sidedness culling (front/back)
+ if ( itpoly->flags & ITERFLAG_ONESIDED ) {
+
+ //NOTE:
+ // the ITERFLAG_BACKFACES flag means that
+ // backfaces are _drawn_ not _culled_. the
+ // bit for this is one in order for drawing
+ // of frontfaces to be the default.
+
+ ASSERT( itpoly->plane != NULL );
+ if ( ( PLANE_OFFSET( itpoly->plane ) <= 0 ) ==
+ ( itpoly->flags & ITERFLAG_BACKFACES ) ) {
+
+ // cull faces if eye-point (origin) in
+ // wrong half-space according to plane
+ return;
+ }
+ }
+
+ // transform vertices
+ if ( iter_matrix != NULL ) {
+ itpoly = (IterPolygon3 *)
+ DO_TransformVertices3( (iter_prim_s *)itpoly, itpoly->NumVerts );
+ }
+
+#ifdef PERFORM_PRE_CLIPPING
+
+ // clip if necessary
+ if ( cullmask != 0x00 ) {
+
+ IterPolygon3 *clippoly =
+ CLIP_VolumeIterPolygon3( itpoly, View_Volume, cullmask );
+ if ( clippoly == NULL )
+ return;
+ itpoly = clippoly;
+ }
+
+#endif // PERFORM_PRE_CLIPPING
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itpoly ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itpoly->texmap, texinfo );
+ }
+
+ // project and convert vertices
+ DO_PrepVertices3( itpoly->flags, itpoly->Vtxs, itpoly->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itpoly->itertype, itpoly->raststate, itpoly->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // draw n-gon
+ INIT_GL_ARRAYS( itpoly, 0, itpoly->NumVerts );
+ glDrawArrays( GL_POLYGON, 0, itpoly->NumVerts );
+ DEINIT_GL_ARRAYS( itpoly );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+// DO_KillTemporaries();
+}
+
+
+// draw 2-D triangle strip using iterated vertex attributes -------------------
+//
+void D_DrawIterTriStrip2( IterTriStrip2 *itstrip )
+{
+ ASSERT( itstrip != NULL );
+ ASSERT( itstrip->NumVerts > 2 );
+// ASSERT( itstrip->NumVerts <= MAX_ITERSTRIP_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itstrip ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itstrip->texmap, texinfo );
+ }
+
+ // convert vertex info into opengl format
+ DO_PrepVertices2( itstrip->flags, itstrip->Vtxs, itstrip->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itstrip->itertype, itstrip->raststate, itstrip->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ //NOTE:
+ // drawing sequence will be
+ // (012), (213), (234), (435), ...
+
+ // draw triangle strip
+ INIT_GL_ARRAYS( itstrip, 0, itstrip->NumVerts );
+ glDrawArrays( GL_TRIANGLE_STRIP, 0, itstrip->NumVerts );
+ DEINIT_GL_ARRAYS( itstrip );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+ DO_KillTemporaries();
+}
+
+
+// draw triangle strip as single triangles ------------------------------------
+//
+PRIVATE
+void DO_DrawStripAsTriangles( IterTriStrip3 *itstrip, dword cullmask )
+{
+ ASSERT( itstrip != NULL );
+
+ //NOTE:
+ // drawing sequence will be
+ // (012), (213), (234), (435), ...
+
+ IterTriangle3 ittri;
+
+ ittri.flags = itstrip->flags | ITERFLAG_VERTEXREFS | ITERFLAG_NONDESTRUCTIVE;
+ ittri.itertype = itstrip->itertype;
+ ittri.raststate = itstrip->raststate;
+ ittri.rastmask = itstrip->rastmask;
+ ittri.texmap = itstrip->texmap;
+
+ IterVertex3 **dstrefs = (IterVertex3 **) ittri.Vtxs;
+
+ if ( itstrip->flags & ITERFLAG_VERTEXREFS ) {
+
+ IterVertex3 **refs = (IterVertex3 **) itstrip->Vtxs;
+
+ // draw triangle strip
+ if ( itstrip->NumVerts & 0x01 ) {
+
+ // draw odd number of triangles
+ dstrefs[ 0 ] = refs[ 0 ];
+ dstrefs[ 1 ] = refs[ 1 ];
+ dstrefs[ 2 ] = refs[ 2 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ for ( int v = 3; v < itstrip->NumVerts; v+=2 ) {
+
+ dstrefs[ 0 ] = refs[ v-1 ];
+ dstrefs[ 1 ] = refs[ v-2 ];
+ dstrefs[ 2 ] = refs[ v+0 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ dstrefs[ 0 ] = refs[ v-1 ];
+ dstrefs[ 1 ] = refs[ v+0 ];
+ dstrefs[ 2 ] = refs[ v+1 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+ }
+
+ } else {
+
+ // draw even number of triangles
+ for ( int v = 2; v < itstrip->NumVerts; v+=2 ) {
+
+ dstrefs[ 0 ] = refs[ v-2 ];
+ dstrefs[ 1 ] = refs[ v-1 ];
+ dstrefs[ 2 ] = refs[ v+0 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ dstrefs[ 0 ] = refs[ v+0 ];
+ dstrefs[ 1 ] = refs[ v-1 ];
+ dstrefs[ 2 ] = refs[ v+1 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+ }
+ }
+
+ } else {
+
+ // draw triangle strip
+ if ( itstrip->NumVerts & 0x01 ) {
+
+ // draw odd number of triangles
+ dstrefs[ 0 ] = &itstrip->Vtxs[ 0 ];
+ dstrefs[ 1 ] = &itstrip->Vtxs[ 1 ];
+ dstrefs[ 2 ] = &itstrip->Vtxs[ 2 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ for ( int v = 3; v < itstrip->NumVerts; v+=2 ) {
+
+ dstrefs[ 0 ] = &itstrip->Vtxs[ v-1 ];
+ dstrefs[ 1 ] = &itstrip->Vtxs[ v-2 ];
+ dstrefs[ 2 ] = &itstrip->Vtxs[ v+0 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ dstrefs[ 0 ] = &itstrip->Vtxs[ v-1 ];
+ dstrefs[ 1 ] = &itstrip->Vtxs[ v+0 ];
+ dstrefs[ 2 ] = &itstrip->Vtxs[ v+1 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+ }
+
+ } else {
+
+ // draw even number of triangles
+ for ( int v = 2; v < itstrip->NumVerts; v+=2 ) {
+
+ dstrefs[ 0 ] = &itstrip->Vtxs[ v-2 ];
+ dstrefs[ 1 ] = &itstrip->Vtxs[ v-1 ];
+ dstrefs[ 2 ] = &itstrip->Vtxs[ v+0 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+
+ dstrefs[ 0 ] = &itstrip->Vtxs[ v+0 ];
+ dstrefs[ 1 ] = &itstrip->Vtxs[ v-1 ];
+ dstrefs[ 2 ] = &itstrip->Vtxs[ v+1 ];
+ D_DrawIterTriangle3( &ittri, cullmask );
+ }
+ }
+ }
+}
+
+
+// draw 3-D triangle strip using iterated vertex attributes -------------------
+//
+void D_DrawIterTriStrip3( IterTriStrip3 *itstrip, dword cullmask )
+{
+ ASSERT( itstrip != NULL );
+ ASSERT( itstrip->NumVerts > 2 );
+// ASSERT( itstrip->NumVerts <= MAX_ITERSTRIP_VERTICES );
+
+ ASSERT( gl_array_current == NULL );
+
+ //TODO:
+ // face culling. (ITERFLAG_PLANESTRIP,...)
+/*
+ // transform vertices
+ if ( iter_matrix != NULL ) {
+ itstrip = (IterTriStrip3 *)
+ DO_TransformVertices3( (iter_prim_s *)itstrip, itstrip->NumVerts );
+ }
+
+#ifdef PERFORM_PRE_CLIPPING
+
+ // clip if necessary
+ if ( cullmask != 0x00 ) {
+
+ prev_matrix = iter_matrix;
+ iter_matrix = NULL;
+ DO_DrawStripAsTriangles( itstrip, cullmask );
+ iter_matrix = prev_matrix;
+ return;
+*/
+ //TODO:
+/*
+ IterPolygon3 *clipstrip =
+ CLIP_VolumeIterTriStrip3( itstrip, View_Volume, cullmask );
+ if ( clipstrip == NULL )
+ return;
+ itstrip = clipstrip;
+*/
+/* }
+
+#endif
+*/
+ // get info and select texture
+ GLTexInfo _texinfo;
+ GLTexInfo *texinfo = NULL;
+ if ( ITERPRIM_TEXTURED( itstrip ) ) {
+ texinfo = &_texinfo;
+ DO_SelectTexture( itstrip->texmap, texinfo );
+ }
+
+ // project and convert vertices
+// DO_PrepVertices3( itstrip->flags, itstrip->Vtxs, itstrip->NumVerts, texinfo );
+
+ // use gl projection matrix
+ DO_PrepProjection( itstrip->flags, itstrip->Vtxs, itstrip->NumVerts, texinfo );
+
+ // save zcmp and zwrite state
+ int zcmpstate = RO_DepthCmpEnabled();
+ int zwritestate = RO_DepthWriteEnabled();
+
+ // configure rasterizer
+ RO_InitRasterizerState( itstrip->itertype, itstrip->raststate, itstrip->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ //NOTE:
+ // drawing sequence will be
+ // (012), (213), (234), (435), ...
+
+ // draw triangle strip
+ INIT_GL_ARRAYS( itstrip, 0, itstrip->NumVerts );
+ glDrawArrays( GL_TRIANGLE_STRIP, 0, itstrip->NumVerts );
+ DEINIT_GL_ARRAYS( itstrip );
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( zcmpstate, zwritestate );
+
+ // free intermediate storage
+ DO_KillTemporaries();
+
+ // restore gl projection matrix
+ DO_KillProjection();
+}
+
+
+// enable needed vertex arrays and set appropriate pointers -------------------
+//
+INLINE
+void DO_PrepArrays( dword arrayinfo )
+{
+ ASSERT( ITERARRAY_USE_COLOR == 0x01 );
+ ASSERT( ITERARRAY_USE_TEXTURE == 0x02 );
+
+ int stateindx = arrayinfo & 0x03;
+
+ switch ( stateindx ) {
+
+ case 0x00:
+ RO_ClientState( VTXARRAY_VERTICES );
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_1, gl_array_vtxs ) ) {
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x );
+ }
+ break;
+
+ case 0x01:
+ RO_ClientState( VTXARRAY_VERTICES | VTXARRAY_COLORS );
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_2, gl_array_vtxs ) ) {
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x );
+ glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( GLVertex3 ), &gl_array_vtxs->r );
+ }
+ break;
+
+ case 0x02:
+ RO_ClientState( VTXARRAY_VERTICES | VTXARRAY_TEXCOORDS );
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_3, gl_array_vtxs ) ) {
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x );
+ glTexCoordPointer( 4, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->s );
+ }
+ break;
+
+ case 0x03:
+ RO_ClientState( VTXARRAY_VERTICES | VTXARRAY_COLORS | VTXARRAY_TEXCOORDS );
+ if ( RO_ArrayMakeCurrent( VTXPTRS_DO_ITER_4, gl_array_vtxs ) ) {
+ glVertexPointer( 3, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->x );
+ glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( GLVertex3 ), &gl_array_vtxs->r );
+ glTexCoordPointer( 4, GL_FLOAT, sizeof( GLVertex3 ), &gl_array_vtxs->s );
+ }
+ break;
+ }
+}
+
+
+// lock (specify and convert) array of 2-D iterated vertices ------------------
+//
+void D_LockIterArray2( IterArray2 *itarray, dword first, dword count )
+{
+ //NOTE:
+ // on the first array lock (itarray != NULL) the entire
+ // vertex array will be processed (i.e. converted).
+ // then, only the subrange [first,first+count-1] will be
+ // locked in the gl.
+ // subsequent calls with (itarray == NULL) may follow to
+ // gl-lock different subranges. also, on these calls the
+ // following fields of the IterArray2 are allowed to be
+ // modified to render using a different rasterizer state:
+ // - IterArray2::itertype
+ // - IterArray2::raststate
+ // - IterArray2::rastmask
+ // - IterArray2::texmap
+
+ // array must not be already locked if new array
+ ASSERT( ( gl_array_current == NULL ) || ( itarray == NULL ) );
+ if ( gl_array_current != NULL ) {
+ if ( itarray != NULL ) {
+ // full unlock for release-safety
+ D_UnlockIterArray();
+ }
+ }
+
+ // itarray may be NULL to reuse last
+ int newarray = ( itarray != NULL );
+ if ( newarray ) {
+ gl_array_current = (IterArray3 *) itarray;
+ } else {
+ itarray = (IterArray2 *) gl_array_current;
+ }
+
+ ASSERT( itarray != NULL );
+ ASSERT( first < (dword)itarray->NumVerts );
+ ASSERT( first + count <= (dword)itarray->NumVerts );
+
+ // select texture
+ GLTexInfo *texinfo = NULL;
+ if ( itarray->arrayinfo & ITERARRAY_USE_TEXTURE ) {
+
+ ASSERT( ITERPRIM_TEXTURED( itarray ) );
+ texinfo = &gl_array_texinfo;
+
+ // fetch texture map
+ TextureMap *texmap = itarray->texmap;
+ ASSERT( texmap != NULL );
+
+ // fill texinfo structure and determine coscale/aratio
+ RO_TextureMap2GLTexInfo( texinfo, texmap );
+
+ // also select source if there will only be one texture
+ if ( itarray->arrayinfo & ITERARRAY_GLOBAL_TEXTURE ) {
+
+ // enforce texel source
+ RO_SelectTexelSource( texinfo );
+ }
+ }
+
+ // setup array on first lock
+ if ( newarray ) {
+
+ // convert vertex array into opengl format
+ DO_PrepVertices2( itarray->flags, itarray->Vtxs, itarray->NumVerts, texinfo );
+
+ // specify gl arrays
+ DO_PrepArrays( itarray->arrayinfo );
+
+ // save zcmp and zwrite state
+ gl_array_zcmpstate = RO_DepthCmpEnabled();
+ gl_array_zwritestate = RO_DepthWriteEnabled();
+ }
+
+ // configure rasterizer
+ RO_InitRasterizerState( itarray->itertype, itarray->raststate, itarray->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // remember locked range
+ gl_lockrange_base = first;
+ gl_lockrange_beyond = first + count;
+}
+
+
+// lock (specify and convert) array of 3-D iterated vertices ------------------
+//
+void D_LockIterArray3( IterArray3 *itarray, dword first, dword count )
+{
+ //NOTE:
+ // on the first array lock (itarray != NULL) the entire
+ // vertex array will be processed (i.e. converted).
+ // then, only the subrange [first,first+count-1] will be
+ // locked in the gl.
+ // subsequent calls with (itarray == NULL) may follow to
+ // gl-lock different subranges. also, on these calls the
+ // following fields of the IterArray3 are allowed to be
+ // modified to render using a different rasterizer state:
+ // - IterArray3::itertype
+ // - IterArray3::raststate
+ // - IterArray3::rastmask
+ // - IterArray3::texmap
+
+ // array must not be already locked if new array
+ ASSERT( ( gl_array_current == NULL ) || ( itarray == NULL ) );
+ if ( gl_array_current != NULL ) {
+ if ( itarray != NULL ) {
+ // full unlock for release-safety
+ D_UnlockIterArray();
+ }
+ }
+
+ // itarray may be NULL to reuse last
+ int newarray = ( itarray != NULL );
+ if ( newarray ) {
+ gl_array_current = itarray;
+ } else {
+ itarray = gl_array_current;
+ }
+
+ ASSERT( itarray != NULL );
+ ASSERT( first < (dword)itarray->NumVerts );
+ ASSERT( first + count <= (dword)itarray->NumVerts );
+
+ // select texture
+ GLTexInfo *texinfo = NULL;
+ if ( itarray->arrayinfo & ITERARRAY_USE_TEXTURE ) {
+
+ ASSERT( ITERPRIM_TEXTURED( itarray ) );
+ texinfo = &gl_array_texinfo;
+
+ // fetch texture map
+ TextureMap *texmap = itarray->texmap;
+ ASSERT( texmap != NULL );
+
+ // fill texinfo structure and determine coscale/aratio
+ RO_TextureMap2GLTexInfo( texinfo, texmap );
+
+ // also select source if there will only be one texture
+ if ( itarray->arrayinfo & ITERARRAY_GLOBAL_TEXTURE ) {
+
+ // enforce texel source
+ RO_SelectTexelSource( texinfo );
+ }
+ }
+
+ // setup array on first lock
+ if ( newarray ) {
+
+ // project and convert vertices
+// DO_PrepVertices3( itarray->flags, itarray->Vtxs, itarray->NumVerts, texinfo );
+
+ // use gl projection matrix
+ DO_PrepProjection( itarray->flags, itarray->Vtxs, itarray->NumVerts, texinfo );
+
+ // specify gl arrays
+ DO_PrepArrays( itarray->arrayinfo );
+
+ // save zcmp and zwrite state
+ gl_array_zcmpstate = RO_DepthCmpEnabled();
+ gl_array_zwritestate = RO_DepthWriteEnabled();
+ }
+
+ // configure rasterizer
+ RO_InitRasterizerState( itarray->itertype, itarray->raststate, itarray->rastmask );
+ RO_TextureCombineState( texcomb_decal );
+
+ // remember locked range
+ gl_lockrange_base = first;
+ gl_lockrange_beyond = first + count;
+}
+
+
+// unlock (free) array of iterated vertices -----------------------------------
+//
+void D_UnlockIterArray()
+{
+ // array must be locked
+ ASSERT( gl_array_current != NULL );
+
+ if ( gl_array_current != NULL ) {
+
+ IterArray3 *itarray = gl_array_current;
+ gl_array_current = NULL;
+
+ // disable gl arrays
+// RO_ClientState( VTXARRAY_NONE );
+
+ // free intermediate storage
+ DO_KillTemporaries();
+
+ // restore gl projection matrix
+ DO_KillProjection();
+
+ // set rasterizer state to default
+ RO_DefaultRasterizerState();
+
+ // restore zcmp and zwrite state
+ RO_RestoreDepthState( gl_array_zcmpstate, gl_array_zwritestate );
+ }
+}
+
+
+// convert mode spec (ITERMODE_xx) into GL_xx mode spec -----------------------
+//
+static GLenum gl_array_modes[] = {
+
+ GL_TRIANGLES, // ITERARRAY_MODE_TRIANGLES
+ GL_TRIANGLE_STRIP, // ITERARRAY_MODE_TRISTRIP
+ GL_TRIANGLE_FAN, // ITERARRAY_MODE_TRIFAN
+ GL_QUADS, // ITERARRAY_MODE_QUADS
+ GL_QUAD_STRIP, // ITERARRAY_MODE_QUADSTRIP
+};
+
+
+// draw vertex array using iterated vertex attributes -------------------------
+//
+void D_DrawIterArray( dword mode, dword first, dword count, dword cullmask )
+{
+ IterArray3 *itarray = gl_array_current;
+ ASSERT( itarray != NULL );
+
+ ASSERT( mode < ITERARRAY_MODE_NUM_MODES );
+ ASSERT( first >= gl_lockrange_base );
+ ASSERT( first + count <= gl_lockrange_beyond );
+
+ // select another texture if last cannot be safely reused
+ if ( itarray->arrayinfo & ITERARRAY_USE_TEXTURE ) {
+ ASSERT( itarray->texmap != NULL );
+ if ( ( itarray->arrayinfo & ITERARRAY_GLOBAL_TEXTURE ) == 0 ) {
+ DO_SelectTexture( itarray->texmap, &gl_array_texinfo );
+ }
+ }
+
+ // determine gl mode
+ ASSERT( CALC_NUM_ARRAY_ENTRIES( gl_array_modes ) ==
+ ITERARRAY_MODE_NUM_MODES );
+ GLenum glmode = gl_array_modes[ mode ];
+
+ // draw linear array subrange
+ glDrawArrays( glmode, first, count );
+}
+
+
+// draw vertex array with indexes using iterated vertex attributes ------------
+//
+void D_DrawIterArrayIndexed( dword mode, dword count, dword *indexes, dword cullmask )
+{
+ ASSERT( indexes != NULL );
+
+ IterArray3 *itarray = gl_array_current;
+ ASSERT( itarray != NULL );
+
+ ASSERT( mode < ITERARRAY_MODE_NUM_MODES );
+
+ // select another texture if last cannot be safely reused
+ if ( itarray->arrayinfo & ITERARRAY_USE_TEXTURE ) {
+ ASSERT( itarray->texmap != NULL );
+ if ( ( itarray->arrayinfo & ITERARRAY_GLOBAL_TEXTURE ) == 0 ) {
+ DO_SelectTexture( itarray->texmap, &gl_array_texinfo );
+ }
+ }
+
+ // determine gl mode
+ ASSERT( CALC_NUM_ARRAY_ENTRIES( gl_array_modes ) ==
+ ITERARRAY_MODE_NUM_MODES );
+ GLenum glmode = gl_array_modes[ mode ];
+
+ // draw indexed array elements
+ glDrawElements( glmode, count, GL_UNSIGNED_INT, indexes );
+}
+
+
+