Пример #1
0
/*
==================
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;
}
Пример #2
0
/*	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;
}
Пример #3
0
/*
==================
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);	
}
Пример #4
0
/*
==================
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);
}