Esempio n. 1
0
//===========================================================================
// Returns a single brush made up by the intersection of the
// two provided brushes, or NULL if they are disjoint.
//
// The originals are undisturbed.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *IntersectBrush( bspbrush_t *a, bspbrush_t *b ) {
	int i;
	bspbrush_t  *front, *back;
	bspbrush_t  *in;

	in = a;
	for ( i = 0 ; i < b->numsides && in ; i++ )
	{
		SplitBrush( in, b->sides[i].planenum, &front, &back );
//		SplitBrush2(in, b->sides[i].planenum, &front, &back);
		if ( in != a ) {
			FreeBrush( in );
		}
		if ( front ) {
			FreeBrush( front );
		}
		in = back;
	} //end for

	if ( in == a ) {
		return NULL;
	}

	in->next = NULL;
	return in;
} //end of the function IntersectBrush
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Purpose: Recursively filter a brush through the tree
// Input  : *node - 
//			*brush - 
//-----------------------------------------------------------------------------
void MergeBrush_r( node_t *node, bspbrush_t *brush )
{
	if ( node->planenum == PLANENUM_LEAF )
	{
		if ( node->contents & CONTENTS_SOLID )
		{
			FreeBrush( brush );
		}
		else
		{
			AddBrushToLeaf( node, brush );
		}
		return;
	}

	bspbrush_t *front, *back;
	SplitBrush( brush, node->planenum, &front, &back );
	FreeBrush( brush );

	if ( front )
	{
		MergeBrush_r( node->children[0], front );
	}
	if ( back )
	{
		MergeBrush_r( node->children[1], back );
	}
}
Esempio n. 3
0
//===========================================================================
// Returns a list of brushes that remain after B is subtracted from A.
// May by empty if A is contained inside B.
// The originals are undisturbed.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b)
{	// a - b = out (list)
	int		i;
	bspbrush_t	*front, *back;
	bspbrush_t	*out, *in;

	in = a;
	out = NULL;
	for (i = 0; i < b->numsides && in; i++)
	{
		SplitBrush2(in, b->sides[i].planenum, &front, &back);
		if (in != a) FreeBrush(in);
		if (front)
		{	// add to list
			front->next = out;
			out = front;
		} //end if
		in = back;
	} //end for
	if (in)
	{
		FreeBrush (in);
	} //end if
	else
	{	// didn't really intersect
		FreeBrushList (out);
		return a;
	} //end else
	return out;
} //end of the function SubtractBrush
Esempio n. 4
0
/*
================
FreeDMapFile
================
*/
void FreeDMapFile( void )
{
    int		i, j;

    FreeBrush( buildBrush );
    buildBrush = NULL;

    // free the entities and brushes
    for( i = 0; i < dmapGlobals.num_entities; i++ )
    {
        uEntity_t	*ent;
        primitive_t	*prim, *nextPrim;

        ent = &dmapGlobals.uEntities[i];

        FreeTree( ent->tree );

        // free primitives
        for( prim = ent->primitives; prim; prim = nextPrim )
        {
            nextPrim = prim->next;

            if( prim->brush )
            {
                FreeBrush( prim->brush );
            }

            if( prim->tris )
            {
                FreeTriList( prim->tris );
            }
            Mem_Free( prim );
        }

        // free area surfaces
        if( ent->areas )
        {
            for( j = 0; j < ent->numAreas; j++ )
            {
                uArea_t	*area;

                area = &ent->areas[j];
                FreeOptimizeGroupList( area->groups );

            }
            Mem_Free( ent->areas );
        }
    }
    Mem_Free( dmapGlobals.uEntities );

    dmapGlobals.num_entities = 0;

    // free the map lights
    for( i = 0; i < dmapGlobals.mapLights.Num(); i++ )
    {
        R_FreeLightDefDerivedData( &dmapGlobals.mapLights[i]->def );
    }
    dmapGlobals.mapLights.DeleteContents( true );
}
Esempio n. 5
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *MergeBrushes(bspbrush_t *brushlist)
{
	int nummerges, merged;
	bspbrush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
	bspbrush_t *lastb2;

	if (!brushlist) return NULL;

	qprintf("%5d brushes merged", nummerges = 0);
	do
	{
		for (tail = brushlist; tail; tail = tail->next)
		{
			if (!tail->next) break;
		} //end for
		merged = 0;
		newbrushlist = NULL;
		for (b1 = brushlist; b1; b1 = brushlist)
		{
			lastb2 = b1;
			for (b2 = b1->next; b2; b2 = b2->next)
			{
				//if the brushes don't have the same contents
				if (b1->original->contents != b2->original->contents ||
					b1->original->expansionbbox != b2->original->expansionbbox) newbrush = NULL;
				else newbrush = TryMergeBrushes(b1, b2);
				if (newbrush)
				{
					tail->next = newbrush;
					lastb2->next = b2->next;
					brushlist = brushlist->next;
					FreeBrush(b1);
					FreeBrush(b2);
					for (tail = brushlist; tail; tail = tail->next)
					{
						if (!tail->next) break;
					} //end for
					merged++;
					qprintf("\r%5d", nummerges++);
					break;
				} //end if
				lastb2 = b2;
			} //end for
			//if b1 can't be merged with any of the other brushes
			if (!b2)
			{
				brushlist = brushlist->next;
				//keep b1
				b1->next = newbrushlist;
				newbrushlist = b1;
			} //end else
		} //end for
		brushlist = newbrushlist;
	} while(merged);
	qprintf("\n");
	return newbrushlist;
} //end of the function MergeBrushes
Esempio n. 6
0
/*
============
PruneNodes_r
============
*/
void PruneNodes_r (node_t *node)
{
	bspbrush_t		*b, *next;
//	portal_t	*p, *nextp;
//	int			s;

	if (node->planenum == PLANENUM_LEAF)
		return;
	PruneNodes_r (node->children[0]);
	PruneNodes_r (node->children[1]);

	if ( (node->children[0]->contents & CONTENTS_SOLID)
	&& (node->children[1]->contents & CONTENTS_SOLID) )
	{
		if (node->faces)
			Error ("node->faces seperating CONTENTS_SOLID");
		if (node->children[0]->faces || node->children[1]->faces)
			Error ("!node->faces with children");

		// FIXME: free stuff

		node->pruned = true;
		node->planenum = PLANENUM_LEAF;
		node->contents = CONTENTS_SOLID;
		node->detail_seperator = false;

		if (node->brushlist)
			Error ("PruneNodes: node->brushlist");

		// combine brush lists
		node->brushlist = node->children[1]->brushlist;

		for (b=node->children[0]->brushlist ; b ; b=next)
		{
			next = b->next;
			b->next = node->brushlist;
			node->brushlist = b;
		}

		node->children[0]->brushlist = NULL;
		node->children[1]->brushlist = NULL;

		if(node->children[0]->volume != NULL)
		{
			FreeBrush(node->children[0]->volume);
			node->children[0]->volume = NULL;
		}

		if(node->children[1]->volume != NULL)
		{
			FreeBrush(node->children[1]->volume);
			node->children[1]->volume = NULL;
		}

		c_pruned++;
	}
}
Esempio n. 7
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
void Tree_Free_r( node_t *node ) {
//	face_t *f, *nextf;
	bspbrush_t *brush, *nextbrush;

	//free children
	if ( node->planenum != PLANENUM_LEAF ) {
		Tree_Free_r( node->children[0] );
		Tree_Free_r( node->children[1] );
	} //end if
	  //free bspbrushes
//	FreeBrushList (node->brushlist);
	for ( brush = node->brushlist; brush; brush = nextbrush )
	{
		nextbrush = brush->next;
#ifdef ME
		freedtreemem += MemorySize( brush );
#endif //ME
		FreeBrush( brush );
	} //end for
	node->brushlist = NULL;

	/*
	NOTE: only used when creating Q2 bsp
	// free faces
	for (f = node->faces; f; f = nextf)
	{
		nextf = f->next;
#ifdef ME
		if (f->w) freedtreemem += MemorySize(f->w);
		freedtreemem += sizeof(face_t);
#endif //ME
		FreeFace(f);
	} //end for
	*/

	// free the node
	if ( node->volume ) {
#ifdef ME
		freedtreemem += MemorySize( node->volume );
#endif //ME
		FreeBrush( node->volume );
	} //end if

	if ( numthreads == 1 ) {
		c_nodes--;
	}
#ifdef ME
	freedtreemem += MemorySize( node );
#endif //ME
	FreeMemory( node );
} //end of the function Tree_Free_r
Esempio n. 8
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
{
	bspbrush_t	*front, *back;
	qboolean	good;

	SplitBrush (node->volume, pnum, &front, &back);

	good = (front && back);

	if (front) FreeBrush (front);
	if (back) FreeBrush (back);

	return good;
} //end of the function CheckPlaneAgaintsVolume
Esempio n. 9
0
/*
====================
FilterBrushIntoTree_r

====================
*/
int FilterBrushIntoTree_r( uBrush_t *b, node_t *node )
{
	uBrush_t		*front, *back;
	int				c;
	
	if( !b )
	{
		return 0;
	}
	
	// add it to the leaf list
	if( node->planenum == PLANENUM_LEAF )
	{
		b->next = node->brushlist;
		node->brushlist = b;
		
		// classify the leaf by the structural brush
		if( b->opaque )
		{
			node->opaque = true;
		}
		return 1;
	}
	
	// split it by the node plane
	SplitBrush( b, node->planenum, &front, &back );
	FreeBrush( b );
	
	c = 0;
	c += FilterBrushIntoTree_r( front, node->children[0] );
	c += FilterBrushIntoTree_r( back, node->children[1] );
	
	return c;
}
Esempio n. 10
0
static bool CheckPlaneAgainstVolume (uint16_t pnum, const bspbrush_t* volume)
{
		bspbrush_t* front, *back;
		bool good;

		SplitBrush(volume, pnum, &front, &back);

		good = (front && back);

		if (front)
				FreeBrush(front);
		if (back)
				FreeBrush(back);

		return good;
}
Esempio n. 11
0
/*
   =============
   FreeTree_r
   =============
 */
void FreeTree_r( node_t *node ){
	face_t      *f, *nextf;

	// free children
	if ( node->planenum != PLANENUM_LEAF ) {
		FreeTree_r( node->children[0] );
		FreeTree_r( node->children[1] );
	}

	// free bspbrushes
	FreeBrushList( node->brushlist );

	// free faces
	for ( f = node->faces ; f ; f = nextf )
	{
		nextf = f->next;
		FreeFace( f );
	}

	// free the node
	if ( node->volume ) {
		FreeBrush( node->volume );
	}

	if ( numthreads == 1 ) {
		c_nodes--;
	}
	free( node );
}
Esempio n. 12
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void Q1_CreateMapBrushes(entity_t *mapent, int modelnum)
{
    bspbrush_t *brushlist, *brush, *nextbrush;
    int i;

    //create brushes from the model BSP tree
    brushlist = Q1_CreateBrushesFromBSP(modelnum);
    //texture the brushes and split them when necesary
    brushlist = Q1_TextureBrushes(brushlist, modelnum);
    //fix the contents textures of all brushes
    Q1_FixContentsTextures(brushlist);
    //
    if (!nobrushmerge)
    {
        brushlist = Q1_MergeBrushes(brushlist, modelnum);
        //brushlist = Q1_MergeBrushes(brushlist, modelnum);
    } //end if
    //
    if (!modelnum) qprintf("converting brushes to map brushes\n");
    if (!modelnum) qprintf("%5d brushes", i = 0);
    for (brush = brushlist; brush; brush = nextbrush)
    {
        nextbrush = brush->next;
        Q1_BSPBrushToMapBrush(brush, mapent);
        brush->next = NULL;
        FreeBrush(brush);
        if (!modelnum) qprintf("\r%5d", ++i);
    } //end for
    if (!modelnum) qprintf("\n");
} //end of the function Q1_CreateMapBrushes
Esempio n. 13
0
static void FreeTree_r (node_t *node)
{
	face_t *f, *nextf;

	/* free children */
	if (node->planenum != PLANENUM_LEAF) {
		FreeTree_r(node->children[0]);
		FreeTree_r(node->children[1]);
	}

	/* free bspbrushes */
	FreeBrushList(node->brushlist);

	/* free faces */
	for (f = node->faces; f; f = nextf) {
		nextf = f->next;
		FreeFace(f);
	}

	/* free the node */
	if (node->volume)
		FreeBrush(node->volume);

	if (threadstate.numthreads == 1)
		c_nodes--;
	Mem_Free(node);
}
Esempio n. 14
0
static _Bool CheckPlaneAgainstVolume(int32_t pnum, node_t *node) {
	brush_t *front, *back;
	_Bool good;

	SplitBrush(node->volume, pnum, &front, &back);

	good = (front && back);

	if (front) {
		FreeBrush(front);
	}
	if (back) {
		FreeBrush(back);
	}

	return good;
}
Esempio n. 15
0
/**
 * @sa AllocBrush
 * @sa CountBrushList
 */
void FreeBrushList (bspbrush_t* brushes)
{
	bspbrush_t* next;

	for (; brushes; brushes = next) {
		next = brushes->next;
		FreeBrush(brushes);
	}
}
Esempio n. 16
0
/*
================
FreeBrushList
================
*/
void FreeBrushList( uBrush_t *brushes )
{
	uBrush_t	*next;
	
	for( /**/; brushes; brushes = next )
	{
		next = brushes->next;
		FreeBrush( brushes );
	}
}
Esempio n. 17
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void FreeBrushList( bspbrush_t *brushes ) {
	bspbrush_t  *next;

	for ( ; brushes; brushes = next )
	{
		next = brushes->next;

		FreeBrush( brushes );
	} //end for
} //end of the function FreeBrushList
Esempio n. 18
0
//===========================================================================
// Any planes shared with the box edge will be set to no texinfo
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *ClipBrushToBox(bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
{
	int		i, j;
	bspbrush_t	*front,	*back;
	int		p;

	for (j=0 ; j<2 ; j++)
	{
		if (brush->maxs[j] > clipmaxs[j])
		{
			SplitBrush (brush, maxplanenums[j], &front, &back);
			if (front)
				FreeBrush (front);
			brush = back;
			if (!brush)
				return NULL;
		}
		if (brush->mins[j] < clipmins[j])
		{
			SplitBrush (brush, minplanenums[j], &front, &back);
			if (back)
				FreeBrush (back);
			brush = front;
			if (!brush)
				return NULL;
		}
	}

	// remove any colinear faces

	for (i=0 ; i<brush->numsides ; i++)
	{
		p = brush->sides[i].planenum & ~1;
		if (p == maxplanenums[0] || p == maxplanenums[1] 
			|| p == minplanenums[0] || p == minplanenums[1])
		{
			brush->sides[i].texinfo = TEXINFO_NODE;
			brush->sides[i].flags &= ~SFL_VISIBLE;
		}
	}
	return brush;
} //end of the function ClipBrushToBox
Esempio n. 19
0
File: brush.c Progetto: kellyrm/Q1
/*
=====================
FreeBrushsetBrushes
=====================
*/
void FreeBrushsetBrushes(void)
{
	brush_t *pBrush, *pNext;

	for (pBrush = brushset->brushes; pBrush; pBrush = pNext)
	{
		pNext = pBrush->next;
		FreeBrushFaces(pBrush->faces);
		FreeBrush(pBrush);
	}
}
Esempio n. 20
0
void FreeBrushList( brush_t *brushes ){
	brush_t     *next;


	/* walk brush list */
	for ( ; brushes != NULL; brushes = next )
	{
		next = brushes->next;
		FreeBrush( brushes );
	}
}
Esempio n. 21
0
/*
  ====================
  FreeBrushList

  ====================
*/
void FreeBrushList( cbspbrush_t *list )
{
	cbspbrush_t	*next;

	if ( !list )
		return;

	for ( ; list ;list = next )
	{
		next = list->next;
		FreeBrush( list );
	}
}
Esempio n. 22
0
File: brush.c Progetto: otty/cake3
/*
====================
FilterBrushIntoTree_r
====================
*/
int FilterBrushIntoTree_r(bspBrush_t * b, node_t * node)
{
	bspBrush_t     *front, *back;
	int             c;

	if(!b)
	{
		return 0;
	}

	// add it to the leaf list
	if(node->planenum == PLANENUM_LEAF)
	{
		b->next = node->brushlist;
		node->brushlist = b;

		// classify the leaf by the structural brush
		if(!b->detail)
		{
			if(b->opaque)
			{
				node->opaque = qtrue;
				node->areaportal = qfalse;
			}
			else if(b->contents & CONTENTS_AREAPORTAL)
			{
				if(!node->opaque)
				{
					node->areaportal = qtrue;
				}
			}
		}

		return 1;
	}

	// split it by the node plane
	SplitBrush(b, node->planenum, &front, &back);
	FreeBrush(b);

	c = 0;
	c += FilterBrushIntoTree_r(front, node->children[0]);
	c += FilterBrushIntoTree_r(back, node->children[1]);

	return c;
}
Esempio n. 23
0
int FilterBrushIntoTree_r( brush_t *b, node_t *node )
{
    brush_t		*front, *back;
    int			c;

    /* dummy check */
    if( b == NULL )
        return 0;

    /* add it to the leaf list */
    if( node->planenum == PLANENUM_LEAF )
    {
        /* something somewhere is hammering brushlist */
        b->next = node->brushlist;
        node->brushlist = b;

        /* classify the leaf by the structural brush */
        if( !b->detail )
        {
            if( b->opaque )
            {
                node->opaque = qtrue;
                node->areaportal = qfalse;
            }
            else if( b->compileFlags & C_AREAPORTAL )
            {
                if( !node->opaque )
                    node->areaportal = qtrue;
            }
        }

        return 1;
    }

    /* split it by the node plane */
    c = b->numsides;
    SplitBrush( b, node->planenum, &front, &back );
    FreeBrush( b );

    c = 0;
    c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
    c += FilterBrushIntoTree_r( back, node->children[ 1 ] );

    return c;
}
Esempio n. 24
0
//===========================================================================
// Builds a new list that doesn't hold the given brush
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *CullList( bspbrush_t *list, bspbrush_t *skip1 ) {
	bspbrush_t  *newlist;
	bspbrush_t  *next;

	newlist = NULL;

	for ( ; list ; list = next )
	{
		next = list->next;
		if ( list == skip1 ) {
			FreeBrush( list );
			continue;
		}
		list->next = newlist;
		newlist = list;
	}
	return newlist;
} //end of the function CullList
Esempio n. 25
0
/*
=============
FreeTree_r
=============
*/
void FreeTree_r (node_t *node)
{
	// free children
	if (node->planenum != PLANENUM_LEAF)
	{
		FreeTree_r (node->children[0]);
		FreeTree_r (node->children[1]);
	}

	// free bspbrushes
	FreeBrushList (node->brushlist);

	// free the node
	if (node->volume)
		FreeBrush (node->volume);

	if (numthreads == 1)
		c_nodes--;
	free (node);
}
Esempio n. 26
0
/**
 * @brief Generates two new brushes, leaving the original unchanged
 */
void SplitBrush (const bspbrush_t* brush, uint16_t planenum, bspbrush_t** front, bspbrush_t** back)
{
	bspbrush_t* b[2];
	int i, j;
	winding_t* w, *cw[2], *midwinding;
	plane_t* plane;
	float d_front, d_back;

	*front = *back = nullptr;
	plane = &mapplanes[planenum];

	/* check all points */
	d_front = d_back = 0;
	for (i = 0; i < brush->numsides; i++) {
		w = brush->sides[i].winding;
		if (!w)
			continue;
		for (j = 0; j < w->numpoints; j++) {
			const float d = DotProduct(w->p[j], plane->normal) - plane->dist;
			if (d > 0 && d > d_front)
				d_front = d;
			else if (d < 0 && d < d_back)
				d_back = d;
		}
	}
	if (d_front < 0.1) { /* PLANESIDE_EPSILON) */
		/* only on back */
		*back = CopyBrush(brush);
		return;
	}
	if (d_back > -0.1) { /* PLANESIDE_EPSILON) */
		/* only on front */
		*front = CopyBrush(brush);
		return;
	}

	/* create a new winding from the split plane */
	w = BaseWindingForPlane(plane->normal, plane->dist);
	for (i = 0; i < brush->numsides && w; i++) {
		plane_t* plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); /* PLANESIDE_EPSILON); */
	}

	/* the brush isn't really split */
	if (!w || WindingIsTiny(w)) {
		const int side = BrushMostlyOnSide(brush, plane);
		if (side == PSIDE_FRONT)
			*front = CopyBrush(brush);
		else if (side == PSIDE_BACK)
			*back = CopyBrush(brush);
		return;
	}

	if (WindingIsHuge(w)) {
		/** @todo Print brush and entnum either of the brush that was splitted
		 * or the plane that was used as splitplane */
		Com_Printf("WARNING: Large winding\n");
	}

	midwinding = w;

	/* split it for real */
	for (i = 0; i < 2; i++) {
		b[i] = AllocBrush(brush->numsides + 1);
		b[i]->original = brush->original;
	}

	/* split all the current windings */
	for (i = 0; i < brush->numsides; i++) {
		const side_t* s = &brush->sides[i];
		w = s->winding;
		if (!w)
			continue;
		ClipWindingEpsilon(w, plane->normal, plane->dist,
			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
		for (j = 0; j < 2; j++) {
			side_t* cs;

			if (!cw[j])
				continue;

			cs = &b[j]->sides[b[j]->numsides];
			b[j]->numsides++;
			*cs = *s;

			cs->winding = cw[j];
			cs->tested = false;
		}
	}

	/* see if we have valid polygons on both sides */
	for (i = 0; i < 2; i++) {
		BoundBrush(b[i]);
		for (j = 0; j < 3; j++) {
			if (b[i]->mins[j] < -MAX_WORLD_WIDTH || b[i]->maxs[j] > MAX_WORLD_WIDTH) {
				/** @todo Print brush and entnum either of the brush that was split
				 * or the plane that was used as splitplane */
				Verb_Printf(VERB_EXTRA, "bogus brush after clip\n");
				break;
			}
		}

		if (b[i]->numsides < 3 || j < 3) {
			FreeBrush(b[i]);
			b[i] = nullptr;
		}
	}

	if (!(b[0] && b[1])) {
		/** @todo Print brush and entnum either of the brush that was splitted
		 * or the plane that was used as splitplane */
		if (!b[0] && !b[1])
			Verb_Printf(VERB_EXTRA, "split removed brush\n");
		else
			Verb_Printf(VERB_EXTRA, "split not on both sides\n");
		if (b[0]) {
			FreeBrush(b[0]);
			*front = CopyBrush(brush);
		}
		if (b[1]) {
			FreeBrush(b[1]);
			*back = CopyBrush(brush);
		}
		return;
	}

	/* add the midwinding to both sides */
	for (i = 0; i < 2; i++) {
		side_t* cs = &b[i]->sides[b[i]->numsides];
		b[i]->numsides++;

		cs->planenum = planenum ^ i ^ 1;
		cs->texinfo = TEXINFO_NODE;
		cs->visible = false;
		cs->tested = false;
		if (i == 0)
			cs->winding = CopyWinding(midwinding);
		else
			cs->winding = midwinding;
	}

	for (i = 0; i < 2; i++) {
		const vec_t v1 = BrushVolume(b[i]);
		if (v1 < 1.0) {
			FreeBrush(b[i]);
			b[i] = nullptr;
			/** @todo Print brush and entnum either of the brush that was splitted
			 * or the plane that was used as splitplane */
			Verb_Printf(VERB_EXTRA, "tiny volume after clip\n");
		}
	}

	*front = b[0];
	*back = b[1];
}
Esempio n. 27
0
void SplitBrush( bspbrush_t *brush, int planenum, bspbrush_t **front, bspbrush_t **back )
{
	bspbrush_t	*b[2];
	int			i, j;
	winding_t	*w, *cw[2], *midwinding;
	plane_t		*plane, *plane2;
	side_t		*s, *cs;
	float		d, d_front, d_back;

	*front = *back = NULL;
	plane = &g_MainMap->mapplanes[planenum];

	// check all points
	d_front = d_back = 0;
	for (i=0 ; i<brush->numsides ; i++)
	{
		w = brush->sides[i].winding;
		if (!w)
			continue;
		for (j=0 ; j<w->numpoints ; j++)
		{
			d = DotProduct (w->p[j], plane->normal) - plane->dist;
			if (d > 0 && d > d_front)
				d_front = d;
			if (d < 0 && d < d_back)
				d_back = d;
		}
	}

	if (d_front < 0.1) // PLANESIDE_EPSILON)
	{	// only on back
		*back = CopyBrush (brush);
		return;
	}
	if (d_back > -0.1) // PLANESIDE_EPSILON)
	{	// only on front
		*front = CopyBrush (brush);
		return;
	}


	// Move the CSG problem so that offset is at the origin
	// This gives us much better floating point precision in the clipping operations
	Vector offset = -0.5f * (brush->mins + brush->maxs);
	// create a new winding from the split plane

	w = BaseWindingForPlane (plane->normal, plane->dist + DotProduct(plane->normal,offset));
	for (i=0 ; i<brush->numsides && w ; i++)
	{
		plane2 = &g_MainMap->mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace (&w, plane2->normal, plane2->dist+DotProduct(plane2->normal,offset), 0); // PLANESIDE_EPSILON);
	}

	if (!w || WindingIsTiny (w) )
	{	// the brush isn't really split
		int		side;

		side = BrushMostlyOnSide (brush, plane);
		if (side == PSIDE_FRONT)
			*front = CopyBrush (brush);
		if (side == PSIDE_BACK)
			*back = CopyBrush (brush);
		return;
	}

	if (WindingIsHuge (w))
	{
		qprintf ("WARNING: huge winding\n");
	}

	TranslateWinding( w, -offset );
	midwinding = w;

    //
    //
	// split it for real
    //
    //

    //
    // allocate two new brushes referencing the original
    //
	for( i = 0; i < 2; i++ )
	{
		b[i] = AllocBrush( brush->numsides + 1 );
		b[i]->original = brush->original;
	}

    //
	// split all the current windings
    //
	for( i = 0; i < brush->numsides; i++ )
	{
        // get the current side
		s = &brush->sides[i];

        // get the sides winding
		w = s->winding;
		if( !w )
			continue;

        // clip the winding
		ClipWindingEpsilon_Offset( w, plane->normal, plane->dist, 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1], offset );

		for( j = 0; j < 2; j++ )
		{
            // does winding exist?
			if( !cw[j] )
				continue;
#if 0
			if (WindingIsTiny (cw[j]))
			{
				FreeWinding (cw[j]);
				continue;
			}
#endif

            //
            // create a clipped "side" with the new winding
            //
			cs = &b[j]->sides[b[j]->numsides];
			b[j]->numsides++;
			*cs = *s;
			cs->winding = cw[j];
			cs->tested = false;
            // save the original side information
            //cs->original = s->original;
		}
	}


	// see if we have valid polygons on both sides

	for (i=0 ; i<2 ; i++)
	{
		BoundBrush (b[i]);
		for (j=0 ; j<3 ; j++)
		{
			if (b[i]->mins[j] < MIN_COORD_INTEGER || b[i]->maxs[j] > MAX_COORD_INTEGER)
			{
				qprintf ("bogus brush after clip\n");
				break;
			}
		}

		if (b[i]->numsides < 3 || j < 3)
		{
			FreeBrush (b[i]);
			b[i] = NULL;
		}
	}

	if ( !(b[0] && b[1]) )
	{
		if (!b[0] && !b[1])
			qprintf ("split removed brush\n");
		else
			qprintf ("split not on both sides\n");
		if (b[0])
		{
			FreeBrush (b[0]);
			*front = CopyBrush (brush);
		}
		if (b[1])
		{
			FreeBrush (b[1]);
			*back = CopyBrush (brush);
		}
		return;
	}

	// add the midwinding to both sides
	for (i=0 ; i<2 ; i++)
	{
		cs = &b[i]->sides[b[i]->numsides];
		b[i]->numsides++;

		cs->planenum = planenum^i^1;
		cs->texinfo = TEXINFO_NODE;

        // initialize the displacement map index
		cs->pMapDisp = NULL;

        cs->visible = false;
		cs->tested = false;
		if (i==0)
			cs->winding = CopyWinding (midwinding);
		else
			cs->winding = midwinding;
	}

{
	vec_t	v1;
	int		i;

	for (i=0 ; i<2 ; i++)
	{
		v1 = BrushVolume (b[i]);
		if (v1 < 1.0)
		{
			FreeBrush (b[i]);
			b[i] = NULL;
//			qprintf ("tiny volume after clip\n");
		}
	}
}

	*front = b[0];
	*back = b[1];
}
Esempio n. 28
0
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){
	brush_t     *b[2];
	int i, j;
	winding_t   *w, *cw[2], *midwinding;
	plane_t     *plane, *plane2;
	side_t      *s, *cs;
	float d, d_front, d_back;


	*front = NULL;
	*back = NULL;
	plane = &mapplanes[planenum];

	// check all points
	d_front = d_back = 0;
	for ( i = 0 ; i < brush->numsides ; i++ )
	{
		w = brush->sides[i].winding;
		if ( !w ) {
			continue;
		}
		for ( j = 0 ; j < w->numpoints ; j++ )
		{
			d = DotProduct( w->p[j], plane->normal ) - plane->dist;
			if ( d > 0 && d > d_front ) {
				d_front = d;
			}
			if ( d < 0 && d < d_back ) {
				d_back = d;
			}
		}
	}

	if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
		// only on back
		*back = CopyBrush( brush );
		return;
	}

	if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
		// only on front
		*front = CopyBrush( brush );
		return;
	}

	// create a new winding from the split plane
	w = BaseWindingForPlane( plane->normal, plane->dist );
	for ( i = 0 ; i < brush->numsides && w ; i++ )
	{
		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace( &w, plane2->normal, plane2->dist, 0 ); // PLANESIDE_EPSILON);
	}

	if ( !w || WindingIsTiny( w ) ) { // the brush isn't really split
		int side;

		side = BrushMostlyOnSide( brush, plane );
		if ( side == PSIDE_FRONT ) {
			*front = CopyBrush( brush );
		}
		if ( side == PSIDE_BACK ) {
			*back = CopyBrush( brush );
		}
		return;
	}

	if ( WindingIsHuge( w ) ) {
		Sys_FPrintf( SYS_VRB,"WARNING: huge winding\n" );
	}

	midwinding = w;

	// split it for real

	for ( i = 0 ; i < 2 ; i++ )
	{
		b[i] = AllocBrush( brush->numsides + 1 );
		memcpy( b[i], brush, sizeof( brush_t ) - sizeof( brush->sides ) );
		b[i]->numsides = 0;
		b[i]->next = NULL;
		b[i]->original = brush->original;
	}

	// split all the current windings

	for ( i = 0 ; i < brush->numsides ; i++ )
	{
		s = &brush->sides[i];
		w = s->winding;
		if ( !w ) {
			continue;
		}
		/* strict, in parallel case we get the face back because it also is the midwinding */
		ClipWindingEpsilonStrict( w, plane->normal, plane->dist,
							0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1] );
		for ( j = 0 ; j < 2 ; j++ )
		{
			if ( !cw[j] ) {
				continue;
			}
			cs = &b[j]->sides[b[j]->numsides];
			b[j]->numsides++;
			*cs = *s;
			cs->winding = cw[j];
		}
	}


	// see if we have valid polygons on both sides
	for ( i = 0 ; i < 2 ; i++ )
	{
		if ( b[i]->numsides < 3 || !BoundBrush( b[i] ) ) {
			if ( b[i]->numsides >= 3 ) {
				Sys_FPrintf( SYS_VRB,"bogus brush after clip\n" );
			}
			FreeBrush( b[i] );
			b[i] = NULL;
		}
	}

	if ( !( b[0] && b[1] ) ) {
		if ( !b[0] && !b[1] ) {
			Sys_FPrintf( SYS_VRB,"split removed brush\n" );
		}
		else{
			Sys_FPrintf( SYS_VRB,"split not on both sides\n" );
		}
		if ( b[0] ) {
			FreeBrush( b[0] );
			*front = CopyBrush( brush );
		}
		if ( b[1] ) {
			FreeBrush( b[1] );
			*back = CopyBrush( brush );
		}
		return;
	}

	// add the midwinding to both sides
	for ( i = 0 ; i < 2 ; i++ )
	{
		cs = &b[i]->sides[b[i]->numsides];
		b[i]->numsides++;

		cs->planenum = planenum ^ i ^ 1;
		cs->shaderInfo = NULL;
		if ( i == 0 ) {
			cs->winding = CopyWinding( midwinding );
		}
		else{
			cs->winding = midwinding;
		}
	}

	{
		vec_t v1;
		int i;


		for ( i = 0 ; i < 2 ; i++ )
		{
			v1 = BrushVolume( b[i] );
			if ( v1 < 1.0 ) {
				FreeBrush( b[i] );
				b[i] = NULL;
				//			Sys_FPrintf (SYS_VRB,"tiny volume after clip\n");
			}
		}
	}

	*front = b[0];
	*back = b[1];
}
Esempio n. 29
0
/*
================
SplitBrush

Generates two new brushes, leaving the original
unchanged
================
*/
void SplitBrush (bspbrush_t *brush, int planenum,
	bspbrush_t **front, bspbrush_t **back)
{
	bspbrush_t	*b[2];
	int			i, j;
	winding_t	*w, *cw[2], *midwinding;
	plane_t		*plane, *plane2;
	side_t		*s, *cs;
	float		d, d_front, d_back;

	*front = *back = NULL;
	plane = &mapplanes[planenum];

	// check all points
	d_front = d_back = 0;
	for (i=0 ; i<brush->numsides ; i++)
	{
		w = brush->sides[i].winding;
		if (!w)
			continue;
		for (j=0 ; j<w->numpoints ; j++)
		{
			d = DotProduct (w->p[j], plane->normal) - plane->dist;
			if (d > 0 && d > d_front)
				d_front = d;
			if (d < 0 && d < d_back)
				d_back = d;
		}
	}
	if (d_front < 0.1) // PLANESIDE_EPSILON)
	{	// only on back
		*back = CopyBrush (brush);
		return;
	}
	if (d_back > -0.1) // PLANESIDE_EPSILON)
	{	// only on front
		*front = CopyBrush (brush);
		return;
	}

	// create a new winding from the split plane

	w = BaseWindingForPlane (plane->normal, plane->dist);
	for (i=0 ; i<brush->numsides && w ; i++)
	{
		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
	}

	if (!w || WindingIsTiny (w) )
	{	// the brush isn't really split
		int		side;

		side = BrushMostlyOnSide (brush, plane);
		if (side == PSIDE_FRONT)
			*front = CopyBrush (brush);
		if (side == PSIDE_BACK)
			*back = CopyBrush (brush);
		return;
	}

	if (WindingIsHuge (w))
	{
		qprintf ("WARNING: huge winding\n");
	}

	midwinding = w;

	// split it for real

	for (i=0 ; i<2 ; i++)
	{
		b[i] = AllocBrush (brush->numsides+1);
		b[i]->original = brush->original;
	}

	// split all the current windings

	for (i=0 ; i<brush->numsides ; i++)
	{
		s = &brush->sides[i];
		w = s->winding;
		if (!w)
			continue;
		ClipWindingEpsilon (w, plane->normal, plane->dist,
			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
		for (j=0 ; j<2 ; j++)
		{
			if (!cw[j])
				continue;
#if 0
			if (WindingIsTiny (cw[j]))
			{
				FreeWinding (cw[j]);
				continue;
			}
#endif
			cs = &b[j]->sides[b[j]->numsides];
			b[j]->numsides++;
			*cs = *s;
//			cs->planenum = s->planenum;
//			cs->texinfo = s->texinfo;
//			cs->visible = s->visible;
//			cs->original = s->original;
			cs->winding = cw[j];
			cs->tested = false;
		}
	}


	// see if we have valid polygons on both sides

	for (i=0 ; i<2 ; i++)
	{
		BoundBrush (b[i]);
		for (j=0 ; j<3 ; j++)
		{
			if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
			{
				qprintf ("bogus brush after clip\n");
				break;
			}
		}

		if (b[i]->numsides < 3 || j < 3)
		{
			FreeBrush (b[i]);
			b[i] = NULL;
		}
	}

	if ( !(b[0] && b[1]) )
	{
		if (!b[0] && !b[1])
			qprintf ("split removed brush\n");
		else
			qprintf ("split not on both sides\n");
		if (b[0])
		{
			FreeBrush (b[0]);
			*front = CopyBrush (brush);
		}
		if (b[1])
		{
			FreeBrush (b[1]);
			*back = CopyBrush (brush);
		}
		return;
	}

	// add the midwinding to both sides
	for (i=0 ; i<2 ; i++)
	{
		cs = &b[i]->sides[b[i]->numsides];
		b[i]->numsides++;

		cs->planenum = planenum^i^1;
		cs->texinfo = TEXINFO_NODE;
		cs->visible = false;
		cs->tested = false;
		if (i==0)
			cs->winding = CopyWinding (midwinding);
		else
			cs->winding = midwinding;
	}

{
	vec_t	v1;
	int		i;

	for (i=0 ; i<2 ; i++)
	{
		v1 = BrushVolume (b[i]);
		if (v1 < 1.0)
		{
			FreeBrush (b[i]);
			b[i] = NULL;
//			qprintf ("tiny volume after clip\n");
		}
	}
}

	*front = b[0];
	*back = b[1];
}
Esempio n. 30
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *Q1_TextureBrushes(bspbrush_t *brushlist, int modelnum)
{
    float area, largestarea;
    int i, n, texinfonum, sn, numbrushes, ofs;
    int bestfacenum, sidenodenum;
    side_t *side;
    q1_dmiptexlump_t *miptexlump;
    q1_miptex_t *miptex;
    bspbrush_t *brush, *nextbrush, *prevbrush, *newbrushes, *brushlistend;
    vec_t defaultvec[4] = {1, 0, 0, 0};

    if (!modelnum) qprintf("texturing brushes\n");
    if (!modelnum) qprintf("%5d brushes", numbrushes = 0);
    //get a pointer to the last brush in the list
    for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
    {
        if (!brushlistend->next) break;
    } //end for
    //there's no previous brush when at the start of the list
    prevbrush = NULL;
    //go over the brush list
    for (brush = brushlist; brush; brush = nextbrush)
    {
        nextbrush = brush->next;
        //find a texinfo for every brush side
        for (sn = 0; sn < brush->numsides; sn++)
        {
            side = &brush->sides[sn];
            //
            if (side->flags & SFL_TEXTURED) continue;
            //number of the node that created this brush side
            sidenodenum = side->surf;	//see midwinding in Q1_SplitBrush
            //no face found yet
            bestfacenum = -1;
            //minimum face size
            largestarea = 1;
            //if optimizing the texture placement and not going for the
            //least number of brushes
            if (!lessbrushes)
            {
                for (i = 0; i < q1_numfaces; i++)
                {
                    //the face must be in the same plane as the node plane that created
                    //this brush side
                    if (q1_dfaces[i].planenum == q1_dnodes[sidenodenum].planenum)
                    {
                        //get the area the face and the brush side overlap
                        area = Q1_FaceOnWinding(&q1_dfaces[i], side->winding);
                        //if this face overlaps the brush side winding more than previous faces
                        if (area > largestarea)
                        {
                            //if there already was a face for texturing this brush side with
                            //a different texture
                            if (bestfacenum >= 0 &&
                                    (q1_dfaces[bestfacenum].texinfo != q1_dfaces[i].texinfo))
                            {
                                //split the brush to fit the texture
                                newbrushes = Q1_SplitBrushWithFace(brush, &q1_dfaces[i]);
                                //if new brushes where created
                                if (newbrushes)
                                {
                                    //remove the current brush from the list
                                    if (prevbrush) prevbrush->next = brush->next;
                                    else brushlist = brush->next;
                                    if (brushlistend == brush)
                                    {
                                        brushlistend = prevbrush;
                                        nextbrush = newbrushes;
                                    } //end if
                                    //add the new brushes to the end of the list
                                    if (brushlistend) brushlistend->next = newbrushes;
                                    else brushlist = newbrushes;
                                    //free the current brush
                                    FreeBrush(brush);
                                    //don't forget about the prevbrush pointer at the bottom of
                                    //the outer loop
                                    brush = prevbrush;
                                    //find the end of the list
                                    for (brushlistend = brushlist; brushlistend; brushlistend = brushlistend->next)
                                    {
                                        if (!brushlistend->next) break;
                                    } //end for
                                    break;
                                } //end if
                                else
                                {
                                    Log_Write("brush %d: no real texture split", numbrushes);
                                } //end else
                            } //end if
                            else
                            {
                                //best face for texturing this brush side
                                bestfacenum = i;
                            } //end else
                        } //end if
                    } //end if
                } //end for
                //if the brush was split the original brush is removed
                //and we just continue with the next one in the list
                if (i < q1_numfaces) break;
            } //end if
            else
            {
                //find the face with the largest overlap with this brush side
                //for texturing the brush side
                for (i = 0; i < q1_numfaces; i++)
                {
                    //the face must be in the same plane as the node plane that created
                    //this brush side
                    if (q1_dfaces[i].planenum == q1_dnodes[sidenodenum].planenum)
                    {
                        //get the area the face and the brush side overlap
                        area = Q1_FaceOnWinding(&q1_dfaces[i], side->winding);
                        //if this face overlaps the brush side winding more than previous faces
                        if (area > largestarea)
                        {
                            largestarea = area;
                            bestfacenum = i;
                        } //end if
                    } //end if
                } //end for
            } //end else
            //if a face was found for texturing this brush side
            if (bestfacenum >= 0)
            {
                //set the MAP texinfo values
                texinfonum = q1_dfaces[bestfacenum].texinfo;
                for (n = 0; n < 4; n++)
                {
                    map_texinfo[texinfonum].vecs[0][n] = q1_texinfo[texinfonum].vecs[0][n];
                    map_texinfo[texinfonum].vecs[1][n] = q1_texinfo[texinfonum].vecs[1][n];
                } //end for
                //make sure the two vectors aren't of zero length otherwise use the default
                //vector to prevent a divide by zero in the map writing
                if (VectorLength(map_texinfo[texinfonum].vecs[0]) < 0.01)
                    memcpy(map_texinfo[texinfonum].vecs[0], defaultvec, sizeof(defaultvec));
                if (VectorLength(map_texinfo[texinfonum].vecs[1]) < 0.01)
                    memcpy(map_texinfo[texinfonum].vecs[1], defaultvec, sizeof(defaultvec));
                //
                map_texinfo[texinfonum].flags = q1_texinfo[texinfonum].flags;
                map_texinfo[texinfonum].value = 0; //Q1 and HL texinfos don't have a value
                //the mip texture
                miptexlump = (q1_dmiptexlump_t *) q1_dtexdata;
                ofs = miptexlump->dataofs[q1_texinfo[texinfonum].miptex];
                if ( ofs > q1_texdatasize ) {
                    ofs = miptexlump->dataofs[0];
                }
                miptex = (q1_miptex_t *)((byte *)miptexlump + ofs);
                //get the mip texture name
                strcpy(map_texinfo[texinfonum].texture, miptex->name);
                //no animations in Quake1 and Half-Life mip textures
                map_texinfo[texinfonum].nexttexinfo = -1;
                //store the texinfo number
                side->texinfo = texinfonum;
                //
                if (texinfonum > map_numtexinfo) map_numtexinfo = texinfonum;
                //this side is textured
                side->flags |= SFL_TEXTURED;
            } //end if
            else
            {
                //no texture for this side
                side->texinfo = TEXINFO_NODE;
                //this side is textured
                side->flags |= SFL_TEXTURED;
            } //end if
        } //end for
        //
        if (!modelnum && prevbrush != brush) qprintf("\r%5d", ++numbrushes);
        //previous brush in the list
        prevbrush = brush;
    } //end for
    if (!modelnum) qprintf("\n");
    //return the new list with brushes
    return brushlist;
} //end of the function Q1_TextureBrushes