/* ==================== PutWindingIntoAreas_r Clips a winding down into the bsp tree, then converts the fragments to triangles and adds them to the area lists ==================== */ static void PutWindingIntoAreas_r( uEntity_t *e, const idWinding *w, side_t *side, node_t *node ) { idWinding *front, *back; int area; if ( !w ) { return; } if ( node->planenum != PLANENUM_LEAF ) { if ( side->planenum == node->planenum ) { PutWindingIntoAreas_r( e, w, side, node->children[0] ); return; } if ( side->planenum == ( node->planenum ^ 1) ) { PutWindingIntoAreas_r( e, w, side, node->children[1] ); return; } // see if we need to split it // adding the "noFragment" flag to big surfaces like sky boxes // will avoid potentially dicing them up into tons of triangles // that take forever to optimize back together if ( !dmapGlobals.fullCarve || side->material->NoFragment() ) { area = CheckWindingInAreas_r( w, node ); if ( area >= 0 ) { mapTri_t *tri; // put in single area tri = TriListForSide( side, w ); AddTriListToArea( e, tri, side->planenum, area, &side->texVec ); return; } } w->Split( dmapGlobals.mapPlanes[ node->planenum ], ON_EPSILON, &front, &back ); PutWindingIntoAreas_r( e, front, side, node->children[0] ); if ( front ) { delete front; } PutWindingIntoAreas_r( e, back, side, node->children[1] ); if ( back ) { delete back; } return; } // if opaque leaf, don't add if ( node->area >= 0 && !node->opaque ) { mapTri_t *tri; tri = TriListForSide( side, w ); AddTriListToArea( e, tri, side->planenum, node->area, &side->texVec ); } }
/* ================== AddMapTriToAreas Used for curves and inlined models ================== */ void AddMapTriToAreas( mapTri_t* tri, uEntity_t* e ) { int area; idWinding* w; // skip degenerate triangles from pinched curves if( MapTriArea( tri ) <= 0 ) { return; } if( dmapGlobals.fullCarve ) { // always fragment into areas w = WindingForTri( tri ); ClipTriIntoTree_r( w, tri, e, e->tree->headnode ); return; } w = WindingForTri( tri ); area = CheckWindingInAreas_r( w, e->tree->headnode ); delete w; if( area == -1 ) { return; } if( area >= 0 ) { mapTri_t* newTri; idPlane plane; int planeNum; textureVectors_t texVec; // put in single area newTri = CopyMapTri( tri ); newTri->next = NULL; PlaneForTri( tri, plane ); planeNum = FindFloatPlane( plane ); TexVecForTri( &texVec, newTri ); AddTriListToArea( e, newTri, planeNum, area, &texVec ); } else { // fragment into areas w = WindingForTri( tri ); ClipTriIntoTree_r( w, tri, e, e->tree->headnode ); } }
/* ==================== ClipTriIntoTree_r This is used for adding curve triangles The winding will be freed before it returns ==================== */ void ClipTriIntoTree_r( idWinding* w, mapTri_t* originalTri, uEntity_t* e, node_t* node ) { idWinding* front, *back; if( !w ) { return; } if( node->planenum != PLANENUM_LEAF ) { //common->Printf( "ClipTriIntoTree_r: splitting triangle with splitplane %i\n", node->nodeNumber ); w->Split( dmapGlobals.mapPlanes[ node->planenum ], ON_EPSILON, &front, &back ); delete w; ClipTriIntoTree_r( front, originalTri, e, node->children[0] ); ClipTriIntoTree_r( back, originalTri, e, node->children[1] ); return; } //common->Printf( "ClipTriIntoTree_r: leaf area = %i, opaque = %i, occupied = %i\n", node->area, node->occupied ); // if opaque leaf, don't add if( !node->opaque && node->area >= 0 ) { mapTri_t* list; int planeNum; idPlane plane; textureVectors_t texVec; list = WindingToTriList( w, originalTri ); PlaneForTri( originalTri, plane ); planeNum = FindFloatPlane( plane ); TexVecForTri( &texVec, originalTri ); AddTriListToArea( e, list, planeNum, node->area, &texVec ); } delete w; return; }