/* ================== BuildSurfaces Returns a chain of all the external surfaces with one or more visible faces. ================== */ void BuildSurfaces( tree_t *tree ) { int i; face_t **f; face_t *count; surface_t *s; surface_t *surfhead; surfhead = NULL; for( i = 0, f = tree->validfaces; i < nummapplanes; i++, f++ ) { if( !*f ) continue; // nothing left on this plane // create a new surface to hold the faces on this plane s = AllocSurface (); s->planenum = i; s->next = surfhead; surfhead = s; s->faces = *f; for( count = s->faces; count; count = count->next ) numcsgmergefaces++; CalcSurfaceInfo( s ); // bounding box and flags } tree->surfaces = surfhead; }
/* ================== DivideSurface ================== */ void DivideSurface (surface_t *in, dplane_t *split, surface_t **front, surface_t **back) { face_t *facet, *next; face_t *frontlist, *backlist; face_t *frontfrag, *backfrag; surface_t *news; dplane_t *inplane; inplane = &dplanes[in->planenum]; // parallel case is easy if (inplane->normal[0] == split->normal[0] && inplane->normal[1] == split->normal[1] && inplane->normal[2] == split->normal[2]) { if (inplane->dist > split->dist) { *front = in; *back = NULL; } else if (inplane->dist < split->dist) { *front = NULL; *back = in; } else { // split the surface into front and back frontlist = NULL; backlist = NULL; for (facet = in->faces ; facet ; facet = next) { next = facet->next; if (facet->planenum & 1) { facet->next = backlist; backlist = facet; } else { facet->next = frontlist; frontlist = facet; } } goto makesurfs; } return; } // do a real split. may still end up entirely on one side // OPTIMIZE: use bounding box for fast test frontlist = NULL; backlist = NULL; for (facet = in->faces ; facet ; facet = next) { next = facet->next; SplitFace (facet, split, &frontfrag, &backfrag); if (frontfrag) { frontfrag->next = frontlist; frontlist = frontfrag; } if (backfrag) { backfrag->next = backlist; backlist = backfrag; } } // if nothing actually got split, just move the in plane makesurfs: if (frontlist == NULL) { *front = NULL; *back = in; in->faces = backlist; return; } if (backlist == NULL) { *front = in; *back = NULL; in->faces = frontlist; return; } // stuff got split, so allocate one new surface and reuse in news = AllocSurface (); *news = *in; news->faces = backlist; *back = news; in->faces = frontlist; *front = in; // recalc bboxes and flags CalcSurfaceInfo (news); CalcSurfaceInfo (in); }
/* ================== DividePlane ================== */ void DividePlane (surface_t *in, plane_t *split, surface_t **front, surface_t **back) { face_t *facet, *next; face_t *frontlist, *backlist; face_t *frontfrag, *backfrag; surface_t *news; plane_t *inplane; inplane = &planes[in->planenum]; // parallel case is easy if (VectorCompare (inplane->normal, split->normal)) { // check for exactly on node if (inplane->dist == split->dist) { // divide the facets to the front and back sides news = AllocSurface (); *news = *in; facet=in->faces; in->faces = NULL; news->faces = NULL; in->onnode = news->onnode = true; for ( ; facet ; facet=next) { next = facet->next; if (facet->planeside == 1) { facet->next = news->faces; news->faces = facet; } else { facet->next = in->faces; in->faces = facet; } } if (in->faces) *front = in; else *front = NULL; if (news->faces) *back = news; else *back = NULL; return; } if (inplane->dist > split->dist) { *front = in; *back = NULL; } else { *front = NULL; *back = in; } return; } // do a real split. may still end up entirely on one side // OPTIMIZE: use bounding box for fast test frontlist = NULL; backlist = NULL; for (facet = in->faces ; facet ; facet = next) { next = facet->next; SplitFace (facet, split, &frontfrag, &backfrag); if (frontfrag) { frontfrag->next = frontlist; frontlist = frontfrag; } if (backfrag) { backfrag->next = backlist; backlist = backfrag; } } // if nothing actually got split, just move the in plane if (frontlist == NULL) { *front = NULL; *back = in; in->faces = backlist; return; } if (backlist == NULL) { *front = in; *back = NULL; in->faces = frontlist; return; } // stuff got split, so allocate one new plane and reuse in news = AllocSurface (); *news = *in; news->faces = backlist; *back = news; in->faces = frontlist; *front = in; // recalc bboxes and flags CalcSurfaceInfo (news); CalcSurfaceInfo (in); }