From cfeea25febdc2bc06f8257ab47b4a93a35bb4882 Mon Sep 17 00:00:00 2001 From: divverent Date: Sat, 4 Apr 2009 11:56:32 +0000 Subject: [PATCH] new options: -bsp -deep - include detail brushes into BSP tree generation (but at lowest possible priority), but still ignore them for vis -vis -mergeportals - only merge vis portals on the same plane, but don't merge clusters (much faster vis, but only slightly worse - will evaluate later why it's worse vis at all) git-svn-id: svn://svn.icculus.org/netradiant/trunk@244 61c419a2-8eb2-4b30-bcec-8cead039b335 --- tools/quake3/q3map2/bsp.c | 8 ++- tools/quake3/q3map2/facebsp.c | 58 ++++++++++++---- tools/quake3/q3map2/prtfile.c | 122 +++++++++++++++++++++++++++++----- tools/quake3/q3map2/q3map2.h | 9 ++- 4 files changed, 167 insertions(+), 30 deletions(-) diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c index 377ba687..6199d07f 100644 --- a/tools/quake3/q3map2/bsp.c +++ b/tools/quake3/q3map2/bsp.c @@ -847,7 +847,13 @@ int BSPMain( int argc, char **argv ){ Sys_Printf( "Alternate BSP splitting (by 27) enabled\n" ); bspAlternateSplitWeights = qtrue; } - else if ( !strcmp( argv[ i ], "-bsp" ) ) { + else if( !strcmp( argv[ i ], "-deep" ) ) + { + Sys_Printf( "Deep BSP tree generation enabled\n" ); + deepBSP = qtrue; + } + else if( !strcmp( argv[ i ], "-bsp" ) ) + { Sys_Printf( "-bsp argument unnecessary\n" ); } else{ diff --git a/tools/quake3/q3map2/facebsp.c b/tools/quake3/q3map2/facebsp.c index 0140a447..c1d7d939 100644 --- a/tools/quake3/q3map2/facebsp.c +++ b/tools/quake3/q3map2/facebsp.c @@ -117,14 +117,14 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, bestValue = -99999; bestSplit = list; - for ( split = list; split; split = split->next ) - split->checked = qfalse; + // div0: this check causes detail/structural mixes + //for( split = list; split; split = split->next ) + // split->checked = qfalse; for ( split = list; split; split = split->next ) { - if ( split->checked ) { - continue; - } + //if ( split->checked ) + // continue; plane = &mapplanes[ split->planenum ]; splits = 0; @@ -134,7 +134,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, for ( check = list ; check ; check = check->next ) { if ( check->planenum == split->planenum ) { facing++; - check->checked = qtrue; // won't need to test this plane again + //check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); @@ -188,7 +188,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; - if (*splitPlaneNum>-1) mapplanes[ *splitPlaneNum ].counter++; + if (*splitPlaneNum>-1) mapplanes[ *splitPlaneNum ].counter++; } @@ -236,6 +236,7 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ /* if we don't have any more faces, this is a node */ if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; + node->has_structural_children = qfalse; c_faceLeafs++; return; } @@ -243,9 +244,12 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ /* partition the list */ node->planenum = splitPlaneNum; node->compileFlags = compileFlags; + node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque; plane = &mapplanes[ splitPlaneNum ]; childLists[0] = NULL; childLists[1] = NULL; + + qboolean isstruct = 0; for ( split = list; split; split = next ) { /* set next */ @@ -257,6 +261,9 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ continue; } + if(!(split->compileFlags & C_DETAIL)) + isstruct = 1; + /* determine which side the face falls on */ side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); @@ -311,9 +318,22 @@ void BuildFaceTree_r( node_t *node, face_t *list ){ } } +#if 0 + if((node->compileFlags & C_DETAIL) && isstruct) + Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf1\n", node->has_structural_children); +#endif + for ( i = 0 ; i < 2 ; i++ ) { BuildFaceTree_r( node->children[i], childLists[i] ); + node->has_structural_children |= node->children[i]->has_structural_children; } + +#if 0 + if((node->compileFlags & C_DETAIL) && !(node->children[0]->compileFlags & C_DETAIL) && node->children[0]->planenum != PLANENUM_LEAF) + Sys_FPrintf(SYS_ERR, "I am detail, my child is structural\n", node->has_structural_children); + if((node->compileFlags & C_DETAIL) && isstruct) + Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf2\n", node->has_structural_children); +#endif } @@ -345,10 +365,10 @@ tree_t *FaceBSP( face_t *list ) { } Sys_FPrintf( SYS_VRB, "%9d faces\n", count ); - for( i = 0; i < nummapplanes; i++) - { - mapplanes[ i ].counter=0; - } + for ( i = 0; i < nummapplanes; i++ ) + { + mapplanes[ i ].counter = 0; + } tree->headnode = AllocNode(); VectorCopy( tree->mins, tree->headnode->mins ); @@ -380,7 +400,7 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ flist = NULL; for ( b = list; b != NULL; b = b->next ) { - if ( b->detail ) { + if ( !deepBSP && b->detail ) { continue; } @@ -403,6 +423,9 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ f->w = CopyWinding( w ); f->planenum = s->planenum & ~1; f->compileFlags = s->compileFlags; /* ydnar */ + if ( b->detail ) { + f->compileFlags |= C_DETAIL; + } /* ydnar: set priority */ f->priority = 0; @@ -415,6 +438,9 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ){ if ( f->compileFlags & C_AREAPORTAL ) { f->priority += AREAPORTAL_PRIORITY; } + if ( f->compileFlags & C_DETAIL ) { + f->priority += DETAIL_PRIORITY; + } /* get next face */ f->next = flist; @@ -443,7 +469,7 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ flist = NULL; for ( b = list; b != NULL; b = b->next ) { - if ( b->detail ) { + if ( !deepBSP && b->detail ) { continue; } @@ -466,6 +492,9 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ f->w = CopyWinding( w ); f->planenum = s->planenum & ~1; f->compileFlags = s->compileFlags; /* ydnar */ + if ( b->detail ) { + f->compileFlags |= C_DETAIL; + } /* ydnar: set priority */ f->priority = 0; @@ -478,6 +507,9 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ){ if ( f->compileFlags & C_AREAPORTAL ) { f->priority += AREAPORTAL_PRIORITY; } + if ( f->compileFlags & C_DETAIL ) { + f->priority += DETAIL_PRIORITY; + } /* get next face */ f->next = flist; diff --git a/tools/quake3/q3map2/prtfile.c b/tools/quake3/q3map2/prtfile.c index eeb3a800..55d47af6 100644 --- a/tools/quake3/q3map2/prtfile.c +++ b/tools/quake3/q3map2/prtfile.c @@ -64,6 +64,40 @@ void WriteFloat( FILE *f, vec_t v ){ } } +void CountVisportals_r(node_t *node) +{ + int i, s; + portal_t *p; + winding_t *w; + vec3_t normal; + vec_t dist; + + // decision node + if (node->planenum != PLANENUM_LEAF) { + CountVisportals_r (node->children[0]); + CountVisportals_r (node->children[1]); + return; + } + + if (node->opaque) { + return; + } + + for (p = node->portals ; p ; p=p->next[s]) + { + w = p->winding; + s = (p->nodes[1] == node); + if (w && p->nodes[0] == node) + { + if (!PortalPassable(p)) + continue; + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; + ++num_visportals; + } + } +} + /* ================= WritePortalFile_r @@ -95,16 +129,19 @@ void WritePortalFile_r( node_t *node ){ if ( !PortalPassable( p ) ) { continue; } + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; + --num_visportals; // write out to the file // sometimes planes get turned around when they are very near // the changeover point between different axis. interpret the // plane the same way vis will, and flip the side orders if needed // FIXME: is this still relevent? - WindingPlane( w, normal, &dist ); - - if ( DotProduct( p->plane.normal, normal ) < 0.99 ) { // backwards... - fprintf( pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster ); + WindingPlane (w, normal, &dist); + if ( DotProduct (p->plane.normal, normal) < 0.99 ) + { // backwards... + fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); } else{ fprintf( pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster ); @@ -133,6 +170,40 @@ void WritePortalFile_r( node_t *node ){ } +void CountSolidFaces_r (node_t *node) +{ + int i, s; + portal_t *p; + winding_t *w; + + // decision node + if (node->planenum != PLANENUM_LEAF) { + CountSolidFaces_r (node->children[0]); + CountSolidFaces_r (node->children[1]); + return; + } + + if (node->opaque) { + return; + } + + for (p = node->portals ; p ; p=p->next[s]) + { + w = p->winding; + s = (p->nodes[1] == node); + if (w) + { + if (PortalPassable(p)) + continue; + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; + // write out to the file + + ++num_solidfaces; + } + } +} + /* ================= WriteFaceFile_r @@ -162,6 +233,9 @@ void WriteFaceFile_r( node_t *node ){ if ( PortalPassable( p ) ) { continue; } + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; + --num_visportals; // write out to the file if ( p->nodes[0] == node ) { @@ -194,18 +268,30 @@ void WriteFaceFile_r( node_t *node ){ } /* - ================ - NumberLeafs_r - ================ - */ -void NumberLeafs_r( node_t *node ){ - portal_t *p; +================ +NumberLeafs_r +================ +*/ +void NumberLeafs_r (node_t *node, int c) +{ + portal_t *p; if ( node->planenum != PLANENUM_LEAF ) { // decision node node->cluster = -99; - NumberLeafs_r( node->children[0] ); - NumberLeafs_r( node->children[1] ); + + if(node->has_structural_children) + { + NumberLeafs_r (node->children[0], c); + NumberLeafs_r (node->children[1], c); + } + else + { + if(c < 0) + c = num_visclusters++; + NumberLeafs_r (node->children[0], c); + NumberLeafs_r (node->children[1], c); + } return; } @@ -217,9 +303,12 @@ void NumberLeafs_r( node_t *node ){ return; } - node->cluster = num_visclusters; - num_visclusters++; + if(c < 0) + c = num_visclusters++; + + node->cluster = c; +#if 0 // count the portals for ( p = node->portals ; p ; ) { @@ -240,6 +329,7 @@ void NumberLeafs_r( node_t *node ){ p = p->next[1]; } } +#endif } @@ -256,7 +346,9 @@ void NumberClusters( tree_t *tree ) { Sys_FPrintf( SYS_VRB,"--- NumberClusters ---\n" ); // set the cluster field in every leaf and count the total number of portals - NumberLeafs_r( tree->headnode ); + NumberLeafs_r (tree->headnode, -1); + CountVisportals_r (tree->headnode); + CountSolidFaces_r (tree->headnode); Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters ); Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals ); diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index d8537a3c..abfc262e 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -202,6 +202,7 @@ #define HINT_PRIORITY 1000 /* ydnar: force hint splits first and antiportal/areaportal splits last */ #define ANTIPORTAL_PRIORITY -1000 #define AREAPORTAL_PRIORITY -1000 +#define DETAIL_PRIORITY -3000 #define PSIDE_FRONT 1 #define PSIDE_BACK 2 @@ -789,7 +790,7 @@ typedef struct face_s struct face_s *next; int planenum; int priority; - qboolean checked; + //qboolean checked; int compileFlags; winding_t *w; } @@ -1116,6 +1117,8 @@ typedef struct node_s entity_t *occupant; /* for leak file testing */ struct portal_s *portals; /* also on nodes during construction */ + + qboolean has_structural_children; } node_t; @@ -1948,6 +1951,7 @@ Q_EXTERN qboolean noHint Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse ); /* ydnar */ Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse ); /* 27 */ +Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse ); /* div0 */ Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 ); /* ydnar: -patchmeta subdivisions */ @@ -2081,10 +2085,13 @@ Q_EXTERN qboolean fastvis; Q_EXTERN qboolean noPassageVis; Q_EXTERN qboolean passageVisOnly; Q_EXTERN qboolean mergevis; +Q_EXTERN qboolean mergevisportals; Q_EXTERN qboolean nosort; Q_EXTERN qboolean saveprt; Q_EXTERN qboolean hint; /* ydnar */ Q_EXTERN char inbase[ MAX_QPATH ]; +Q_EXTERN char inbase[ MAX_QPATH ]; +Q_EXTERN char globalCelShader[ MAX_QPATH ]; /* other bits */ Q_EXTERN int totalvis;