/* =================== R_SplitEntityOnNode2 =================== */ void R_SplitEntityOnNode2(mnode_t *node) { mplane_t *splitplane; int sides; if (node->visframe != r_visframecount) return; if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) r_pefragtopnode = node; // we've reached a non-solid leaf, so it's // visible and not BSP clipped return; } splitplane = node->plane; sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); if (sides == 3) { // remember first splitter r_pefragtopnode = node; return; } // not split yet; recurse down the contacted side if (sides & 1) R_SplitEntityOnNode2(node->children[0]); else R_SplitEntityOnNode2(node->children[1]); }
/* =================== R_SplitEntityOnNode =================== */ void R_SplitEntityOnNode(mnode_t *node) { efrag_t *ef; mplane_t *splitplane; mleaf_t *leaf; int sides; if (node->contents == CONTENTS_SOLID) { return; } // add an efrag if the node is a leaf if (node->contents < 0) { if (!r_pefragtopnode) r_pefragtopnode = node; leaf = (mleaf_t *)node; // grab an efrag off the free list ef = cl.free_efrags; if (!ef) { Con_Printf("Too many efrags!\n"); return; // no free fragments... } cl.free_efrags = cl.free_efrags->entnext; ef->entity = r_addent; // add the entity link *lastlink = ef; lastlink = &ef->entnext; ef->entnext = NULL; // set the leaf links ef->leaf = leaf; ef->leafnext = leaf->efrags; leaf->efrags = ef; return; } // NODE_MIXED splitplane = node->plane; sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it if (!r_pefragtopnode) r_pefragtopnode = node; } // recurse down the contacted sides if (sides & 1) R_SplitEntityOnNode(node->children[0]); if (sides & 2) R_SplitEntityOnNode(node->children[1]); }
/* * R_VisCullBox */ qboolean R_VisCullBox( const vec3_t mins, const vec3_t maxs ) { int s, stackdepth = 0; vec3_t extmins, extmaxs; mnode_t *node, *localstack[2048]; if( !rsh.worldModel || ( rn.refdef.rdflags & RDF_NOWORLDMODEL ) ) return qfalse; if( rn.renderFlags & RF_NOVIS ) return qfalse; for( s = 0; s < 3; s++ ) { extmins[s] = mins[s] - 4; extmaxs[s] = maxs[s] + 4; } for( node = rsh.worldBrushModel->nodes;; ) { if( node->pvsframe != rf.pvsframecount ) { if( !stackdepth ) return qtrue; node = localstack[--stackdepth]; continue; } if( !node->plane ) return qfalse; s = BOX_ON_PLANE_SIDE( extmins, extmaxs, node->plane ) - 1; if( s < 2 ) { node = node->children[s]; continue; } // go down both sides if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ) ) localstack[stackdepth++] = node->children[0]; node = node->children[1]; } return qtrue; }
/* * R_SurfaceShadowBits */ static unsigned int R_SurfaceShadowBits( const msurface_t *surf, unsigned int checkShadowBits ) { unsigned int i, bit; shadowGroup_t *grp; unsigned int surfShadowBits = 0; if( !R_SurfPotentiallyShadowed( surf ) ) { return 0; } for( i = 0; i < rsc.numShadowGroups; i++ ) { if( !checkShadowBits ) { break; } grp = rsc.shadowGroups + i; bit = grp->bit; if( checkShadowBits & bit ) { switch( surf->facetype ) { case FACETYPE_PLANAR: if( BOX_ON_PLANE_SIDE( grp->visMins, grp->visMaxs, surf->plane ) == 3 ) { // crossed by plane surfShadowBits |= bit; } break; case FACETYPE_PATCH: case FACETYPE_TRISURF: case FACETYPE_FOLIAGE: if( BoundsIntersect( surf->mins, surf->maxs, grp->visMins, grp->visMaxs ) ) { surfShadowBits |= bit; } break; } checkShadowBits &= ~bit; } } return surfShadowBits; }
/* * R_RecursiveWorldNode */ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipFlags, unsigned int dlightBits, unsigned int shadowBits ) { unsigned int i; unsigned int dlightBits1; unsigned int shadowBits1; unsigned int bit; const cplane_t *clipplane; mleaf_t *pleaf; while( 1 ) { if( node->pvsframe != rf.pvsframecount ) return; if( clipFlags ) { for( i = sizeof( rn.frustum )/sizeof( rn.frustum[0] ), bit = 1, clipplane = rn.frustum; i > 0; i--, bit<<=1, clipplane++ ) { if( clipFlags & bit ) { int clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane ); if( clipped == 2 ) return; else if( clipped == 1 ) clipFlags &= ~bit; // node is entirely on screen } } } if( !node->plane ) break; dlightBits1 = 0; if( dlightBits ) { float dist; unsigned int checkBits = dlightBits; for( i = 0, bit = 1; i < rsc.numDlights; i++, bit <<= 1 ) { dlight_t *dl = rsc.dlights + i; if( dlightBits & bit ) { dist = PlaneDiff( dl->origin, node->plane ); if( dist < -dl->intensity ) dlightBits &= ~bit; if( dist < dl->intensity ) dlightBits1 |= bit; checkBits &= ~bit; if( !checkBits ) break; } } } shadowBits1 = 0; if( shadowBits ) { unsigned int checkBits = shadowBits; for( i = 0; i < rsc.numShadowGroups; i++ ) { shadowGroup_t *group = rsc.shadowGroups + i; bit = group->bit; if( checkBits & bit ) { int clipped = BOX_ON_PLANE_SIDE( group->visMins, group->visMaxs, node->plane ); if( !(clipped & 1) ) shadowBits &= ~bit; if( clipped & 2 ) shadowBits1 |= bit; checkBits &= ~bit; if( !checkBits ) break; } } } R_RecursiveWorldNode( node->children[0], clipFlags, dlightBits, shadowBits ); node = node->children[1]; dlightBits = dlightBits1; shadowBits = shadowBits1; } // if a leaf node, draw stuff pleaf = ( mleaf_t * )node; pleaf->visframe = rf.frameCount; // add leaf bounds to view bounds for( i = 0; i < 3; i++ ) { rn.visMins[i] = min( rn.visMins[i], pleaf->mins[i] ); rn.visMaxs[i] = max( rn.visMaxs[i], pleaf->maxs[i] ); } rn.dlightBits |= dlightBits; rn.shadowBits |= shadowBits; R_MarkLeafSurfaces( pleaf->firstVisSurface, clipFlags, dlightBits, shadowBits ); rf.stats.c_world_leafs++; }