static bool PortalCrossesWater( waterleaf_t &baseleaf, portal_t *portal ) { if ( baseleaf.hasSurface ) { int side = WindingOnPlaneSide( portal->winding, baseleaf.surfaceNormal, baseleaf.surfaceDist ); if ( side == SIDE_CROSS || side == SIDE_FRONT ) return true; } return false; }
void BuildFaceTree_r( node_t *node, face_t *list ){ face_t *split; face_t *next; int side; plane_t *plane; face_t *newFace; face_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum, compileFlags; /* count faces left */ i = CountFaceList( list ); /* select the best split plane */ SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags ); /* if we don't have any more faces, this is a node */ if ( splitPlaneNum == -1 ) { node->planenum = PLANENUM_LEAF; c_faceLeafs++; return; } /* partition the list */ node->planenum = splitPlaneNum; node->compileFlags = compileFlags; plane = &mapplanes[ splitPlaneNum ]; childLists[0] = NULL; childLists[1] = NULL; for ( split = list; split; split = next ) { /* set next */ next = split->next; /* don't split by identical plane */ if ( split->planenum == node->planenum ) { FreeBspFace( split ); continue; } /* determine which side the face falls on */ side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); /* switch on side */ if ( side == SIDE_CROSS ) { ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding ); if ( frontWinding ) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[0] = newFace; } if ( backWinding ) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[1] = newFace; } FreeBspFace( split ); } else if ( side == SIDE_FRONT ) { split->next = childLists[0]; childLists[0] = split; } else if ( side == SIDE_BACK ) { split->next = childLists[1]; childLists[1] = split; } } // recursively process children for ( i = 0 ; i < 2 ; i++ ) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy( node->mins, node->children[i]->mins ); VectorCopy( node->maxs, node->children[i]->maxs ); } for ( i = 0 ; i < 3 ; i++ ) { if ( plane->normal[i] == 1 ) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } for ( i = 0 ; i < 2 ; i++ ) { BuildFaceTree_r( node->children[i], childLists[i] ); } }
static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, int *compileFlags ){ face_t *split; face_t *check; face_t *bestSplit; int splits, facing, front, back; int side; plane_t *plane; int value, bestValue; int i; vec3_t normal; float dist; int planenum; float sizeBias; int frontC,backC,splitsC,facingC; /* ydnar: set some defaults */ *splitPlaneNum = -1; /* leaf */ *compileFlags = 0; /* ydnar 2002-06-24: changed this to split on z-axis as well */ /* ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value */ /* if it is crossing a block boundary, force a split */ for ( i = 0; i < 3; i++ ) { if ( blockSize[ i ] <= 0 ) { continue; } dist = blockSize[ i ] * ( floor( node->mins[ i ] / blockSize[ i ] ) + 1 ); if ( node->maxs[ i ] > dist ) { VectorClear( normal ); normal[ i ] = 1; planenum = FindFloatPlane( normal, dist, 0, NULL ); *splitPlaneNum = planenum; return; } } /* pick one of the face planes */ bestValue = -99999; bestSplit = list; for ( split = list; split; split = split->next ) split->checked = qfalse; //we don't add planes that already exist in the bsp. This stops us from checking them repeatedly for ( split = list; split; split = split->next ) { if ( split->checked ) { continue; } plane = &mapplanes[ split->planenum ]; splits = 0; facing = 0; front = 0; back = 0; for ( check = list ; check ; check = check->next ) { if ( check->planenum == split->planenum ) { facing++; check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); if ( side == SIDE_CROSS ) { splits++; } else if ( side == SIDE_FRONT ) { front++; } else if ( side == SIDE_BACK ) { back++; } } //Bigger is better sizeBias = GetSurfaceAreaOfWinding( split->w ); //Base score = 20000 perfectly balanced value = 20000 - ( abs( front - back ) ); value -= plane->counter; // If we've already used this plane sometime in the past try not to use it again value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value -= splits * 5; //more splits = bad value += sizeBias * 10; //We want a huge score bias based on plane size /* //164fps - strange drops in places //Base score = 20000 perfectly balanced value = 20000-(abs(front-back)); value -= plane->counter*10;// If we've already used this plane sometime in the past try not to use it again value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value -= splits; //more splits = bad value += sizeBias*10; //We want a huge score bias based on plane size */ /* //166 fps //Base score = 20000 perfectly balanced value = 20000-(abs(front-back)); value -= plane->counter;// If we've already used this plane sometime in the past try not to use it again value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value -= splits; //more splits = bad value += sizeBias*10; //We want a huge score bias based on plane size */ /* //150fps sizeBias=GetSurfaceAreaOfWinding(split->w); //Base score = 20000 perfectly balanced value = 20000-(abs(front-back)); value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value += sizeBias*10; //We want a huge score bias based on plane size */ //if ( plane->type < 3 ) { // value+=5; // axial is better //} value += split->priority; // prioritize hints higher if ( value > bestValue ) { bestValue = value; bestSplit = split; frontC = front; backC = back; splitsC = splits; facingC = facing; } } /* for( split = list; split; split = split->next ) { if ( split->checked ) continue; plane = &mapplanes[ split->planenum ]; splits = 0; facing = 0; front = 0; back = 0; for ( check = list ; check ; check = check->next ) { if ( check->planenum == split->planenum ) { facing++; check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); if ( side == SIDE_CROSS ) { splits++; } else if ( side == SIDE_FRONT ) { front++; } else if ( side == SIDE_BACK ) { back++; } } value = 5*facing - 5*splits; // - abs(front-back); if ( plane->type < 3 ) { value+=5; // axial is better } value += split->priority; // prioritize hints higher if ( value > bestValue ) { bestValue = value; bestSplit = split; frontC=front; backC=back; splitsC=splits; } } */ /* nothing, we have a leaf */ if ( bestValue == -99999 ) { return; } //Sys_FPrintf (SYS_VRB, "F: %d B:%d S:%d FA:%ds\n",frontC,backC,splitsC,facingC ); // if (frontC+backC<10) { // Sys_FPrintf (SYS_VRB, "Forced Leaf\n"); // return; //Test! } /* set best split data */ *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; if ( *splitPlaneNum > -1 ) { mapplanes[ *splitPlaneNum ].counter++; } }
static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, int *compileFlags ){ face_t *split; face_t *check; face_t *bestSplit; int splits, facing, front, back; int side; plane_t *plane; int value, bestValue; int i; vec3_t normal; float dist; int planenum; float sizeBias; /* ydnar: set some defaults */ *splitPlaneNum = -1; /* leaf */ *compileFlags = 0; /* ydnar 2002-06-24: changed this to split on z-axis as well */ /* ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value */ /* if it is crossing a block boundary, force a split */ for ( i = 0; i < 3; i++ ) { if ( blockSize[ i ] <= 0 ) { continue; } dist = blockSize[ i ] * ( floor( node->mins[ i ] / blockSize[ i ] ) + 1 ); if ( node->maxs[ i ] > dist ) { VectorClear( normal ); normal[ i ] = 1; planenum = FindFloatPlane( normal, dist, 0, NULL ); *splitPlaneNum = planenum; return; } } /* pick one of the face planes */ bestValue = -99999; bestSplit = list; // 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; plane = &mapplanes[ split->planenum ]; splits = 0; facing = 0; front = 0; back = 0; for ( check = list ; check ; check = check->next ) { if ( check->planenum == split->planenum ) { facing++; //check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); if ( side == SIDE_CROSS ) { splits++; } else if ( side == SIDE_FRONT ) { front++; } else if ( side == SIDE_BACK ) { back++; } } if ( bspAlternateSplitWeights ) { // from 27 //Bigger is better sizeBias = WindingArea( split->w ); //Base score = 20000 perfectly balanced value = 20000 - ( abs( front - back ) ); value -= plane->counter; // If we've already used this plane sometime in the past try not to use it again value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value -= splits * 5; //more splits = bad value += sizeBias * 10; //We want a huge score bias based on plane size } else { value = 5 * facing - 5 * splits; // - abs(front-back); if ( plane->type < 3 ) { value += 5; // axial is better } } value += split->priority; // prioritize hints higher if ( value > bestValue ) { bestValue = value; bestSplit = split; } } /* nothing, we have a leaf */ if ( bestValue == -99999 ) { return; } /* set best split data */ *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; if ( *splitPlaneNum > -1 ) { mapplanes[ *splitPlaneNum ].counter++; } }
/* ================ SelectSplitPlaneNum ================ */ static void SelectSplitPlaneNum(node_t * node, bspFace_t * list, int *splitPlaneNum, int *hintSplit) { bspFace_t *split; bspFace_t *check; bspFace_t *bestSplit; int splits, facing, front, back; int side; plane_t *plane; int value, bestValue; int i; vec3_t normal; float dist; int planenum; *splitPlaneNum = -1; *hintSplit = qfalse; // ydnar 2002-06-24: changed this to split on z-axis as well // ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value // if it is crossing a 1k block boundary, force a split for(i = 0; i < 3; i++) { if(blockSize[i] <= 0) continue; dist = blockSize[i] * (floor(node->mins[i] / blockSize[i]) + 1); if(node->maxs[i] > dist) { VectorClear(normal); normal[i] = 1; planenum = FindFloatPlane(normal, dist); *splitPlaneNum = planenum; return; } } // pick one of the face planes bestValue = -99999; bestSplit = list; for(split = list; split; split = split->next) { split->checked = qfalse; } for(split = list; split; split = split->next) { if(split->checked) { continue; } plane = &mapPlanes[split->planenum]; splits = 0; facing = 0; front = 0; back = 0; for(check = list; check; check = check->next) { if(check->planenum == split->planenum) { facing++; check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide(check->w, plane->normal, plane->dist); if(side == SIDE_CROSS) { splits++; } else if(side == SIDE_FRONT) { front++; } else if(side == SIDE_BACK) { back++; } } value = 5 * facing - 5 * splits; // - abs(front-back); if(plane->type < 3) { value += 5; // axial is better } value += split->priority; // prioritize hints higher if(value > bestValue) { bestValue = value; bestSplit = split; } } if(bestValue == -99999) { return; } if(bestSplit->hint) *hintSplit = qtrue; *splitPlaneNum = bestSplit->planenum; }
/* ================ BuildFaceTree_r ================ */ void BuildFaceTree_r(node_t * node, bspFace_t * list) { bspFace_t *split; bspFace_t *next; int side; plane_t *plane; bspFace_t *newFace; bspFace_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum; int hintSplit; i = CountFaceList(list); SelectSplitPlaneNum(node, list, &splitPlaneNum, &hintSplit); // if we don't have any more faces, this is a node if(splitPlaneNum == -1) { node->planenum = PLANENUM_LEAF; c_faceLeafs++; return; } // partition the list node->planenum = splitPlaneNum; node->hint = hintSplit; plane = &mapPlanes[splitPlaneNum]; childLists[0] = NULL; childLists[1] = NULL; for(split = list; split; split = next) { next = split->next; if(split->planenum == node->planenum) { FreeBspFace(split); continue; } side = WindingOnPlaneSide(split->w, plane->normal, plane->dist); if(side == SIDE_CROSS) { ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding); if(frontWinding) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->hint = split->hint; childLists[0] = newFace; } if(backWinding) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->hint = split->hint; childLists[1] = newFace; } FreeBspFace(split); } else if(side == SIDE_FRONT) { split->next = childLists[0]; childLists[0] = split; } else if(side == SIDE_BACK) { split->next = childLists[1]; childLists[1] = split; } } // recursively process children for(i = 0; i < 2; i++) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy(node->mins, node->children[i]->mins); VectorCopy(node->maxs, node->children[i]->maxs); } for(i = 0; i < 3; i++) { if(plane->normal[i] == 1) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } for(i = 0; i < 2; i++) { BuildFaceTree_r(node->children[i], childLists[i]); } }
static void SelectSplitPlaneNum(node_t * node, face_t * list, int *splitPlaneNum, int *compileFlags) { face_t *split; face_t *check; face_t *bestSplit; int splits, facing, front, back; int side; plane_t *plane; int value, bestValue; int i; vec3_t normal; float dist; int planenum; //float sizeBias; //int checks; int frontC, backC, splitsC, facingC; /* ydnar: set some defaults */ *splitPlaneNum = -1; /* leaf */ *compileFlags = 0; /* ydnar 2002-06-24: changed this to split on z-axis as well */ /* ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value */ /* if it is crossing a block boundary, force a split */ #if 1 for(i = 0; i < 3; i++) { if(blockSize[i] <= 0) continue; dist = blockSize[i] * (floor(node->mins[i] / blockSize[i]) + 1); if(node->maxs[i] > dist) { VectorClear(normal); normal[i] = 1; planenum = FindFloatPlane(normal, dist, 0, NULL); *splitPlaneNum = planenum; return; } } #endif /* pick one of the face planes */ bestValue = -99999; bestSplit = list; //checks = 0; #if 1 // div0: this check causes detail/structural mixes //for(split = list; split; split = split->next) // split->checked = qfalse; #if defined(DEBUG_SPLITS) Sys_FPrintf(SYS_VRB, "split scores: ["); #endif for(split = list; split; split = split->next) { //if(split->checked) // continue; //checks++; plane = &mapplanes[split->planenum]; splits = 0; facing = 0; front = 0; back = 0; for(check = list; check; check = check->next) { if(check->planenum == split->planenum) { facing++; //check->checked = qtrue; // won't need to test this plane again continue; } side = WindingOnPlaneSide(check->w, plane->normal, plane->dist); if(side == SIDE_CROSS) { splits++; } else if(side == SIDE_FRONT) { front++; } else if(side == SIDE_BACK) { back++; } } if(bspAlternateSplitWeights) { //Base score = 20000 perfectly balanced value = 0;//20000; value -= abs(front - back); // prefer centered planes value -= plane->counter; // if we've already used this plane sometime in the past try not to use it again value += facing * 5; // if we're going to have alot of other surfs use this plane, we want to get it in quickly. value -= splits * 5; // more splits = bad //value += sizeBias * 10; // we want a huge score bias based on plane size if(plane->type < 3) { value += 5; // axial is better } // we want a huge score bias based on plane size #if 0 { winding_t *w; node_t *n; plane_t *plane; vec3_t normal; vec_t dist; // create temporary winding to draw the split plane w = CopyWinding(split->w); // clip by all the parents for(n = node->parent; n && w;) { plane = &mapplanes[n->planenum]; if(n->children[0] == node) { // take front ChopWindingInPlace(&w, plane->normal, plane->dist, 0.001); // BASE_WINDING_EPSILON } else { // take back VectorNegate(plane->normal, normal); dist = -plane->dist; ChopWindingInPlace(&w, normal, dist, 0.001); // BASE_WINDING_EPSILON } node = n; n = n->parent; } // clip by node AABB if(w != NULL) ChopWindingByBounds(&w, node->mins, node->maxs, CLIP_EPSILON); if(w != NULL) value += WindingArea(w); } #endif } else { value = 5 * facing - 5 * splits; // - abs(front-back); if(plane->type < 3) { value += 5; // axial is better } } value += split->priority; // prioritize hints higher #if defined(DEBUG_SPLITS) Sys_FPrintf(SYS_VRB, " %d", value); #endif if(value > bestValue) { bestValue = value; bestSplit = split; frontC = front; backC = back; splitsC = splits; facingC = facing; } } #if defined(DEBUG_SPLITS) Sys_FPrintf(SYS_VRB, "]\n"); #endif #endif /* nothing, we have a leaf */ if(bestValue == -99999) return; //Sys_FPrintf(SYS_VRB, "F: %9d B:%9d S:%9d FA:%9d\n", frontC, backC, splitsC, facingC); /* set best split data */ *splitPlaneNum = bestSplit->planenum; *compileFlags = bestSplit->compileFlags; #if defined(DEBUG_SPLITS) 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++; }
void BuildFaceTree_r(node_t * node, face_t * list) { face_t *split; face_t *next; int side; plane_t *plane; face_t *newFace; face_t *childLists[2]; winding_t *frontWinding, *backWinding; int i; int splitPlaneNum, compileFlags; qboolean isstruct = qfalse; int splits, front, back; /* count faces left */ i = CountFaceList(list); #if defined(DEBUG_SPLITS) Sys_FPrintf(SYS_VRB, "faces left = %d\n", i); #endif /* select the best split plane */ SelectSplitPlaneNum(node, list, &splitPlaneNum, &compileFlags); /* if we don't have any more faces, this is a leaf */ if(splitPlaneNum == -1) { node->planenum = PLANENUM_LEAF; node->has_structural_children = qfalse; c_faceLeafs++; return; } /* 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; splits = front = back = 0; for(split = list; split; split = next) { /* set next */ next = split->next; /* don't split by identical plane */ if(split->planenum == node->planenum) { 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); /* switch on side */ if(side == SIDE_CROSS) { splits++; ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding); if(frontWinding) { newFace = AllocBspFace(); newFace->w = frontWinding; newFace->next = childLists[0]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[0] = newFace; front++; } if(backWinding) { newFace = AllocBspFace(); newFace->w = backWinding; newFace->next = childLists[1]; newFace->planenum = split->planenum; newFace->priority = split->priority; newFace->compileFlags = split->compileFlags; childLists[1] = newFace; back++; } FreeBspFace(split); } else if(side == SIDE_FRONT) { split->next = childLists[0]; childLists[0] = split; front++; } else if(side == SIDE_BACK) { split->next = childLists[1]; childLists[1] = split; back++; } } // recursively process children for(i = 0; i < 2; i++) { node->children[i] = AllocNode(); node->children[i]->parent = node; VectorCopy(node->mins, node->children[i]->mins); VectorCopy(node->maxs, node->children[i]->maxs); c_faceNodes++; } for(i = 0; i < 3; i++) { if(plane->normal[i] == 1) { node->children[0]->mins[i] = plane->dist; node->children[1]->maxs[i] = plane->dist; break; } } #if 1 if(drawBSP && drawTree) { drawChildLists[0] = childLists[0]; drawChildLists[1] = childLists[1]; drawSplitNode = node; Draw_Scene(DrawAll); } #endif #if defined(DEBUG_SPLITS) 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 defined(DEBUG_SPLITS) 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 }