/* ================== 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 ); } }
/* ===================== FilterMeshesIntoTree Mark the leafs as opaque and areaportals and put mesh fragments in each leaf so portal surfaces can be matched to materials ===================== */ void FilterMeshesIntoTree( uEntity_t* e ) { uBrush_t* b; primitive_t* prim; mapTri_t* tri; int r; int c_unique, c_clusters; common->Printf( "----- FilterMeshesIntoTree -----\n" ); c_unique = 0; c_clusters = 0; for( prim = e->primitives ; prim ; prim = prim->next ) { b = prim->brush; if( !b ) { // add BSP triangles for( tri = prim->bsptris ; tri ; tri = tri->next ) { idWinding* w = WindingForTri( tri ); c_unique++; r = FilterMeshesIntoTree_r( w, tri, e->tree->headnode ); c_clusters += r; } continue; } } common->Printf( "%5i total BSP triangles\n", c_unique ); common->Printf( "%5i cluster references\n", c_clusters ); }
/* ================== ClipTriList ================== */ void ClipTriList( const mapTri_t *list, const idPlane &plane, float epsilon, mapTri_t **front, mapTri_t **back ) { const mapTri_t *tri; mapTri_t *newList; idWinding *w, *frontW, *backW; *front = NULL; *back = NULL; for ( tri = list ; tri ; tri = tri->next ) { w = WindingForTri( tri ); w->Split( plane, epsilon, &frontW, &backW ); newList = WindingToTriList( frontW, tri ); *front = MergeTriLists( *front, newList ); newList = WindingToTriList( backW, tri ); *back = MergeTriLists( *back, newList ); delete w; } }
/* ================= ClipTriByLight Carves a triangle by the frustom planes of a light, producing a (possibly empty) list of triangles on the inside and outside. The original triangle is not modified. If no clipping is required, the result will be a copy of the original. If clipping was required, the outside fragments will be planar clips, which will benefit from re-optimization. ================= */ static void ClipTriByLight( const mapLight_t *light, const mapTri_t *tri, mapTri_t **in, mapTri_t **out ) { idWinding *inside, *oldInside; idWinding *outside[6]; bool hasOutside; int i; *in = NULL; *out = NULL; // clip this winding to the light inside = WindingForTri( tri ); hasOutside = false; for ( i = 0 ; i < 6 ; i++ ) { oldInside = inside; if ( oldInside ) { oldInside->Split( light->def.frustum[i], 0, &outside[i], &inside ); delete oldInside; } else { outside[i] = NULL; } if ( outside[i] ) { hasOutside = true; } } if ( !inside ) { // the entire winding is outside this light // free the clipped fragments for ( i = 0 ; i < 6 ; i++ ) { if ( outside[i] ) { delete outside[i]; } } *out = CopyMapTri( tri ); (*out)->next = NULL; return; } if ( !hasOutside ) { // the entire winding is inside this light // free the inside copy delete inside; *in = CopyMapTri( tri ); (*in)->next = NULL; return; } // the winding is split *in = WindingToTriList( inside, tri ); delete inside; // combine all the outside fragments for ( i = 0 ; i < 6 ; i++ ) { if ( outside[i] ) { mapTri_t *list; list = WindingToTriList( outside[i], tri ); delete outside[i]; *out = MergeTriLists( *out, list ); } } }