Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

surface.c (28518B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "qbsp.h"
     24 
     25 
     26 mapDrawSurface_t	mapDrawSurfs[MAX_MAP_DRAW_SURFS];
     27 int			numMapDrawSurfs;
     28 
     29 /*
     30 =============================================================================
     31 
     32 DRAWSURF CONSTRUCTION
     33 
     34 =============================================================================
     35 */
     36 
     37 /*
     38 =================
     39 AllocDrawSurf
     40 =================
     41 */
     42 mapDrawSurface_t	*AllocDrawSurf( void ) {
     43 	mapDrawSurface_t	*ds;
     44 
     45 	if ( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) {
     46 		Error( "MAX_MAP_DRAW_SURFS");
     47 	}
     48 	ds = &mapDrawSurfs[ numMapDrawSurfs ];
     49 	numMapDrawSurfs++;
     50 
     51 	return ds;
     52 }
     53 
     54 /*
     55 =================
     56 DrawSurfaceForSide
     57 =================
     58 */
     59 #define	SNAP_FLOAT_TO_INT	8
     60 #define	SNAP_INT_TO_FLOAT	(1.0/SNAP_FLOAT_TO_INT)
     61 
     62 mapDrawSurface_t	*DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ) {
     63 	mapDrawSurface_t	*ds;
     64 	int					i, j;
     65 	shaderInfo_t		*si;
     66 	drawVert_t			*dv;
     67 	float				mins[2], maxs[2];
     68 
     69 	// brush primitive :
     70 	// axis base
     71 	vec3_t		texX,texY;
     72 	vec_t		x,y;
     73 
     74 	if ( w->numpoints > 64 ) {
     75 		Error( "DrawSurfaceForSide: w->numpoints = %i", w->numpoints );
     76 	}
     77 
     78 	si = s->shaderInfo;
     79 
     80 	ds = AllocDrawSurf();
     81 
     82 	ds->shaderInfo = si;
     83 	ds->mapBrush = b;
     84 	ds->side = s;
     85 	ds->fogNum = -1;
     86 	ds->numVerts = w->numpoints;
     87 	ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
     88 	memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
     89 
     90 	mins[0] = mins[1] = 99999;
     91 	maxs[0] = maxs[1] = -99999;
     92 
     93 	// compute s/t coordinates from brush primitive texture matrix
     94 	// compute axis base
     95 	ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY );
     96 
     97 	for ( j = 0 ; j < w->numpoints ; j++ ) {
     98 		dv = ds->verts + j;
     99 
    100 		// round the xyz to a given precision
    101 		for ( i = 0 ; i < 3 ; i++ ) {
    102 			dv->xyz[i] = SNAP_INT_TO_FLOAT * floor( w->p[j][i] * SNAP_FLOAT_TO_INT + 0.5 );
    103 		}
    104 	
    105 		if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES)
    106 		{
    107 			// calculate texture s/t
    108 			dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0],	dv->xyz );
    109 			dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1],	dv->xyz );
    110 			dv->st[0] /= si->width;
    111 			dv->st[1] /= si->height;
    112 		} 
    113 		else
    114 		{
    115 			// calculate texture s/t from brush primitive texture matrix
    116 			x = DotProduct( dv->xyz, texX );
    117 			y = DotProduct( dv->xyz, texY );
    118 			dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2];
    119 			dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2];
    120 		}
    121 
    122 		for ( i = 0 ; i < 2 ; i++ ) {
    123 			if ( dv->st[i] < mins[i] ) {
    124 				mins[i] = dv->st[i];
    125 			}
    126 			if ( dv->st[i] > maxs[i] ) {
    127 				maxs[i] = dv->st[i];
    128 			}
    129 		}
    130 
    131 		// copy normal
    132 		VectorCopy ( mapplanes[s->planenum].normal, dv->normal );
    133 	}
    134 
    135 	// adjust the texture coordinates to be as close to 0 as possible
    136 	if ( !si->globalTexture ) {
    137 		mins[0] = floor( mins[0] );
    138 		mins[1] = floor( mins[1] );
    139 		for ( i = 0 ; i < w->numpoints ; i++ ) {
    140 			dv = ds->verts + i;
    141 			dv->st[0] -= mins[0];
    142 			dv->st[1] -= mins[1];
    143 		}
    144 	}
    145 
    146 	return ds;
    147 }
    148 
    149 
    150 //=========================================================================
    151 
    152 
    153 
    154 
    155 typedef struct {
    156 	int				planenum;
    157 	shaderInfo_t	*shaderInfo;
    158 	int				count;
    159 } sideRef_t;
    160 
    161 #define	MAX_SIDE_REFS	MAX_MAP_PLANES
    162 
    163 sideRef_t	sideRefs[MAX_SIDE_REFS];
    164 int			numSideRefs;
    165 
    166 void AddSideRef( side_t *side ) {
    167 	int		i;
    168 
    169 	for ( i = 0 ; i < numSideRefs ; i++ ) {
    170 		if ( side->planenum == sideRefs[i].planenum
    171 			&& side->shaderInfo == sideRefs[i].shaderInfo ) {
    172 			sideRefs[i].count++;
    173 			return;
    174 		}
    175 	}
    176 
    177 	if ( numSideRefs == MAX_SIDE_REFS ) {
    178 		Error( "MAX_SIDE_REFS" );
    179 	}
    180 
    181 	sideRefs[i].planenum = side->planenum;
    182 	sideRefs[i].shaderInfo = side->shaderInfo;
    183 	sideRefs[i].count++;
    184 	numSideRefs++;
    185 }
    186 
    187 
    188 /*
    189 =====================
    190 MergeSides
    191 
    192 =====================
    193 */
    194 void MergeSides( entity_t *e, tree_t *tree ) {
    195 	int				i;
    196 
    197 	qprintf( "----- MergeSides -----\n");
    198 
    199 	for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
    200 //			AddSideRef( side );
    201 	}
    202 
    203 	qprintf( "%5i siderefs\n", numSideRefs );
    204 }
    205 
    206 //=====================================================================
    207 
    208 /*
    209 ===================
    210 SubdivideDrawSurf
    211 ===================
    212 */
    213 void SubdivideDrawSurf( mapDrawSurface_t *ds, winding_t *w, float subdivisions ) {
    214 	int				i;
    215 	int				axis;
    216 	vec3_t			bounds[2];
    217 	const float		epsilon = 0.1;
    218 	int				subFloor, subCeil;
    219 	winding_t		*frontWinding, *backWinding;
    220 	mapDrawSurface_t	*newds;
    221 
    222 	if ( !w ) {
    223 		return;
    224 	}
    225 	if ( w->numpoints < 3 ) {
    226 		Error( "SubdivideDrawSurf: Bad w->numpoints" );
    227 	}
    228 
    229 	ClearBounds( bounds[0], bounds[1] );
    230 	for ( i = 0 ; i < w->numpoints ; i++ ) {
    231 		AddPointToBounds( w->p[i], bounds[0], bounds[1] );
    232 	}
    233 
    234 	for ( axis = 0 ; axis < 3 ; axis++ ) {
    235 		vec3_t planePoint = { 0, 0, 0 };
    236 		vec3_t planeNormal = { 0, 0, 0 };
    237 		float d;
    238 
    239 		subFloor = floor( bounds[0][axis]  / subdivisions ) * subdivisions;
    240 		subCeil = ceil( bounds[1][axis] / subdivisions ) * subdivisions;
    241 
    242 		planePoint[axis] = subFloor + subdivisions;
    243 		planeNormal[axis] = -1;
    244 
    245 		d = DotProduct( planePoint, planeNormal );
    246 
    247 		// subdivide if necessary
    248 		if ( subCeil - subFloor > subdivisions ) {
    249 			// gotta clip polygon into two polygons
    250 			ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding );
    251 
    252 			// the clip may not produce two polygons if it was epsilon close
    253 			if ( !frontWinding ) {
    254 				w = backWinding;
    255 			} else if ( !backWinding ) {
    256 				w = frontWinding;
    257 			} else {
    258 				SubdivideDrawSurf( ds, frontWinding, subdivisions );
    259 				SubdivideDrawSurf( ds, backWinding, subdivisions );
    260 
    261 				return;
    262 			}
    263 		}
    264 	}
    265 
    266 	// emit this polygon
    267 	newds = DrawSurfaceForSide( ds->mapBrush, ds->side, w );
    268 	newds->fogNum = ds->fogNum;
    269 }
    270 
    271 
    272 /*
    273 =====================
    274 SubdivideDrawSurfs
    275 
    276 Chop up surfaces that have subdivision attributes
    277 =====================
    278 */
    279 void SubdivideDrawSurfs( entity_t *e, tree_t *tree ) {
    280 	int				i;
    281 	mapDrawSurface_t	*ds;
    282 	int				numBaseDrawSurfs;
    283 	winding_t		*w;
    284 	float			subdivision;
    285 	shaderInfo_t	*si;
    286 
    287 	qprintf( "----- SubdivideDrawSurfs -----\n");
    288 	numBaseDrawSurfs = numMapDrawSurfs;
    289 	for ( i = e->firstDrawSurf ; i < numBaseDrawSurfs ; i++ ) {
    290 		ds = &mapDrawSurfs[i];
    291 
    292 		// only subdivide brush sides, not patches or misc_models
    293 		if ( !ds->side ) {
    294 			continue;
    295 		}
    296 
    297 		// check subdivision for shader
    298 		si = ds->side->shaderInfo;
    299 		if ( !si ) {
    300 			continue;
    301 		}
    302 
    303 		if (ds->shaderInfo->autosprite || si->autosprite) {
    304 			continue;
    305 		}
    306 
    307 		subdivision = si->subdivisions;
    308 		if ( !subdivision ) {
    309 			continue;
    310 		}
    311 
    312 		w = WindingFromDrawSurf( ds );
    313 		ds->numVerts = 0;		// remove this reference
    314 		SubdivideDrawSurf( ds, w, subdivision );
    315 	}
    316 
    317 }
    318 
    319 
    320 //===================================================================================
    321 
    322 /*
    323 ====================
    324 ClipSideIntoTree_r
    325 
    326 Adds non-opaque leaf fragments to the convex hull
    327 ====================
    328 */
    329 void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) {
    330 	plane_t			*plane;
    331 	winding_t		*front, *back;
    332 
    333 	if ( !w ) {
    334 		return;
    335 	}
    336 
    337 	if ( node->planenum != PLANENUM_LEAF ) {
    338 		if ( side->planenum == node->planenum ) {
    339 			ClipSideIntoTree_r( w, side, node->children[0] );
    340 			return;
    341 		}
    342 		if ( side->planenum == ( node->planenum ^ 1) ) {
    343 			ClipSideIntoTree_r( w, side, node->children[1] );
    344 			return;
    345 		}
    346 
    347 		plane = &mapplanes[ node->planenum ];
    348 		ClipWindingEpsilon ( w, plane->normal, plane->dist,
    349 				ON_EPSILON, &front, &back );
    350 		FreeWinding( w );
    351 
    352 		ClipSideIntoTree_r( front, side, node->children[0] );
    353 		ClipSideIntoTree_r( back, side, node->children[1] );
    354 
    355 		return;
    356 	}
    357 
    358 	// if opaque leaf, don't add
    359 	if ( !node->opaque ) {
    360 		AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal );
    361 	}
    362 
    363 	FreeWinding( w );
    364 	return;
    365 }
    366 
    367 
    368 /*
    369 =====================
    370 ClipSidesIntoTree
    371 
    372 Creates side->visibleHull for all visible sides
    373 
    374 The drawsurf for a side will consist of the convex hull of
    375 all points in non-opaque clusters, which allows overlaps
    376 to be trimmed off automatically.
    377 =====================
    378 */
    379 void ClipSidesIntoTree( entity_t *e, tree_t *tree ) {
    380 	bspbrush_t		*b;
    381 	int				i;
    382 	winding_t		*w;
    383 	side_t			*side, *newSide;
    384 	shaderInfo_t	*si;
    385 
    386 	qprintf( "----- ClipSidesIntoTree -----\n");
    387 
    388 	for ( b = e->brushes ; b ; b = b->next ) {
    389 		for ( i = 0 ; i < b->numsides ; i++ ) {
    390 			side = &b->sides[i];
    391 			if ( !side->winding) {
    392 				continue;
    393 			}
    394 			w = CopyWinding( side->winding );
    395 			side->visibleHull = NULL;
    396 			ClipSideIntoTree_r( w, side, tree->headnode );
    397 
    398 			w = side->visibleHull;
    399 			if ( !w ) {
    400 				continue;
    401 			}
    402 			si = side->shaderInfo;
    403 			if ( !si ) {
    404 				continue;
    405 			}
    406 			// don't create faces for non-visible sides
    407 			if ( si->surfaceFlags & SURF_NODRAW ) {
    408 				continue;
    409 			}
    410 
    411 			// always use the original quad winding for auto sprites
    412 			if ( side->shaderInfo->autosprite ) {
    413 				w = side->winding;
    414 			}
    415 			//
    416 			if ( side->bevel ) {
    417 				Error( "monkey tried to create draw surface for brush bevel" );
    418 			}
    419 			// save this winding as a visible surface
    420 			DrawSurfaceForSide( b, side, w );
    421 
    422 			// make a back side for it if needed
    423 			if ( !(si->contents & CONTENTS_FOG) ) {
    424 				continue;
    425 			}
    426 
    427 			// duplicate the up-facing side
    428 			w = ReverseWinding( w );
    429 		
    430 			newSide = malloc( sizeof( *side ) );
    431 			*newSide = *side;
    432 			newSide->visibleHull = w;
    433 			newSide->planenum ^= 1;
    434 
    435 			// save this winding as a visible surface
    436 			DrawSurfaceForSide( b, newSide, w );
    437 
    438 		}
    439 	}
    440 }
    441 
    442 /*
    443 ===================================================================================
    444 
    445   FILTER REFERENCES DOWN THE TREE
    446 
    447 ===================================================================================
    448 */
    449 
    450 /*
    451 ====================
    452 FilterDrawSurfIntoTree
    453 
    454 Place a reference to the given drawsurf in every leaf it contacts
    455 We assume that the point mesh aproximation to the curve will get a 
    456 reference into all the leafs we need.
    457 ====================
    458 */
    459 int FilterMapDrawSurfIntoTree( vec3_t point, mapDrawSurface_t *ds, node_t *node ) {
    460 	drawSurfRef_t	*dsr;
    461 	float			d;
    462 	plane_t			*plane;
    463 	int				c;
    464 
    465 	if ( node->planenum != PLANENUM_LEAF ) {
    466 		plane = &mapplanes[ node->planenum ];
    467 		d = DotProduct( point, plane->normal ) - plane->dist;
    468 		c = 0;
    469 		if ( d >= -ON_EPSILON ) {
    470 			c += FilterMapDrawSurfIntoTree( point, ds, node->children[0] );
    471 		}
    472 		if ( d <= ON_EPSILON ) {
    473 			c += FilterMapDrawSurfIntoTree( point, ds, node->children[1] );
    474 		}
    475 		return c;
    476 	}
    477 
    478 	// if opaque leaf, don't add
    479 	if ( node->opaque ) {
    480 		return 0;
    481 	}
    482 
    483 	// add the drawsurf if it hasn't been already
    484 	for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) {
    485 		if ( dsr->outputNumber == numDrawSurfaces ) {
    486 			return 0;		// already referenced
    487 		}
    488 	}
    489 
    490 	dsr = malloc( sizeof( *dsr ) );
    491 	dsr->outputNumber = numDrawSurfaces;
    492 	dsr->nextRef = node->drawSurfReferences;
    493 	node->drawSurfReferences = dsr;
    494 	return 1;
    495 }
    496 
    497 /*
    498 ====================
    499 FilterDrawSurfIntoTree_r
    500 
    501 Place a reference to the given drawsurf in every leaf it is in
    502 ====================
    503 */
    504 int FilterMapDrawSurfIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) {
    505 	drawSurfRef_t	*dsr;
    506 	plane_t			*plane;
    507 	int				total;
    508 	winding_t		*front, *back;
    509 
    510 	if ( node->planenum != PLANENUM_LEAF ) {
    511 		plane = &mapplanes[ node->planenum ];
    512 		ClipWindingEpsilon ( w, plane->normal, plane->dist,
    513 				ON_EPSILON, &front, &back );
    514 
    515 		total = 0;
    516 		if ( front ) {
    517 			total += FilterMapDrawSurfIntoTree_r( front, ds, node->children[0] );
    518 		}
    519 		if ( back ) {
    520 			total += FilterMapDrawSurfIntoTree_r( back, ds, node->children[1] );
    521 		}
    522 
    523 		FreeWinding( w );
    524 		return total;
    525 	}
    526 
    527 	// if opaque leaf, don't add
    528 	if ( node->opaque ) {
    529 		return 0;
    530 	}
    531 
    532 	// add the drawsurf if it hasn't been already
    533 	for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) {
    534 		if ( dsr->outputNumber == numDrawSurfaces ) {
    535 			return 0;		// already referenced
    536 		}
    537 	}
    538 
    539 	dsr = malloc( sizeof( *dsr ) );
    540 	dsr->outputNumber = numDrawSurfaces;
    541 	dsr->nextRef = node->drawSurfReferences;
    542 	node->drawSurfReferences = dsr;
    543 	return 1;
    544 }
    545 
    546 /*
    547 ====================
    548 FilterSideIntoTree_r
    549 
    550 Place a reference to the given drawsurf in every leaf it contacts
    551 ====================
    552 */
    553 int FilterSideIntoTree_r( winding_t *w, side_t *side, mapDrawSurface_t *ds, node_t *node ) {
    554 	drawSurfRef_t	*dsr;
    555 	plane_t			*plane;
    556 	winding_t		*front, *back;
    557 	int				total;
    558 
    559 	if ( !w ) {
    560 		return 0;
    561 	}
    562 
    563 	if ( node->planenum != PLANENUM_LEAF ) {
    564 		if ( side->planenum == node->planenum ) {
    565 			return FilterSideIntoTree_r( w, side, ds, node->children[0] );
    566 		}
    567 		if ( side->planenum == ( node->planenum ^ 1) ) {
    568 			return FilterSideIntoTree_r( w, side, ds, node->children[1] );
    569 		}
    570 
    571 		plane = &mapplanes[ node->planenum ];
    572 		ClipWindingEpsilon ( w, plane->normal, plane->dist,
    573 				ON_EPSILON, &front, &back );
    574 
    575 		total = FilterSideIntoTree_r( front, side, ds, node->children[0] );
    576 		total += FilterSideIntoTree_r( back, side, ds, node->children[1] );
    577 
    578 		FreeWinding( w );
    579 		return total;
    580 	}
    581 
    582 	// if opaque leaf, don't add
    583 	if ( node->opaque ) {
    584 		return 0;
    585 	}
    586 
    587 	dsr = malloc( sizeof( *dsr ) );
    588 	dsr->outputNumber = numDrawSurfaces;
    589 	dsr->nextRef = node->drawSurfReferences;
    590 	node->drawSurfReferences = dsr;
    591 
    592 	FreeWinding( w );
    593 	return 1;
    594 }
    595 
    596 
    597 /*
    598 =====================
    599 FilterFaceIntoTree
    600 =====================
    601 */
    602 int	FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) {
    603 	int			l;
    604 	winding_t	*w;
    605 
    606 	w = WindingFromDrawSurf( ds );
    607 	l = FilterSideIntoTree_r( w, ds->side, ds, tree->headnode );
    608 
    609 	return l;
    610 }
    611 
    612 
    613 
    614 /*
    615 =====================
    616 FilterPatchSurfIntoTree
    617 =====================
    618 */
    619 #define	SUBDIVISION_LIMIT		8.0
    620 int FilterPatchSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) {
    621 	int					i, j;
    622 	int					l;
    623 	mesh_t				baseMesh, *subdividedMesh;
    624 	winding_t			*w;
    625 
    626 	baseMesh.width = ds->patchWidth;
    627 	baseMesh.height = ds->patchHeight;
    628 	baseMesh.verts = ds->verts;
    629 	subdividedMesh = SubdivideMesh( baseMesh, SUBDIVISION_LIMIT, 32 );
    630 
    631 	l = 0;
    632 	for (i = 0; i < subdividedMesh->width-1; i++) {
    633 		for (j = 0; j < subdividedMesh->height-1; j++) {
    634 			w = AllocWinding(3);
    635 			VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i].xyz, w->p[0]);
    636 			VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[1]);
    637 			VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]);
    638 			w->numpoints = 3;
    639 			l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode );
    640 			w = AllocWinding(3);
    641 			VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[0]);
    642 			VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i + 1].xyz, w->p[1]);
    643 			VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]);
    644 			w->numpoints = 3;
    645 			l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode );
    646 		}
    647 	}
    648 
    649 	// also use the old point filtering into the tree
    650 	for ( i = 0 ; i < subdividedMesh->width * subdividedMesh->height ; i++ ) {
    651 		l += FilterMapDrawSurfIntoTree( subdividedMesh->verts[i].xyz, ds, tree->headnode );
    652 	}
    653 
    654 	free(subdividedMesh);
    655 
    656 	return l;
    657 }
    658 
    659 
    660 /*
    661 =====================
    662 FilterMiscModelSurfIntoTree
    663 =====================
    664 */
    665 int	FilterMiscModelSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) {
    666 	int			i;
    667 	int			l;
    668 	winding_t *w;
    669 
    670 	l = 0;
    671 	for (i = 0; i < ds->numIndexes-2; i++) {
    672 		w = AllocWinding(3);
    673 		VectorCopy(ds->verts[ds->indexes[i]].xyz, w->p[0]);
    674 		VectorCopy(ds->verts[ds->indexes[i+1]].xyz, w->p[1]);
    675 		VectorCopy(ds->verts[ds->indexes[i+2]].xyz, w->p[2]);
    676 		w->numpoints = 3;
    677 		l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode );
    678 	}
    679 
    680 	// also use the old point filtering into the tree
    681 	for ( i = 0 ; i < ds->numVerts ; i++ ) {
    682 		l += FilterMapDrawSurfIntoTree( ds->verts[i].xyz, ds, tree->headnode );
    683 	}
    684 
    685 	return l;
    686 }
    687 
    688 /*
    689 =====================
    690 FilterFlareSurfIntoTree
    691 =====================
    692 */
    693 int	FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) {
    694 	return FilterMapDrawSurfIntoTree( ds->lightmapOrigin, ds, tree->headnode );
    695 }
    696 
    697 
    698 //======================================================================
    699 
    700 int		c_stripSurfaces, c_fanSurfaces;
    701 
    702 /*
    703 ==================
    704 IsTriangleDegenerate
    705 
    706 Returns qtrue if all three points are collinear or backwards
    707 ===================
    708 */
    709 #define	COLINEAR_AREA	10
    710 static qboolean	IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) {
    711 	vec3_t		v1, v2, v3;
    712 	float		d;
    713 
    714 	VectorSubtract( points[b].xyz, points[a].xyz, v1 );
    715 	VectorSubtract( points[c].xyz, points[a].xyz, v2 );
    716 	CrossProduct( v1, v2, v3 );
    717 	d = VectorLength( v3 );
    718 
    719 	// assume all very small or backwards triangles will cause problems
    720 	if ( d < COLINEAR_AREA ) {
    721 		return qtrue;
    722 	}
    723 
    724 	return qfalse;
    725 }
    726 
    727 /*
    728 ===============
    729 SurfaceAsTriFan
    730 
    731 The surface can't be represented as a single tristrip without
    732 leaving a degenerate triangle (and therefore a crack), so add
    733 a point in the middle and create (points-1) triangles in fan order
    734 ===============
    735 */
    736 static void SurfaceAsTriFan( dsurface_t *ds ) {
    737 	int					i;
    738 	int					colorSum[4];
    739 	drawVert_t			*mid, *v;
    740 
    741 	// create a new point in the center of the face
    742 	if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) {
    743 		Error( "MAX_MAP_DRAW_VERTS" );
    744 	}
    745 	mid = &drawVerts[ numDrawVerts ];
    746 	numDrawVerts++;
    747 
    748 	colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0;
    749 
    750 	v = drawVerts + ds->firstVert;
    751 	for (i = 0 ; i < ds->numVerts ; i++, v++ ) {
    752 		VectorAdd( mid->xyz, v->xyz, mid->xyz );
    753 		mid->st[0] += v->st[0];
    754 		mid->st[1] += v->st[1];
    755 		mid->lightmap[0] += v->lightmap[0];
    756 		mid->lightmap[1] += v->lightmap[1];
    757 
    758 		colorSum[0] += v->color[0];
    759 		colorSum[1] += v->color[1];
    760 		colorSum[2] += v->color[2];
    761 		colorSum[3] += v->color[3];
    762 	}
    763 
    764 	mid->xyz[0] /= ds->numVerts;
    765 	mid->xyz[1] /= ds->numVerts;
    766 	mid->xyz[2] /= ds->numVerts;
    767 
    768 	mid->st[0] /= ds->numVerts;
    769 	mid->st[1] /= ds->numVerts;
    770 
    771 	mid->lightmap[0] /= ds->numVerts;
    772 	mid->lightmap[1] /= ds->numVerts;
    773 
    774 	mid->color[0] = colorSum[0] / ds->numVerts;
    775 	mid->color[1] = colorSum[1] / ds->numVerts;
    776 	mid->color[2] = colorSum[2] / ds->numVerts;
    777 	mid->color[3] = colorSum[3] / ds->numVerts;
    778 
    779 	VectorCopy((drawVerts+ds->firstVert)->normal, mid->normal );
    780 
    781 	// fill in indices in trifan order
    782 	if ( numDrawIndexes + ds->numVerts*3 > MAX_MAP_DRAW_INDEXES ) {
    783 		Error( "MAX_MAP_DRAWINDEXES" );
    784 	}
    785 	ds->firstIndex = numDrawIndexes;
    786 	ds->numIndexes = ds->numVerts*3;
    787 
    788 	//FIXME
    789 	// should be: for ( i = 0 ; i < ds->numVerts ; i++ ) {
    790 	// set a break point and test this in a map
    791 	//for ( i = 0 ; i < ds->numVerts*3 ; i++ ) {
    792 	for ( i = 0 ; i < ds->numVerts ; i++ ) {
    793 		drawIndexes[numDrawIndexes++] = ds->numVerts;
    794 		drawIndexes[numDrawIndexes++] = i;
    795 		drawIndexes[numDrawIndexes++] = (i+1) % ds->numVerts;
    796 	}
    797 
    798 	ds->numVerts++;
    799 }
    800 
    801 
    802 /*
    803 ================
    804 SurfaceAsTristrip
    805 
    806 Try to create indices that make (points-2) triangles in tristrip order
    807 ================
    808 */
    809 #define	MAX_INDICES	1024
    810 static void SurfaceAsTristrip( dsurface_t *ds ) {
    811 	int					i;
    812 	int					rotate;
    813 	int					numIndices;
    814 	int					ni;
    815 	int					a, b, c;
    816 	int					indices[MAX_INDICES];
    817 
    818 	// determine the triangle strip order
    819 	numIndices = ( ds->numVerts - 2 ) * 3;
    820 	if ( numIndices > MAX_INDICES ) {
    821 		Error( "MAX_INDICES exceeded for surface" );
    822 	}
    823 
    824 	// try all possible orderings of the points looking
    825 	// for a strip order that isn't degenerate
    826 	for ( rotate = 0 ; rotate < ds->numVerts ; rotate++ ) {
    827 		for ( ni = 0, i = 0 ; i < ds->numVerts - 2 - i ; i++ ) {
    828 			a = ( ds->numVerts - 1 - i + rotate ) % ds->numVerts;
    829 			b = ( i + rotate ) % ds->numVerts;
    830 			c = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts;
    831 
    832 			if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) {
    833 				break;
    834 			}
    835 			indices[ni++] = a;
    836 			indices[ni++] = b;
    837 			indices[ni++] = c;
    838 
    839 			if ( i + 1 != ds->numVerts - 1 - i ) {
    840 				a = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts;
    841 				b = ( i + rotate ) % ds->numVerts;
    842 				c = ( i + 1 + rotate ) % ds->numVerts;
    843 
    844 				if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) {
    845 					break;
    846 				}
    847 				indices[ni++] = a;
    848 				indices[ni++] = b;
    849 				indices[ni++] = c;
    850 			}
    851 		}
    852 		if ( ni == numIndices ) {
    853 			break;		// got it done without degenerate triangles
    854 		}
    855 	}
    856 
    857 	// if any triangle in the strip is degenerate,
    858 	// render from a centered fan point instead
    859 	if ( ni < numIndices ) {
    860 		c_fanSurfaces++;
    861 		SurfaceAsTriFan( ds );
    862 		return;
    863 	}
    864 
    865 	// a normal tristrip
    866 	c_stripSurfaces++;
    867 
    868 	if ( numDrawIndexes + ni > MAX_MAP_DRAW_INDEXES ) {
    869 		Error( "MAX_MAP_DRAW_INDEXES" );
    870 	}
    871 	ds->firstIndex = numDrawIndexes;
    872 	ds->numIndexes = ni;
    873 
    874 	memcpy( drawIndexes + numDrawIndexes, indices, ni * sizeof(int) );
    875 	numDrawIndexes += ni;
    876 }
    877 
    878 /*
    879 ===============
    880 EmitPlanarSurf
    881 ===============
    882 */
    883 void EmitPlanarSurf( mapDrawSurface_t *ds ) {
    884 	int				j;
    885 	dsurface_t		*out;
    886 	drawVert_t		*outv;
    887 
    888 	if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) {
    889 		Error( "MAX_MAP_DRAW_SURFS" );
    890 	}
    891 	out = &drawSurfaces[ numDrawSurfaces ];
    892 	numDrawSurfaces++;
    893 
    894 	out->surfaceType = MST_PLANAR;
    895 	out->shaderNum = EmitShader( ds->shaderInfo->shader );
    896 	out->firstVert = numDrawVerts;
    897 	out->numVerts = ds->numVerts;
    898 	out->fogNum = ds->fogNum;
    899 	out->lightmapNum = ds->lightmapNum;
    900 	out->lightmapX = ds->lightmapX;
    901 	out->lightmapY = ds->lightmapY;
    902 	out->lightmapWidth = ds->lightmapWidth;
    903 	out->lightmapHeight = ds->lightmapHeight;
    904 
    905 	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
    906 	VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] );
    907 	VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] );
    908 	VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] );
    909 
    910 	for ( j = 0 ; j < ds->numVerts ; j++ ) {
    911 		if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) {
    912 			Error( "MAX_MAP_DRAW_VERTS" );
    913 		}
    914 		outv = &drawVerts[ numDrawVerts ];
    915 		numDrawVerts++;
    916 		memcpy( outv, &ds->verts[ j ], sizeof( *outv ) );
    917 		outv->color[0] = 255;
    918 		outv->color[1] = 255;
    919 		outv->color[2] = 255;
    920 		outv->color[3] = 255;
    921 	}
    922 
    923 	// create the indexes
    924 	SurfaceAsTristrip( out );
    925 }
    926 
    927 
    928 /*
    929 ===============
    930 EmitPatchSurf
    931 ===============
    932 */
    933 void EmitPatchSurf( mapDrawSurface_t *ds ) {
    934 	int				j;
    935 	dsurface_t		*out;
    936 	drawVert_t		*outv;
    937 
    938 	if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) {
    939 		Error( "MAX_MAP_DRAW_SURFS" );
    940 	}
    941 	out = &drawSurfaces[ numDrawSurfaces ];
    942 	numDrawSurfaces++;
    943 
    944 	out->surfaceType = MST_PATCH;
    945 	out->shaderNum = EmitShader( ds->shaderInfo->shader );
    946 	out->firstVert = numDrawVerts;
    947 	out->numVerts = ds->numVerts;
    948 	out->firstIndex = numDrawIndexes;
    949 	out->numIndexes = ds->numIndexes;
    950 	out->patchWidth = ds->patchWidth;
    951 	out->patchHeight = ds->patchHeight;
    952 	out->fogNum = ds->fogNum;
    953 	out->lightmapNum = ds->lightmapNum;
    954 	out->lightmapX = ds->lightmapX;
    955 	out->lightmapY = ds->lightmapY;
    956 	out->lightmapWidth = ds->lightmapWidth;
    957 	out->lightmapHeight = ds->lightmapHeight;
    958 
    959 	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
    960 	VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] );
    961 	VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] );
    962 	VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] );
    963 
    964 	for ( j = 0 ; j < ds->numVerts ; j++ ) {
    965 		if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) {
    966 			Error( "MAX_MAP_DRAW_VERTS" );
    967 		}
    968 		outv = &drawVerts[ numDrawVerts ];
    969 		numDrawVerts++;
    970 		memcpy( outv, &ds->verts[ j ], sizeof( *outv ) );
    971 		outv->color[0] = 255;
    972 		outv->color[1] = 255;
    973 		outv->color[2] = 255;
    974 		outv->color[3] = 255;
    975 	}
    976 
    977 	for ( j = 0 ; j < ds->numIndexes ; j++ ) {
    978 		if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) {
    979 			Error( "MAX_MAP_DRAW_INDEXES" );
    980 		}
    981 		drawIndexes[ numDrawIndexes ] = ds->indexes[ j ];
    982 		numDrawIndexes++;
    983 	}
    984 }
    985 
    986 /*
    987 ===============
    988 EmitFlareSurf
    989 ===============
    990 */
    991 void EmitFlareSurf( mapDrawSurface_t *ds ) {
    992 	dsurface_t		*out;
    993 
    994 	if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) {
    995 		Error( "MAX_MAP_DRAW_SURFS" );
    996 	}
    997 	out = &drawSurfaces[ numDrawSurfaces ];
    998 	numDrawSurfaces++;
    999 
   1000 	out->surfaceType = MST_FLARE;
   1001 	out->shaderNum = EmitShader( ds->shaderInfo->shader );
   1002 	out->fogNum = ds->fogNum;
   1003 
   1004 	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
   1005 	VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] );	// color
   1006 	VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] );
   1007 }
   1008 
   1009 
   1010 /*
   1011 ===============
   1012 EmitModelSurf
   1013 ===============
   1014 */
   1015 void EmitModelSurf( mapDrawSurface_t *ds ) {
   1016 	int				j;
   1017 	dsurface_t		*out;
   1018 	drawVert_t		*outv;
   1019 
   1020 	if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) {
   1021 		Error( "MAX_MAP_DRAW_SURFS" );
   1022 	}
   1023 	out = &drawSurfaces[ numDrawSurfaces ];
   1024 	numDrawSurfaces++;
   1025 
   1026 	out->surfaceType = MST_TRIANGLE_SOUP;
   1027 	out->shaderNum = EmitShader( ds->shaderInfo->shader );
   1028 	out->firstVert = numDrawVerts;
   1029 	out->numVerts = ds->numVerts;
   1030 	out->firstIndex = numDrawIndexes;
   1031 	out->numIndexes = ds->numIndexes;
   1032 	out->patchWidth = ds->patchWidth;
   1033 	out->patchHeight = ds->patchHeight;
   1034 	out->fogNum = ds->fogNum;
   1035 	out->lightmapNum = ds->lightmapNum;
   1036 	out->lightmapX = ds->lightmapX;
   1037 	out->lightmapY = ds->lightmapY;
   1038 	out->lightmapWidth = ds->lightmapWidth;
   1039 	out->lightmapHeight = ds->lightmapHeight;
   1040 
   1041 	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
   1042 	VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] );
   1043 	VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] );
   1044 	VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] );
   1045 
   1046 	for ( j = 0 ; j < ds->numVerts ; j++ ) {
   1047 		if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) {
   1048 			Error( "MAX_MAP_DRAW_VERTS" );
   1049 		}
   1050 		outv = &drawVerts[ numDrawVerts ];
   1051 		numDrawVerts++;
   1052 		memcpy( outv, &ds->verts[ j ], sizeof( *outv ) );
   1053 		outv->color[0] = 255;
   1054 		outv->color[1] = 255;
   1055 		outv->color[2] = 255;
   1056 	}
   1057 
   1058 	for ( j = 0 ; j < ds->numIndexes ; j++ ) {
   1059 		if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) {
   1060 			Error( "MAX_MAP_DRAW_INDEXES" );
   1061 		}
   1062 		drawIndexes[ numDrawIndexes ] = ds->indexes[ j ];
   1063 		numDrawIndexes++;
   1064 	}
   1065 }
   1066 
   1067 //======================================================================
   1068 
   1069 /*
   1070 ==================
   1071 CreateFlareSurface
   1072 
   1073 Light flares from surface lights become 
   1074 ==================
   1075 */
   1076 void CreateFlareSurface( mapDrawSurface_t *faceDs ) {
   1077 	mapDrawSurface_t	*ds;
   1078 	int					i;
   1079 
   1080 	ds = AllocDrawSurf();
   1081 
   1082 	if ( faceDs->shaderInfo->flareShader[0] ) {
   1083 		ds->shaderInfo = ShaderInfoForShader( faceDs->shaderInfo->flareShader );
   1084 	} else {
   1085 		ds->shaderInfo = ShaderInfoForShader( "flareshader" );
   1086 	}
   1087 	ds->flareSurface = qtrue;
   1088 	VectorCopy( faceDs->lightmapVecs[2], ds->lightmapVecs[2] );
   1089 
   1090 	// find midpoint
   1091 	VectorClear( ds->lightmapOrigin );
   1092 	for ( i = 0 ; i < faceDs->numVerts ; i++ ) {
   1093 		VectorAdd( ds->lightmapOrigin, faceDs->verts[i].xyz, ds->lightmapOrigin );
   1094 	}
   1095 	VectorScale( ds->lightmapOrigin, 1.0/faceDs->numVerts, ds->lightmapOrigin );
   1096 
   1097 	VectorMA( ds->lightmapOrigin, 2,  ds->lightmapVecs[2], ds->lightmapOrigin );
   1098 
   1099 	VectorCopy( faceDs->shaderInfo->color, ds->lightmapVecs[0] );
   1100 
   1101 	// FIXME: fog
   1102 }
   1103 
   1104 /*
   1105 =====================
   1106 FilterDrawsurfsIntoTree
   1107 
   1108 Upon completion, all drawsurfs that actually generate a reference
   1109 will have been emited to the bspfile arrays, and the references
   1110 will have valid final indexes
   1111 =====================
   1112 */
   1113 void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ) {
   1114 	int				i;
   1115 	mapDrawSurface_t	*ds;
   1116 	int				refs;
   1117 	int				c_surfs, c_refs;
   1118 
   1119 	qprintf( "----- FilterDrawsurfsIntoTree -----\n");
   1120 
   1121 	c_surfs = 0;
   1122 	c_refs = 0;
   1123 	for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
   1124 		ds = &mapDrawSurfs[i];
   1125 
   1126 		if ( !ds->numVerts && !ds->flareSurface ) {
   1127 			continue;
   1128 		}
   1129 		if ( ds->miscModel ) {
   1130 			refs = FilterMiscModelSurfIntoTree( ds, tree );
   1131 			EmitModelSurf( ds );		
   1132 		} else if ( ds->patch ) {
   1133 			refs = FilterPatchSurfIntoTree( ds, tree );
   1134 			EmitPatchSurf( ds );		
   1135 		} else if ( ds->flareSurface ) {
   1136 			refs = FilterFlareSurfIntoTree( ds, tree );
   1137 			EmitFlareSurf( ds );					
   1138 		} else {
   1139 			refs = FilterFaceIntoTree( ds, tree );
   1140 //			if ( ds->shaderInfo->value >= 1000 ) { // ds->shaderInfo->flareShader[0] ) {
   1141 			if ( ds->shaderInfo->flareShader[0] ) {
   1142 				CreateFlareSurface( ds );
   1143 			}
   1144 			EmitPlanarSurf( ds );		
   1145 		}
   1146 		if ( refs > 0 ) {
   1147 			c_surfs++;
   1148 			c_refs += refs;
   1149 		}
   1150 	}
   1151 	qprintf( "%5i emited drawsurfs\n", c_surfs );
   1152 	qprintf( "%5i references\n", c_refs );
   1153 	qprintf( "%5i stripfaces\n", c_stripSurfaces );
   1154 	qprintf( "%5i fanfaces\n", c_fanSurfaces );
   1155 }
   1156 
   1157 
   1158