From e2b0ecdcfb93b550f96eeec9c4263248539d0c6d 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 | 5 ++ tools/quake3/q3map2/facebsp.c | 56 +++++++++++++++--- tools/quake3/q3map2/prtfile.c | 107 ++++++++++++++++++++++++++++++++-- tools/quake3/q3map2/q3map2.h | 7 ++- 4 files changed, 159 insertions(+), 16 deletions(-) diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c index c04f30d5..03c04074 100644 --- a/tools/quake3/q3map2/bsp.c +++ b/tools/quake3/q3map2/bsp.c @@ -893,6 +893,11 @@ int BSPMain( int argc, char **argv ) Sys_Printf( "Alternate BSP splitting (by 27) enabled\n" ); bspAlternateSplitWeights = qtrue; } + 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 65532a17..702765ad 100644 --- a/tools/quake3/q3map2/facebsp.c +++ b/tools/quake3/q3map2/facebsp.c @@ -122,14 +122,15 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, 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; facing = 0; @@ -138,7 +139,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 ); @@ -173,7 +174,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, } } - value += split->priority; // prioritize hints higher + value += split->priority; // prioritize hints higher if ( value > bestValue ) { bestValue = value; @@ -195,6 +196,15 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; +#if 0 + if(bestSplit->compileFlags & C_DETAIL) + for( split = list; split; split = split->next ) + if(!(split->compileFlags & C_DETAIL)) + Sys_FPrintf(SYS_ERR, "DON'T DO SUCH SPLITS (1)\n"); + if((node->compileFlags & C_DETAIL) && !(bestSplit->compileFlags & C_DETAIL)) + Sys_FPrintf(SYS_ERR, "DON'T DO SUCH SPLITS (2)\n"); +#endif + if (*splitPlaneNum>-1) mapplanes[ *splitPlaneNum ].counter++; } @@ -246,6 +256,7 @@ void BuildFaceTree_r( node_t *node, face_t *list ) if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; + node->has_structural_children = qfalse; c_faceLeafs++; return; } @@ -253,9 +264,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 */ @@ -267,6 +281,9 @@ void BuildFaceTree_r( node_t *node, face_t *list ) FreeBspFace( split ); continue; } + + if(!(split->compileFlags & C_DETAIL)) + isstruct = 1; /* determine which side the face falls on */ side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); @@ -321,9 +338,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 } @@ -391,7 +421,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; for( i = 0; i < b->numsides; i++ ) @@ -411,6 +441,8 @@ 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; @@ -420,6 +452,8 @@ face_t *MakeStructuralBSPFaceList( brush_t *list ) f->priority += ANTIPORTAL_PRIORITY; if( f->compileFlags & C_AREAPORTAL ) f->priority += AREAPORTAL_PRIORITY; + if( f->compileFlags & C_DETAIL ) + f->priority += DETAIL_PRIORITY; /* get next face */ f->next = flist; @@ -449,7 +483,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; for( i = 0; i < b->numsides; i++ ) @@ -469,6 +503,8 @@ 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 +514,8 @@ face_t *MakeVisibleBSPFaceList( brush_t *list ) f->priority += ANTIPORTAL_PRIORITY; 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 6f36f758..7108c589 100644 --- a/tools/quake3/q3map2/prtfile.c +++ b/tools/quake3/q3map2/prtfile.c @@ -63,6 +63,40 @@ void WriteFloat (FILE *f, vec_t v) fprintf (f,"%f ",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,6 +129,9 @@ 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 @@ -102,6 +139,7 @@ void WritePortalFile_r (node_t *node) // 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); @@ -130,6 +168,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 @@ -160,6 +232,8 @@ void WriteFaceFile_r (node_t *node) { if (PortalPassable(p)) continue; + if(p->nodes[0]->cluster == p->nodes[1]->cluster) + continue; // write out to the file if (p->nodes[0] == node) @@ -197,15 +271,30 @@ void WriteFaceFile_r (node_t *node) NumberLeafs_r ================ */ -void NumberLeafs_r (node_t *node) +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) + { +#if 0 + if(c >= 0) + Sys_FPrintf (SYS_ERR,"THIS CANNOT HAPPEN\n"); +#endif + 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 +306,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 ; ) { @@ -238,6 +330,7 @@ void NumberLeafs_r (node_t *node) p = p->next[1]; } } +#endif } @@ -254,7 +347,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 0a6f3f3d..fbde390d 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -196,6 +196,7 @@ constants #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 @@ -794,7 +795,7 @@ typedef struct face_s struct face_s *next; int planenum; int priority; - qboolean checked; + //qboolean checked; int compileFlags; winding_t *w; } @@ -1123,6 +1124,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; @@ -1955,6 +1958,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 */ @@ -2070,6 +2074,7 @@ 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 */ -- 2.39.2