Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

faces.c (18756B)


      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 // faces.c
     23 
     24 #include "qbsp.h"
     25 #include "l_mem.h"
     26 
     27 /*
     28 
     29   some faces will be removed before saving, but still form nodes:
     30 
     31   the insides of sky volumes
     32   meeting planes of different water current volumes
     33 
     34 */
     35 
     36 // undefine for dumb linear searches
     37 #define	USE_HASHING
     38 
     39 #define	INTEGRAL_EPSILON	0.01
     40 #define	POINT_EPSILON		0.5
     41 #define	OFF_EPSILON			0.5
     42 
     43 int	c_merge;
     44 int	c_subdivide;
     45 
     46 int	c_totalverts;
     47 int	c_uniqueverts;
     48 int	c_degenerate;
     49 int	c_tjunctions;
     50 int	c_faceoverflows;
     51 int	c_facecollapse;
     52 int	c_badstartverts;
     53 
     54 #define	MAX_SUPERVERTS	512
     55 int	superverts[MAX_SUPERVERTS];
     56 int	numsuperverts;
     57 
     58 face_t		*edgefaces[MAX_MAP_EDGES][2];
     59 int		firstmodeledge = 1;
     60 int		firstmodelface;
     61 
     62 int	c_tryedges;
     63 
     64 vec3_t	edge_dir;
     65 vec3_t	edge_start;
     66 vec_t	edge_len;
     67 
     68 int		num_edge_verts;
     69 int		edge_verts[MAX_MAP_VERTS];
     70 
     71 face_t *NewFaceFromFace (face_t *f);
     72 
     73 //===========================================================================
     74 
     75 typedef struct hashvert_s
     76 {
     77 	struct hashvert_s	*next;
     78 	int		num;
     79 } hashvert_t;
     80 
     81 
     82 #define	HASH_SIZE	64
     83 
     84 
     85 int	vertexchain[MAX_MAP_VERTS];		// the next vertex in a hash chain
     86 int	hashverts[HASH_SIZE*HASH_SIZE];	// a vertex number, or 0 for no verts
     87 
     88 face_t		*edgefaces[MAX_MAP_EDGES][2];
     89 
     90 //============================================================================
     91 
     92 
     93 unsigned HashVec (vec3_t vec)
     94 {
     95 	int			x, y;
     96 
     97 	x = (4096 + (int)(vec[0]+0.5)) >> 7;
     98 	y = (4096 + (int)(vec[1]+0.5)) >> 7;
     99 
    100 	if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
    101 		Error ("HashVec: point outside valid range");
    102 	
    103 	return y*HASH_SIZE + x;
    104 }
    105 
    106 #ifdef USE_HASHING
    107 /*
    108 =============
    109 GetVertex
    110 
    111 Uses hashing
    112 =============
    113 */
    114 int	GetVertexnum (vec3_t in)
    115 {
    116 	int			h;
    117 	int			i;
    118 	float		*p;
    119 	vec3_t		vert;
    120 	int			vnum;
    121 
    122 	c_totalverts++;
    123 
    124 	for (i=0 ; i<3 ; i++)
    125 	{
    126 		if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
    127 			vert[i] = Q_rint(in[i]);
    128 		else
    129 			vert[i] = in[i];
    130 	}
    131 	
    132 	h = HashVec (vert);
    133 	
    134 	for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
    135 	{
    136 		p = dvertexes[vnum].point;
    137 		if ( fabs(p[0]-vert[0])<POINT_EPSILON
    138 		&& fabs(p[1]-vert[1])<POINT_EPSILON
    139 		&& fabs(p[2]-vert[2])<POINT_EPSILON )
    140 			return vnum;
    141 	}
    142 	
    143 // emit a vertex
    144 	if (numvertexes == MAX_MAP_VERTS)
    145 		Error ("numvertexes == MAX_MAP_VERTS");
    146 
    147 	dvertexes[numvertexes].point[0] = vert[0];
    148 	dvertexes[numvertexes].point[1] = vert[1];
    149 	dvertexes[numvertexes].point[2] = vert[2];
    150 
    151 	vertexchain[numvertexes] = hashverts[h];
    152 	hashverts[h] = numvertexes;
    153 
    154 	c_uniqueverts++;
    155 
    156 	numvertexes++;
    157 		
    158 	return numvertexes-1;
    159 }
    160 #else
    161 /*
    162 ==================
    163 GetVertexnum
    164 
    165 Dumb linear search
    166 ==================
    167 */
    168 int	GetVertexnum (vec3_t v)
    169 {
    170 	int			i, j;
    171 	dvertex_t	*dv;
    172 	vec_t		d;
    173 
    174 	c_totalverts++;
    175 
    176 	// make really close values exactly integral
    177 	for (i=0 ; i<3 ; i++)
    178 	{
    179 		if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
    180 			v[i] = (int)(v[i]+0.5);
    181 		if (v[i] < -4096 || v[i] > 4096)
    182 			Error ("GetVertexnum: outside +/- 4096");
    183 	}
    184 
    185 	// search for an existing vertex match
    186 	for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
    187 	{
    188 		for (j=0 ; j<3 ; j++)
    189 		{
    190 			d = v[j] - dv->point[j];
    191 			if ( d > POINT_EPSILON || d < -POINT_EPSILON)
    192 				break;
    193 		}
    194 		if (j == 3)
    195 			return i;		// a match
    196 	}
    197 
    198 	// new point
    199 	if (numvertexes == MAX_MAP_VERTS)
    200 		Error ("MAX_MAP_VERTS");
    201 	VectorCopy (v, dv->point);
    202 	numvertexes++;
    203 	c_uniqueverts++;
    204 
    205 	return numvertexes-1;
    206 }
    207 #endif
    208 
    209 
    210 /*
    211 ==================
    212 FaceFromSuperverts
    213 
    214 The faces vertexes have been added to the superverts[] array,
    215 and there may be more there than can be held in a face (MAXEDGES).
    216 
    217 If less, the faces vertexnums[] will be filled in, otherwise
    218 face will reference a tree of split[] faces until all of the
    219 vertexnums can be added.
    220 
    221 superverts[base] will become face->vertexnums[0], and the others
    222 will be circularly filled in.
    223 ==================
    224 */
    225 void FaceFromSuperverts (node_t *node, face_t *f, int base)
    226 {
    227 	face_t	*newf;
    228 	int		remaining;
    229 	int		i;
    230 
    231 	remaining = numsuperverts;
    232 	while (remaining > MAXEDGES)
    233 	{	// must split into two faces, because of vertex overload
    234 		c_faceoverflows++;
    235 
    236 		newf = f->split[0] = NewFaceFromFace (f);
    237 		newf = f->split[0];
    238 		newf->next = node->faces;
    239 		node->faces = newf;
    240 
    241 		newf->numpoints = MAXEDGES;
    242 		for (i=0 ; i<MAXEDGES ; i++)
    243 			newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
    244 
    245 		f->split[1] = NewFaceFromFace (f);
    246 		f = f->split[1];
    247 		f->next = node->faces;
    248 		node->faces = f;
    249 
    250 		remaining -= (MAXEDGES-2);
    251 		base = (base+MAXEDGES-1)%numsuperverts;
    252 	}
    253 
    254 	// copy the vertexes back to the face
    255 	f->numpoints = remaining;
    256 	for (i=0 ; i<remaining ; i++)
    257 		f->vertexnums[i] = superverts[(i+base)%numsuperverts];
    258 }
    259 
    260 
    261 /*
    262 ==================
    263 EmitFaceVertexes
    264 ==================
    265 */
    266 void EmitFaceVertexes (node_t *node, face_t *f)
    267 {
    268 	winding_t	*w;
    269 	int			i;
    270 
    271 	if (f->merged || f->split[0] || f->split[1])
    272 		return;
    273 
    274 	w = f->w;
    275 	for (i=0 ; i<w->numpoints ; i++)
    276 	{
    277 		if (noweld)
    278 		{	// make every point unique
    279 			if (numvertexes == MAX_MAP_VERTS)
    280 				Error ("MAX_MAP_VERTS");
    281 			superverts[i] = numvertexes;
    282 			VectorCopy (w->p[i], dvertexes[numvertexes].point);
    283 			numvertexes++;
    284 			c_uniqueverts++;
    285 			c_totalverts++;
    286 		}
    287 		else
    288 			superverts[i] = GetVertexnum (w->p[i]);
    289 	}
    290 	numsuperverts = w->numpoints;
    291 
    292 	// this may fragment the face if > MAXEDGES
    293 	FaceFromSuperverts (node, f, 0);
    294 }
    295 
    296 /*
    297 ==================
    298 EmitVertexes_r
    299 ==================
    300 */
    301 void EmitVertexes_r (node_t *node)
    302 {
    303 	int		i;
    304 	face_t	*f;
    305 
    306 	if (node->planenum == PLANENUM_LEAF)
    307 		return;
    308 
    309 	for (f=node->faces ; f ; f=f->next)
    310 	{
    311 		EmitFaceVertexes (node, f);
    312 	}
    313 
    314 	for (i=0 ; i<2 ; i++)
    315 		EmitVertexes_r (node->children[i]);
    316 }
    317 
    318 
    319 #ifdef USE_HASHING
    320 /*
    321 ==========
    322 FindEdgeVerts
    323 
    324 Uses the hash tables to cut down to a small number
    325 ==========
    326 */
    327 void FindEdgeVerts (vec3_t v1, vec3_t v2)
    328 {
    329 	int		x1, x2, y1, y2, t;
    330 	int		x, y;
    331 	int		vnum;
    332 
    333 #if 0
    334 {
    335 	int		i;
    336 	num_edge_verts = numvertexes-1;
    337 	for (i=0 ; i<numvertexes-1 ; i++)
    338 		edge_verts[i] = i+1;
    339 }
    340 #endif
    341 
    342 	x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
    343 	y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
    344 	x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
    345 	y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
    346 
    347 	if (x1 > x2)
    348 	{
    349 		t = x1;
    350 		x1 = x2;
    351 		x2 = t;
    352 	}
    353 	if (y1 > y2)
    354 	{
    355 		t = y1;
    356 		y1 = y2;
    357 		y2 = t;
    358 	}
    359 #if 0
    360 	x1--;
    361 	x2++;
    362 	y1--;
    363 	y2++;
    364 	if (x1 < 0)
    365 		x1 = 0;
    366 	if (x2 >= HASH_SIZE)
    367 		x2 = HASH_SIZE;
    368 	if (y1 < 0)
    369 		y1 = 0;
    370 	if (y2 >= HASH_SIZE)
    371 		y2 = HASH_SIZE;
    372 #endif
    373 	num_edge_verts = 0;
    374 	for (x=x1 ; x <= x2 ; x++)
    375 	{
    376 		for (y=y1 ; y <= y2 ; y++)
    377 		{
    378 			for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
    379 			{
    380 				edge_verts[num_edge_verts++] = vnum;
    381 			}
    382 		}
    383 	}
    384 }
    385 
    386 #else
    387 /*
    388 ==========
    389 FindEdgeVerts
    390 
    391 Forced a dumb check of everything
    392 ==========
    393 */
    394 void FindEdgeVerts (vec3_t v1, vec3_t v2)
    395 {
    396 	int		i;
    397 
    398 	num_edge_verts = numvertexes-1;
    399 	for (i=0 ; i<num_edge_verts ; i++)
    400 		edge_verts[i] = i+1;
    401 }
    402 #endif
    403 
    404 /*
    405 ==========
    406 TestEdge
    407 
    408 Can be recursively reentered
    409 ==========
    410 */
    411 void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
    412 {
    413 	int		j, k;
    414 	vec_t	dist;
    415 	vec3_t	delta;
    416 	vec3_t	exact;
    417 	vec3_t	off;
    418 	vec_t	error;
    419 	vec3_t	p;
    420 
    421 	if (p1 == p2)
    422 	{
    423 		c_degenerate++;
    424 		return;		// degenerate edge
    425 	}
    426 
    427 	for (k=startvert ; k<num_edge_verts ; k++)
    428 	{
    429 		j = edge_verts[k];
    430 		if (j==p1 || j == p2)
    431 			continue;
    432 
    433 		VectorCopy (dvertexes[j].point, p);
    434 
    435 		VectorSubtract (p, edge_start, delta);
    436 		dist = DotProduct (delta, edge_dir);
    437 		if (dist <=start || dist >= end)
    438 			continue;		// off an end
    439 		VectorMA (edge_start, dist, edge_dir, exact);
    440 		VectorSubtract (p, exact, off);
    441 		error = VectorLength (off);
    442 
    443 		if (fabs(error) > OFF_EPSILON)
    444 			continue;		// not on the edge
    445 
    446 		// break the edge
    447 		c_tjunctions++;
    448 		TestEdge (start, dist, p1, j, k+1);
    449 		TestEdge (dist, end, j, p2, k+1);
    450 		return;
    451 	}
    452 
    453 	// the edge p1 to p2 is now free of tjunctions
    454 	if (numsuperverts >= MAX_SUPERVERTS)
    455 		Error ("MAX_SUPERVERTS");
    456 	superverts[numsuperverts] = p1;
    457 	numsuperverts++;
    458 }
    459 
    460 /*
    461 ==================
    462 FixFaceEdges
    463 
    464 ==================
    465 */
    466 void FixFaceEdges (node_t *node, face_t *f)
    467 {
    468 	int		p1, p2;
    469 	int		i;
    470 	vec3_t	e2;
    471 	vec_t	len;
    472 	int		count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
    473 	int		base;
    474 
    475 	if (f->merged || f->split[0] || f->split[1])
    476 		return;
    477 
    478 	numsuperverts = 0;
    479 
    480 	for (i=0 ; i<f->numpoints ; i++)
    481 	{
    482 		p1 = f->vertexnums[i];
    483 		p2 = f->vertexnums[(i+1)%f->numpoints];
    484 
    485 		VectorCopy (dvertexes[p1].point, edge_start);
    486 		VectorCopy (dvertexes[p2].point, e2);
    487 
    488 		FindEdgeVerts (edge_start, e2);
    489 
    490 		VectorSubtract (e2, edge_start, edge_dir);
    491 		len = VectorNormalize(edge_dir);
    492 
    493 		start[i] = numsuperverts;
    494 		TestEdge (0, len, p1, p2, 0);
    495 
    496 		count[i] = numsuperverts - start[i];
    497 	}
    498 
    499 	if (numsuperverts < 3)
    500 	{	// entire face collapsed
    501 		f->numpoints = 0;
    502 		c_facecollapse++;
    503 		return;
    504 	}
    505 
    506 	// we want to pick a vertex that doesn't have tjunctions
    507 	// on either side, which can cause artifacts on trifans,
    508 	// especially underwater
    509 	for (i=0 ; i<f->numpoints ; i++)
    510 	{
    511 		if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
    512 			break;
    513 	}
    514 	if (i == f->numpoints)
    515 	{
    516 		f->badstartvert = true;
    517 		c_badstartverts++;
    518 		base = 0;
    519 	}
    520 	else
    521 	{	// rotate the vertex order
    522 		base = start[i];
    523 	}
    524 
    525 	// this may fragment the face if > MAXEDGES
    526 	FaceFromSuperverts (node, f, base);
    527 }
    528 
    529 /*
    530 ==================
    531 FixEdges_r
    532 ==================
    533 */
    534 void FixEdges_r (node_t *node)
    535 {
    536 	int		i;
    537 	face_t	*f;
    538 
    539 	if (node->planenum == PLANENUM_LEAF)
    540 		return;
    541 
    542 	for (f=node->faces ; f ; f=f->next)
    543 		FixFaceEdges (node, f);
    544 
    545 	for (i=0 ; i<2 ; i++)
    546 		FixEdges_r (node->children[i]);
    547 }
    548 
    549 /*
    550 ===========
    551 FixTjuncs
    552 
    553 ===========
    554 */
    555 void FixTjuncs (node_t *headnode)
    556 {
    557 	// snap and merge all vertexes
    558 	qprintf ("---- snap verts ----\n");
    559 	memset (hashverts, 0, sizeof(hashverts));
    560 	c_totalverts = 0;
    561 	c_uniqueverts = 0;
    562 	c_faceoverflows = 0;
    563 	EmitVertexes_r (headnode);
    564 	qprintf ("%i unique from %i\n", c_uniqueverts, c_totalverts);
    565 
    566 	// break edges on tjunctions
    567 	qprintf ("---- tjunc ----\n");
    568 	c_tryedges = 0;
    569 	c_degenerate = 0;
    570 	c_facecollapse = 0;
    571 	c_tjunctions = 0;
    572 	if (!notjunc)
    573 		FixEdges_r (headnode);
    574 	qprintf ("%5i edges degenerated\n", c_degenerate);
    575 	qprintf ("%5i faces degenerated\n", c_facecollapse);
    576 	qprintf ("%5i edges added by tjunctions\n", c_tjunctions);
    577 	qprintf ("%5i faces added by tjunctions\n", c_faceoverflows);
    578 	qprintf ("%5i bad start verts\n", c_badstartverts);
    579 }
    580 
    581 
    582 //========================================================
    583 
    584 int		c_faces;
    585 
    586 face_t	*AllocFace (void)
    587 {
    588 	face_t	*f;
    589 
    590 	f = GetMemory(sizeof(*f));
    591 	memset (f, 0, sizeof(*f));
    592 	c_faces++;
    593 
    594 	return f;
    595 }
    596 
    597 face_t *NewFaceFromFace (face_t *f)
    598 {
    599 	face_t	*newf;
    600 
    601 	newf = AllocFace ();
    602 	*newf = *f;
    603 	newf->merged = NULL;
    604 	newf->split[0] = newf->split[1] = NULL;
    605 	newf->w = NULL;
    606 	return newf;
    607 }
    608 
    609 void FreeFace (face_t *f)
    610 {
    611 	if (f->w)
    612 		FreeWinding (f->w);
    613 	FreeMemory(f);
    614 	c_faces--;
    615 }
    616 
    617 //========================================================
    618 
    619 /*
    620 ==================
    621 GetEdge
    622 
    623 Called by writebsp.
    624 Don't allow four way edges
    625 ==================
    626 */
    627 int GetEdge2 (int v1, int v2,  face_t *f)
    628 {
    629 	dedge_t	*edge;
    630 	int		i;
    631 
    632 	c_tryedges++;
    633 
    634 	if (!noshare)
    635 	{
    636 		for (i=firstmodeledge ; i < numedges ; i++)
    637 		{
    638 			edge = &dedges[i];
    639 			if (v1 == edge->v[1] && v2 == edge->v[0]
    640 			&& edgefaces[i][0]->contents == f->contents)
    641 			{
    642 				if (edgefaces[i][1])
    643 	//				printf ("WARNING: multiple backward edge\n");
    644 					continue;
    645 				edgefaces[i][1] = f;
    646 				return -i;
    647 			}
    648 	#if 0
    649 			if (v1 == edge->v[0] && v2 == edge->v[1])
    650 			{
    651 				printf ("WARNING: multiple forward edge\n");
    652 				return i;
    653 			}
    654 	#endif
    655 		}
    656 	}
    657 
    658 // emit an edge
    659 	if (numedges >= MAX_MAP_EDGES)
    660 		Error ("numedges == MAX_MAP_EDGES");
    661 	edge = &dedges[numedges];
    662 	numedges++;
    663 	edge->v[0] = v1;
    664 	edge->v[1] = v2;
    665 	edgefaces[numedges-1][0] = f;
    666 	
    667 	return numedges-1;
    668 }
    669 
    670 /*
    671 ===========================================================================
    672 
    673 FACE MERGING
    674 
    675 ===========================================================================
    676 */
    677 
    678 /*
    679 =============
    680 TryMerge
    681 
    682 If two polygons share a common edge and the edges that meet at the
    683 common points are both inside the other polygons, merge them
    684 
    685 Returns NULL if the faces couldn't be merged, or the new face.
    686 The originals will NOT be freed.
    687 =============
    688 */
    689 face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal)
    690 {
    691 	face_t		*newf;
    692 	winding_t	*nw;
    693 
    694 	if (!f1->w || !f2->w)
    695 		return NULL;
    696 	if (f1->texinfo != f2->texinfo)
    697 		return NULL;
    698 	if (f1->planenum != f2->planenum)	// on front and back sides
    699 		return NULL;
    700 	if (f1->contents != f2->contents)
    701 		return NULL;
    702 		
    703 
    704 	nw = TryMergeWinding (f1->w, f2->w, planenormal);
    705 	if (!nw)
    706 		return NULL;
    707 
    708 	c_merge++;
    709 	newf = NewFaceFromFace (f1);
    710 	newf->w = nw;
    711 
    712 	f1->merged = newf;
    713 	f2->merged = newf;
    714 
    715 	return newf;
    716 }
    717 
    718 /*
    719 ===============
    720 MergeNodeFaces
    721 ===============
    722 */
    723 void MergeNodeFaces (node_t *node)
    724 {
    725 	face_t	*f1, *f2, *end;
    726 	face_t	*merged;
    727 	plane_t	*plane;
    728 
    729 	plane = &mapplanes[node->planenum];
    730 	merged = NULL;
    731 	
    732 	for (f1 = node->faces ; f1 ; f1 = f1->next)
    733 	{
    734 		if (f1->merged || f1->split[0] || f1->split[1])
    735 			continue;
    736 
    737 		for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
    738 		{
    739 			if (f2->merged || f2->split[0] || f2->split[1])
    740 				continue;
    741 
    742 			//IDBUG: always passes the face's node's normal to TryMerge()
    743 			//regardless of which side the face is on. Approximately 50% of
    744 			//the time the face will be on the other side of node, and thus
    745 			//the result of the convex/concave test in TryMergeWinding(),
    746 			//which depends on the normal, is flipped. This causes faces
    747 			//that shouldn't be merged to be merged and faces that
    748 			//should be merged to not be merged. 
    749 			//the following added line fixes this bug
    750 			//thanks to: Alexander Malmberg <alexander@malmberg.org>
    751 			plane = &mapplanes[f1->planenum];
    752 			//
    753 			merged = TryMerge (f1, f2, plane->normal);
    754 			if (!merged)
    755 				continue;
    756 
    757 			// add merged to the end of the node face list 
    758 			// so it will be checked against all the faces again
    759 			for (end = node->faces ; end->next ; end = end->next)
    760 			;
    761 			merged->next = NULL;
    762 			end->next = merged;
    763 			break;
    764 		}
    765 	}
    766 }
    767 
    768 //=====================================================================
    769 
    770 /*
    771 ===============
    772 SubdivideFace
    773 
    774 Chop up faces that are larger than we want in the surface cache
    775 ===============
    776 */
    777 void SubdivideFace (node_t *node, face_t *f)
    778 {
    779 	float		mins, maxs;
    780 	vec_t		v;
    781 	int			axis, i;
    782 	texinfo_t	*tex;
    783 	vec3_t		temp;
    784 	vec_t		dist;
    785 	winding_t	*w, *frontw, *backw;
    786 
    787 	if (f->merged)
    788 		return;
    789 
    790 // special (non-surface cached) faces don't need subdivision
    791 	tex = &texinfo[f->texinfo];
    792 
    793 	if ( tex->flags & (SURF_WARP|SURF_SKY) )
    794 	{
    795 		return;
    796 	}
    797 
    798 	for (axis = 0 ; axis < 2 ; axis++)
    799 	{
    800 		while (1)
    801 		{
    802 			mins = 999999;
    803 			maxs = -999999;
    804 			
    805 			VectorCopy (tex->vecs[axis], temp);
    806 			w = f->w;
    807 			for (i=0 ; i<w->numpoints ; i++)
    808 			{
    809 				v = DotProduct (w->p[i], temp);
    810 				if (v < mins)
    811 					mins = v;
    812 				if (v > maxs)
    813 					maxs = v;
    814 			}
    815 #if 0
    816 			if (maxs - mins <= 0)
    817 				Error ("zero extents");
    818 #endif
    819 			if (axis == 2)
    820 			{	// allow double high walls
    821 				if (maxs - mins <= subdivide_size/* *2 */)
    822 					break;
    823 			}
    824 			else if (maxs - mins <= subdivide_size)
    825 				break;
    826 			
    827 		// split it
    828 			c_subdivide++;
    829 			
    830 			v = VectorNormalize (temp);
    831 
    832 			dist = (mins + subdivide_size - 16)/v;
    833 
    834 			ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
    835 			if (!frontw || !backw)
    836 				Error ("SubdivideFace: didn't split the polygon");
    837 
    838 			f->split[0] = NewFaceFromFace (f);
    839 			f->split[0]->w = frontw;
    840 			f->split[0]->next = node->faces;
    841 			node->faces = f->split[0];
    842 
    843 			f->split[1] = NewFaceFromFace (f);
    844 			f->split[1]->w = backw;
    845 			f->split[1]->next = node->faces;
    846 			node->faces = f->split[1];
    847 
    848 			SubdivideFace (node, f->split[0]);
    849 			SubdivideFace (node, f->split[1]);
    850 			return;
    851 		}
    852 	}
    853 }
    854 
    855 void SubdivideNodeFaces (node_t *node)
    856 {
    857 	face_t	*f;
    858 
    859 	for (f = node->faces ; f ; f=f->next)
    860 	{
    861 		SubdivideFace (node, f);
    862 	}
    863 }
    864 
    865 //===========================================================================
    866 
    867 int	c_nodefaces;
    868 
    869 
    870 /*
    871 ============
    872 FaceFromPortal
    873 
    874 ============
    875 */
    876 face_t *FaceFromPortal (portal_t *p, int pside)
    877 {
    878 	face_t	*f;
    879 	side_t	*side;
    880 
    881 	side = p->side;
    882 	if (!side)
    883 		return NULL;	// portal does not bridge different visible contents
    884 
    885 	f = AllocFace ();
    886 
    887 	f->texinfo = side->texinfo;
    888 	f->planenum = (side->planenum & ~1) | pside;
    889 	f->portal = p;
    890 
    891 	if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
    892 		&& VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
    893 		return NULL;	// don't show insides of windows
    894 
    895 	if (pside)
    896 	{
    897 		f->w = ReverseWinding(p->winding);
    898 		f->contents = p->nodes[1]->contents;
    899 	}
    900 	else
    901 	{
    902 		f->w = CopyWinding(p->winding);
    903 		f->contents = p->nodes[0]->contents;
    904 	}
    905 	return f;
    906 }
    907 
    908 
    909 /*
    910 ===============
    911 MakeFaces_r
    912 
    913 If a portal will make a visible face,
    914 mark the side that originally created it
    915 
    916   solid / empty : solid
    917   solid / water : solid
    918   water / empty : water
    919   water / water : none
    920 ===============
    921 */
    922 void MakeFaces_r (node_t *node)
    923 {
    924 	portal_t	*p;
    925 	int			s;
    926 
    927 	// recurse down to leafs
    928 	if (node->planenum != PLANENUM_LEAF)
    929 	{
    930 		MakeFaces_r (node->children[0]);
    931 		MakeFaces_r (node->children[1]);
    932 
    933 		// merge together all visible faces on the node
    934 		if (!nomerge)
    935 			MergeNodeFaces (node);
    936 		if (!nosubdiv)
    937 			SubdivideNodeFaces (node);
    938 
    939 		return;
    940 	}
    941 
    942 	// solid leafs never have visible faces
    943 	if (node->contents & CONTENTS_SOLID)
    944 		return;
    945 
    946 	// see which portals are valid
    947 	for (p=node->portals ; p ; p = p->next[s])
    948 	{
    949 		s = (p->nodes[1] == node);
    950 
    951 		p->face[s] = FaceFromPortal (p, s);
    952 		if (p->face[s])
    953 		{
    954 			c_nodefaces++;
    955 			p->face[s]->next = p->onnode->faces;
    956 			p->onnode->faces = p->face[s];
    957 		}
    958 	}
    959 }
    960 
    961 /*
    962 ============
    963 MakeFaces
    964 ============
    965 */
    966 void MakeFaces (node_t *node)
    967 {
    968 	qprintf ("--- MakeFaces ---\n");
    969 	c_merge = 0;
    970 	c_subdivide = 0;
    971 	c_nodefaces = 0;
    972 
    973 	MakeFaces_r (node);
    974 
    975 	qprintf ("%5i makefaces\n", c_nodefaces);
    976 	qprintf ("%5i merged\n", c_merge);
    977 	qprintf ("%5i subdivided\n", c_subdivide);
    978 }