/* ============ QuickTestBrushToPlanenum ============ */ int QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits) { int i, num; plane_t *plane; int s; *numsplits = 0; // if the brush actually uses the planenum, // we can tell the side for sure for (i=0 ; i<brush->numsides ; i++) { num = brush->sides[i].planenum; if (num >= MAX_MAP_PLANES) Error ("bad planenum"); if (num == planenum) return PSIDE_BACK|PSIDE_FACING; if (num == (planenum ^ 1) ) return PSIDE_FRONT|PSIDE_FACING; } // box on plane side plane = &g_MainMap->mapplanes[planenum]; s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane); // if both sides, count the visible faces split if (s == PSIDE_BOTH) { *numsplits += 3; } return s; }
//----------------------------------------------------------------------------- // Check to see if a displacement lives in any leaves that are not // in the 3d skybox //----------------------------------------------------------------------------- bool IsBoxInsideWorld( int node, CUtlVector<int> &skipAreas, const Vector &vecMins, const Vector &vecMaxs ) { while( 1 ) { // leaf if (node < 0) { // get the leaf int leaf = - 1 - node; // Don't bother with solid leaves if (dleafs[leaf].contents & CONTENTS_SOLID) return false; // Skip 3D skybox int i; for ( i = skipAreas.Count(); --i >= 0; ) { if ( dleafs[leaf].area == skipAreas[i] ) return false; } return true; } // // get displacement bounding box position relative to the node plane // dnode_t *pNode = &dnodes[ node ]; dplane_t *pPlane = &dplanes[ pNode->planenum ]; int sideResult = BrushBspBoxOnPlaneSide( vecMins, vecMaxs, pPlane ); // front side if( sideResult == 1 ) { node = pNode->children[0]; } // back side else if( sideResult == 2 ) { node = pNode->children[1]; } //split else { if ( IsBoxInsideWorld( pNode->children[0], skipAreas, vecMins, vecMaxs ) ) return true; node = pNode->children[1]; } } }
/* ============ TestBrushToPlanenum ============ */ int TestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits, qboolean *hintsplit, int *epsilonbrush) { int i, j, num; plane_t *plane; int s; winding_t *w; vec_t d, d_front, d_back; int front, back; *numsplits = 0; *hintsplit = false; // if the brush actually uses the planenum, // we can tell the side for sure for (i=0 ; i<brush->numsides ; i++) { num = brush->sides[i].planenum; if (num >= MAX_MAP_PLANES) Error ("bad planenum"); if (num == planenum) return PSIDE_BACK|PSIDE_FACING; if (num == (planenum ^ 1) ) return PSIDE_FRONT|PSIDE_FACING; } // box on plane side plane = &g_MainMap->mapplanes[planenum]; s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane); if (s != PSIDE_BOTH) return s; // if both sides, count the visible faces split d_front = d_back = 0; for (i=0 ; i<brush->numsides ; i++) { if (brush->sides[i].texinfo == TEXINFO_NODE) continue; // on node, don't worry about splits if (!brush->sides[i].visible) continue; // we don't care about non-visible w = brush->sides[i].winding; if (!w) continue; front = back = 0; for (j=0 ; j<w->numpoints; j++) { d = DotProduct (w->p[j], plane->normal) - plane->dist; if (d > d_front) d_front = d; if (d < d_back) d_back = d; if (d > 0.1) // PLANESIDE_EPSILON) front = 1; if (d < -0.1) // PLANESIDE_EPSILON) back = 1; } if (front && back) { if ( !(brush->sides[i].surf & SURF_SKIP) ) { (*numsplits)++; if (brush->sides[i].surf & SURF_HINT) *hintsplit = true; } } } if ( (d_front > 0.0 && d_front < 1.0) || (d_back < 0.0 && d_back > -1.0) ) (*epsilonbrush)++; #if 0 if (*numsplits == 0) { // didn't really need to be split if (front) s = PSIDE_FRONT; else if (back) s = PSIDE_BACK; else s = 0; } #endif return s; }