1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ----------------------------------------------------------------------------------
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
27 ------------------------------------------------------------------------------- */
41 /* -------------------------------------------------------------------------------
45 ------------------------------------------------------------------------------- */
48 AllocSideRef() - ydnar
49 allocates and assigns a brush side reference
52 sideRef_t *AllocSideRef( side_t *side, sideRef_t *next ){
61 /* allocate and return */
62 sideRef = safe_malloc( sizeof( *sideRef ) );
72 counts the number of brushes in a brush linked list
75 int CountBrushList( brush_t *brushes ){
80 for ( ; brushes != NULL; brushes = brushes->next )
92 brush_t *AllocBrush( int numSides ){
97 /* allocate and clear */
98 if ( numSides <= 0 ) {
99 Error( "AllocBrush called with numsides = %d", numSides );
101 c = (size_t)&( ( (brush_t*) 0 )->sides[ numSides ] );
102 bb = safe_malloc( c );
104 if ( numthreads == 1 ) {
116 frees a single brush and all sides/windings
119 void FreeBrush( brush_t *b ){
124 if ( *( (unsigned int*) b ) == 0xFEFEFEFE ) {
125 Sys_FPrintf( SYS_VRB, "WARNING: Attempt to free an already freed brush!\n" );
129 /* free brush sides */
130 for ( i = 0; i < b->numsides; i++ )
131 if ( b->sides[i].winding != NULL ) {
132 FreeWinding( b->sides[ i ].winding );
135 /* ydnar: overwrite it */
136 memset( b, 0xFE, (size_t)&( ( (brush_t*) 0 )->sides[ b->numsides ] ) );
137 *( (unsigned int*) b ) = 0xFEFEFEFE;
141 if ( numthreads == 1 ) {
150 frees a linked list of brushes
153 void FreeBrushList( brush_t *brushes ){
157 /* walk brush list */
158 for ( ; brushes != NULL; brushes = next )
160 next = brushes->next;
161 FreeBrush( brushes );
169 duplicates the brush, sides, and windings
172 brush_t *CopyBrush( brush_t *brush ){
179 size = (size_t)&( ( (brush_t*) 0 )->sides[ brush->numsides ] );
180 newBrush = AllocBrush( brush->numsides );
181 memcpy( newBrush, brush, size );
183 /* ydnar: nuke linked list */
184 newBrush->next = NULL;
187 for ( i = 0; i < brush->numsides; i++ )
189 if ( brush->sides[ i ].winding != NULL ) {
190 newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
203 sets the mins/maxs based on the windings
204 returns false if the brush doesn't enclose a valid volume
207 qboolean BoundBrush( brush_t *brush ){
212 ClearBounds( brush->mins, brush->maxs );
213 for ( i = 0; i < brush->numsides; i++ )
215 w = brush->sides[ i ].winding;
219 for ( j = 0; j < w->numpoints; j++ )
220 AddPointToBounds( w->p[ j ], brush->mins, brush->maxs );
223 for ( i = 0; i < 3; i++ )
225 if ( brush->mins[ i ] < MIN_WORLD_COORD || brush->maxs[ i ] > MAX_WORLD_COORD || brush->mins[i] >= brush->maxs[ i ] ) {
237 SnapWeldVector() - ydnar
238 welds two vec3_t's into a third, taking into account nearest-to-integer
242 #define SNAP_EPSILON 0.01
244 void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
250 if ( a == NULL || b == NULL || out == NULL ) {
254 /* do each element */
255 for ( i = 0; i < 3; i++ )
257 /* round to integer */
258 ai = Q_rint( a[ i ] );
259 bi = Q_rint( a[ i ] );
261 /* prefer exact integer */
262 if ( ai == a[ i ] ) {
265 else if ( bi == b[ i ] ) {
270 else if ( fabs( ai - a[ i ] ) < fabs( bi < b[ i ] ) ) {
278 outi = Q_rint( out[ i ] );
279 if ( fabs( outi - out[ i ] ) <= SNAP_EPSILON ) {
289 Welds two vectors into a third, taking into account nearest-to-integer
290 instead of averaging.
293 void SnapWeldVectorAccu( vec3_accu_t a, vec3_accu_t b, vec3_accu_t out ){
294 // I'm just preserving what I think was the intended logic of the original
295 // SnapWeldVector(). I'm not actually sure where this function should even
296 // be used. I'd like to know which kinds of problems this function addresses.
298 // TODO: I thought we're snapping all coordinates to nearest 1/8 unit?
299 // So what is natural about snapping to the nearest integer? Maybe we should
300 // be snapping to the nearest 1/8 unit instead?
303 vec_accu_t ai, bi, ad, bd;
305 if ( a == NULL || b == NULL || out == NULL ) {
306 Error( "SnapWeldVectorAccu: NULL argument" );
309 for ( i = 0; i < 3; i++ )
311 ai = Q_rintAccu( a[i] );
312 bi = Q_rintAccu( b[i] );
313 ad = fabs( ai - a[i] );
314 bd = fabs( bi - b[i] );
317 if ( ad < SNAP_EPSILON ) {
320 else{out[i] = a[i]; }
324 if ( bd < SNAP_EPSILON ) {
327 else{out[i] = b[i]; }
336 removes degenerate edges from a winding
337 returns qtrue if the winding is valid
340 #define DEGENERATE_EPSILON 0.1
342 qboolean FixWinding( winding_t *w ){
343 qboolean valid = qtrue;
354 /* check all verts */
355 for ( i = 0; i < w->numpoints; i++ )
357 /* don't remove points if winding is a triangle */
358 if ( w->numpoints == 3 ) {
362 /* get second point index */
363 j = ( i + 1 ) % w->numpoints;
365 /* degenerate edge? */
366 VectorSubtract( w->p[ i ], w->p[ j ], vec );
367 dist = VectorLength( vec );
368 if ( dist < DEGENERATE_EPSILON ) {
370 //Sys_FPrintf( SYS_VRB, "WARNING: Degenerate winding edge found, fixing...\n" );
372 /* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
373 SnapWeldVector( w->p[ i ], w->p[ j ], vec );
374 VectorCopy( vec, w->p[ i ] );
375 //VectorAdd( w->p[ i ], w->p[ j ], vec );
376 //VectorScale( vec, 0.5, w->p[ i ] );
378 /* move the remaining verts */
379 for ( k = i + 2; k < w->numpoints; k++ )
381 VectorCopy( w->p[ k ], w->p[ k - 1 ] );
387 /* one last check and return */
388 if ( w->numpoints < 3 ) {
398 Removes degenerate edges (edges that are too short) from a winding.
399 Returns qtrue if the winding has been altered by this function.
400 Returns qfalse if the winding is untouched by this function.
402 It's advised that you check the winding after this function exits to make
403 sure it still has at least 3 points. If that is not the case, the winding
404 cannot be considered valid. The winding may degenerate to one or two points
405 if the some of the winding's points are close together.
408 qboolean FixWindingAccu( winding_accu_t *w ){
412 qboolean done, altered;
415 Error( "FixWindingAccu: NULL argument" );
422 if ( w->numpoints < 2 ) {
423 break; // Don't remove the only remaining point.
426 for ( i = 0; i < w->numpoints; i++ )
428 j = ( ( ( i + 1 ) == w->numpoints ) ? 0 : ( i + 1 ) );
430 VectorSubtractAccu( w->p[i], w->p[j], vec );
431 dist = VectorLengthAccu( vec );
432 if ( dist < DEGENERATE_EPSILON ) {
433 // TODO: I think the "snap weld vector" was written before
434 // some of the math precision fixes, and its purpose was
435 // probably to address math accuracy issues. We can think
436 // about changing the logic here. Maybe once plane distance
437 // gets 64 bits, we can look at it then.
438 SnapWeldVectorAccu( w->p[i], w->p[j], vec );
439 VectorCopyAccu( vec, w->p[i] );
440 for ( k = j + 1; k < w->numpoints; k++ )
442 VectorCopyAccu( w->p[k], w->p[k - 1] );
446 // The only way to finish off fixing the winding consistently and
447 // accurately is by fixing the winding all over again. For example,
448 // the point at index i and the point at index i-1 could now be
449 // less than the epsilon distance apart. There are too many special
450 // case problems we'd need to handle if we didn't start from the
453 break; // This will cause us to return to the "while" loop.
466 CreateBrushWindings()
467 makes basewindigs for sides and mins/maxs for the brush
468 returns false if the brush doesn't enclose a valid volume
471 qboolean CreateBrushWindings( brush_t *brush ){
473 #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
482 /* walk the list of brush sides */
483 for ( i = 0; i < brush->numsides; i++ )
485 /* get side and plane */
486 side = &brush->sides[ i ];
487 plane = &mapplanes[ side->planenum ];
489 /* make huge winding */
490 #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
491 w = BaseWindingForPlaneAccu( plane->normal, plane->dist );
493 w = BaseWindingForPlane( plane->normal, plane->dist );
496 /* walk the list of brush sides */
497 for ( j = 0; j < brush->numsides && w != NULL; j++ )
502 if ( brush->sides[ j ].planenum == ( brush->sides[ i ].planenum ^ 1 ) ) {
503 continue; /* back side clipaway */
505 if ( brush->sides[ j ].bevel ) {
508 plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
509 #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
510 ChopWindingInPlaceAccu( &w, plane->normal, plane->dist, 0 );
512 ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
515 /* ydnar: fix broken windings that would generate trifans */
516 #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
517 // I think it's better to FixWindingAccu() once after we chop with all planes
518 // so that error isn't multiplied. There is nothing natural about welding
519 // the points unless they are the final endpoints. ChopWindingInPlaceAccu()
520 // is able to handle all kinds of degenerate windings.
526 /* set side winding */
527 #if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
530 if ( w->numpoints < 3 ) {
531 FreeWindingAccu( w );
535 side->winding = ( w ? CopyWindingAccuToRegular( w ) : NULL );
537 FreeWindingAccu( w );
544 /* find brush bounds */
545 return BoundBrush( brush );
555 Creates a new axial brush
558 brush_t *BrushFromBounds( vec3_t mins, vec3_t maxs ){
566 for ( i = 0 ; i < 3 ; i++ )
568 VectorClear( normal );
571 b->sides[i].planenum = FindFloatPlane( normal, dist, 1, (vec3_t*) &maxs );
575 b->sides[3 + i].planenum = FindFloatPlane( normal, dist, 1, (vec3_t*) &mins );
578 CreateBrushWindings( b );
589 vec_t BrushVolume( brush_t *brush ){
593 vec_t d, area, volume;
600 // grab the first valid point as the corner
603 for ( i = 0 ; i < brush->numsides ; i++ )
605 w = brush->sides[i].winding;
613 VectorCopy( w->p[0], corner );
615 // make tetrahedrons to all other faces
618 for ( ; i < brush->numsides ; i++ )
620 w = brush->sides[i].winding;
624 plane = &mapplanes[brush->sides[i].planenum];
625 d = -( DotProduct( corner, plane->normal ) - plane->dist );
626 area = WindingArea( w );
638 writes a map with the split bsp brushes
641 void WriteBSPBrushMap( char *name, brush_t *list ){
649 Sys_Printf( "Writing %s\n", name );
651 /* open the map file */
652 f = fopen( name, "wb" );
654 Error( "Can't write %s\b", name );
657 fprintf( f, "{\n\"classname\" \"worldspawn\"\n" );
659 for ( ; list ; list = list->next )
662 for ( i = 0,s = list->sides ; i < list->numsides ; i++,s++ )
664 // TODO: See if we can use a smaller winding to prevent resolution loss.
665 // Is WriteBSPBrushMap() used only to decompile maps?
666 w = BaseWindingForPlane( mapplanes[s->planenum].normal, mapplanes[s->planenum].dist );
668 fprintf( f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2] );
669 fprintf( f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2] );
670 fprintf( f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2] );
672 fprintf( f, "notexture 0 0 0 1 1\n" );
686 FilterBrushIntoTree_r()
687 adds brush reference to any intersecting bsp leafnode
690 int FilterBrushIntoTree_r( brush_t *b, node_t *node ){
691 brush_t *front, *back;
700 /* add it to the leaf list */
701 if ( node->planenum == PLANENUM_LEAF ) {
702 /* something somewhere is hammering brushlist */
703 b->next = node->brushlist;
706 /* classify the leaf by the structural brush */
709 node->opaque = qtrue;
710 node->areaportal = qfalse;
712 else if ( b->compileFlags & C_AREAPORTAL ) {
713 if ( !node->opaque ) {
714 node->areaportal = qtrue;
722 /* split it by the node plane */
724 SplitBrush( b, node->planenum, &front, &back );
728 c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
729 c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
737 FilterDetailBrushesIntoTree
738 fragment all the detail brushes into the structural leafs
741 void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ){
744 int c_unique, c_clusters;
749 Sys_FPrintf( SYS_VRB, "--- FilterDetailBrushesIntoTree ---\n" );
751 /* walk the list of brushes */
754 for ( b = e->brushes; b; b = b->next )
760 newb = CopyBrush( b );
761 r = FilterBrushIntoTree_r( newb, tree->headnode );
764 /* mark all sides as visible so drawsurfs are created */
766 for ( i = 0; i < b->numsides; i++ )
768 if ( b->sides[ i ].winding ) {
769 b->sides[ i ].visible = qtrue;
775 /* emit some statistics */
776 Sys_FPrintf( SYS_VRB, "%9d detail brushes\n", c_unique );
777 Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
781 =====================
782 FilterStructuralBrushesIntoTree
784 Mark the leafs as opaque and areaportals
785 =====================
787 void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
790 int c_unique, c_clusters;
793 Sys_FPrintf( SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n" );
797 for ( b = e->brushes ; b ; b = b->next ) {
802 newb = CopyBrush( b );
803 r = FilterBrushIntoTree_r( newb, tree->headnode );
806 // mark all sides as visible so drawsurfs are created
808 for ( i = 0 ; i < b->numsides ; i++ ) {
809 if ( b->sides[i].winding ) {
810 b->sides[i].visible = qtrue;
816 /* emit some statistics */
817 Sys_FPrintf( SYS_VRB, "%9d structural brushes\n", c_unique );
818 Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
828 tree_t *AllocTree( void ){
831 tree = safe_malloc( sizeof( *tree ) );
832 memset( tree, 0, sizeof( *tree ) );
833 ClearBounds( tree->mins, tree->maxs );
843 node_t *AllocNode( void ){
846 node = safe_malloc( sizeof( *node ) );
847 memset( node, 0, sizeof( *node ) );
857 Returns true if the winding would be crunched out of
858 existance by the vertex snapping.
861 #define EDGE_LENGTH 0.2
862 qboolean WindingIsTiny( winding_t *w ){
864 if (WindingArea (w) < 1)
874 for ( i = 0 ; i < w->numpoints ; i++ )
876 j = i == w->numpoints - 1 ? 0 : i + 1;
877 VectorSubtract( w->p[j], w->p[i], delta );
878 len = VectorLength( delta );
879 if ( len > EDGE_LENGTH ) {
880 if ( ++edges == 3 ) {
892 Returns true if the winding still has one of the points
893 from basewinding for plane
896 qboolean WindingIsHuge( winding_t *w ){
899 for ( i = 0 ; i < w->numpoints ; i++ )
901 for ( j = 0 ; j < 3 ; j++ )
902 if ( w->p[i][j] <= MIN_WORLD_COORD || w->p[i][j] >= MAX_WORLD_COORD ) {
909 //============================================================
917 int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
925 for ( i = 0 ; i < brush->numsides ; i++ )
927 w = brush->sides[i].winding;
931 for ( j = 0 ; j < w->numpoints ; j++ )
933 d = DotProduct( w->p[j], plane->normal ) - plane->dist;
951 generates two new brushes, leaving the original unchanged
954 void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){
957 winding_t *w, *cw[2], *midwinding;
958 plane_t *plane, *plane2;
960 float d, d_front, d_back;
965 plane = &mapplanes[planenum];
968 d_front = d_back = 0;
969 for ( i = 0 ; i < brush->numsides ; i++ )
971 w = brush->sides[i].winding;
975 for ( j = 0 ; j < w->numpoints ; j++ )
977 d = DotProduct( w->p[j], plane->normal ) - plane->dist;
978 if ( d > 0 && d > d_front ) {
981 if ( d < 0 && d < d_back ) {
987 if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
989 *back = CopyBrush( brush );
993 if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
995 *front = CopyBrush( brush );
999 // create a new winding from the split plane
1000 w = BaseWindingForPlane( plane->normal, plane->dist );
1001 for ( i = 0 ; i < brush->numsides && w ; i++ )
1003 plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
1004 ChopWindingInPlace( &w, plane2->normal, plane2->dist, 0 ); // PLANESIDE_EPSILON);
1007 if ( !w || WindingIsTiny( w ) ) { // the brush isn't really split
1010 side = BrushMostlyOnSide( brush, plane );
1011 if ( side == PSIDE_FRONT ) {
1012 *front = CopyBrush( brush );
1014 if ( side == PSIDE_BACK ) {
1015 *back = CopyBrush( brush );
1020 if ( WindingIsHuge( w ) ) {
1021 Sys_FPrintf( SYS_VRB,"WARNING: huge winding\n" );
1026 // split it for real
1028 for ( i = 0 ; i < 2 ; i++ )
1030 b[i] = AllocBrush( brush->numsides + 1 );
1031 memcpy( b[i], brush, sizeof( brush_t ) - sizeof( brush->sides ) );
1034 b[i]->original = brush->original;
1037 // split all the current windings
1039 for ( i = 0 ; i < brush->numsides ; i++ )
1041 s = &brush->sides[i];
1046 ClipWindingEpsilon( w, plane->normal, plane->dist,
1047 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1] );
1048 for ( j = 0 ; j < 2 ; j++ )
1053 cs = &b[j]->sides[b[j]->numsides];
1056 cs->winding = cw[j];
1061 // see if we have valid polygons on both sides
1062 for ( i = 0 ; i < 2 ; i++ )
1064 if ( b[i]->numsides < 3 || !BoundBrush( b[i] ) ) {
1065 if ( b[i]->numsides >= 3 ) {
1066 Sys_FPrintf( SYS_VRB,"bogus brush after clip\n" );
1073 if ( !( b[0] && b[1] ) ) {
1074 if ( !b[0] && !b[1] ) {
1075 Sys_FPrintf( SYS_VRB,"split removed brush\n" );
1078 Sys_FPrintf( SYS_VRB,"split not on both sides\n" );
1082 *front = CopyBrush( brush );
1086 *back = CopyBrush( brush );
1091 // add the midwinding to both sides
1092 for ( i = 0 ; i < 2 ; i++ )
1094 cs = &b[i]->sides[b[i]->numsides];
1097 cs->planenum = planenum ^ i ^ 1;
1098 cs->shaderInfo = NULL;
1100 cs->winding = CopyWinding( midwinding );
1103 cs->winding = midwinding;
1112 for ( i = 0 ; i < 2 ; i++ )
1114 v1 = BrushVolume( b[i] );
1118 // Sys_FPrintf (SYS_VRB,"tiny volume after clip\n");