/* ================== BuildSurfaces Returns a chain of all the external surfaces with one or more visible faces. ================== */ surface_t *BuildSurfaces (void) { face_t **f; face_t *count; int i; surface_t *s; surface_t *surfhead; surfhead = NULL; f = validfaces; for (i = 0 ; i < numbrushplanes ; 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) csgmergefaces++; CalcSurfaceInfo (s); // bounding box and flags } return surfhead; }
/* 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 ================== */ static 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 = &pPlanes[in->planenum]; *front = *back = NULL; // parallel case is easy if (VectorCompare(inplane->normal, split->normal)) { // check for exactly on node if (inplane->dist == split->dist) { facet = in->faces; in->faces = NULL; in->onnode = true; // divide the facets to the front and back sides news = AllocMem(SURFACE, 1, true); *news = *in; // Prepend each face in facet list to either in or news lists 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 FreeMem(in, SURFACE, 1); if (news->faces) *back = news; else FreeMem(news, SURFACE, 1); return; } if (inplane->dist > split->dist) *front = in; else *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) { *back = in; in->faces = backlist; return; } if (backlist == NULL) { *front = in; in->faces = frontlist; return; } // stuff got split, so allocate one new plane and reuse in news = AllocMem(SURFACE, 1, true); *news = *in; news->faces = backlist; *back = news; in->faces = frontlist; *front = in; // recalc bboxes and flags CalcSurfaceInfo(news); CalcSurfaceInfo(in); }