Example #1
0
brush_t *CopyBrush( brush_t *brush ){
	brush_t     *newBrush;
	size_t size;
	int i;


	/* copy brush */
	size = (size_t)&( ( (brush_t*) 0 )->sides[ brush->numsides ] );
	newBrush = AllocBrush( brush->numsides );
	memcpy( newBrush, brush, size );

	/* ydnar: nuke linked list */
	newBrush->next = NULL;

	/* copy sides */
	for ( i = 0; i < brush->numsides; i++ )
	{
		if ( brush->sides[ i ].winding != NULL ) {
			newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
		}
	}

	/* return it */
	return newBrush;
}
Example #2
0
//===========================================================================
// Creates a new axial brush
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
bspbrush_t	*BrushFromBounds (vec3_t mins, vec3_t maxs)
{
	bspbrush_t *b;
	int i;
	vec3_t normal;
	vec_t dist;

	b = AllocBrush (6);
	b->numsides = 6;
	for (i=0 ; i<3 ; i++)
	{
		VectorClear (normal);
		normal[i] = 1;
		dist = maxs[i];
		b->sides[i].planenum = FindFloatPlane (normal, dist);

		normal[i] = -1;
		dist = -mins[i];
		b->sides[3+i].planenum = FindFloatPlane (normal, dist);
	}

	CreateBrushWindings (b);

	return b;
} //end of the function BrushFromBounds
/*
==================
BrushFromBounds

Creates a new axial brush
==================
*/
bspbrush_t	*BrushFromBounds (Vector& mins, Vector& maxs)
{
	bspbrush_t	*b;
	int			i;
	Vector		normal;
	vec_t		dist;

	b = AllocBrush (6);
	b->numsides = 6;
	for (i=0 ; i<3 ; i++)
	{
		VectorClear (normal);
		normal[i] = 1;
		dist = maxs[i];
		b->sides[i].planenum = g_MainMap->FindFloatPlane (normal, dist);

		normal[i] = -1;
		dist = -mins[i];
		b->sides[3+i].planenum = g_MainMap->FindFloatPlane (normal, dist);
	}

	CreateBrushWindings (b);

	return b;
}
Example #4
0
/*
=================
LoadMapFile

loads a map file into a list of entities
=================
*/
void LoadMapFile( const char *filename, bool onlyLights )
{		
	brush_t		*b;
	int		oldNumEntities, numMapBrushes;
	
	MsgDev( D_NOTE, "--- LoadMapFile ---\n" );
	Msg( "Loading %s\n", filename );
	
	mapfile = Com_OpenScript( filename, NULL, 0 );
	if( !mapfile ) Sys_Break( "can't loading map file %s\n", filename );	
	
	if( onlyLights ) 
		oldNumEntities = numEntities;
	else numEntities = 0;

	c_detail = 0;	
	numMapDrawSurfs = 0;
	g_bBrushPrimit = BRUSH_UNKNOWN;
	
	// allocate a very large temporary brush for building the brushes as they are loaded
	buildBrush = AllocBrush( MAX_BUILD_SIDES );
	
	while( ParseMapEntity( onlyLights ));
	Com_CloseScript( mapfile );
	
	if( onlyLights )
	{
		MsgDev( D_INFO, "%9d light entities\n", numEntities - oldNumEntities );
	}
	else
	{
		ClearBounds( mapMins, mapMaxs );
		for( b = entities[0].brushes; b; b = b->next )
		{
			AddPointToBounds( b->mins, mapMins, mapMaxs );
			AddPointToBounds( b->maxs, mapMins, mapMaxs );
		}

		VectorSubtract( mapMaxs, mapMins, mapSize );		
		numMapBrushes = CountBrushList( entities[0].brushes );
		if(( float )c_detail / (float) numMapBrushes < 0.10f && numMapBrushes > 500 )
			MsgDev( D_WARN, "Over 90 percent structural map detected. Compile time may be adversely affected.\n" );
		
		MsgDev( D_NOTE, "%9d total world brushes\n", numMapBrushes );
		MsgDev( D_NOTE, "%9d detail brushes\n", c_detail );
		MsgDev( D_NOTE, "%9d patches\n", numMapPatches );
		MsgDev( D_NOTE, "%9d boxbevels\n", c_boxbevels );
		MsgDev( D_NOTE, "%9d edgebevels\n", c_edgebevels );
		MsgDev( D_NOTE, "%9d entities\n", numEntities );
		MsgDev( D_NOTE, "%9d planes\n", nummapplanes );
		MsgDev( D_NOTE, "%9d areaportals\n", c_areaportals );
		MsgDev( D_INFO, "World size: %5.0f, %5.0f, %5.0f\n", mapSize[0], mapSize[1], mapSize[2] );
		
		// write bogus map
		if( fakemap ) WriteBSPBrushMap( "fakemap.map", entities[0].brushes );
	}
}
/*
================
LoadDMapFile
================
*/
bool LoadDMapFile( const char *filename ) {
	primitive_t	*prim;
	idBounds	mapBounds;
	int			brushes, triSurfs;
	int			i;
	int			size;
	common->Printf( "--- LoadDMapFile ---\n" );
	common->Printf( "loading %s\n", filename );
	// load and parse the map file into canonical form
	dmapGlobals.dmapFile = new idMapFile();
	if( !dmapGlobals.dmapFile->Parse( filename ) ) {
		delete dmapGlobals.dmapFile;
		dmapGlobals.dmapFile = NULL;
		common->Warning( "Couldn't load map file: '%s'", filename );
		return false;
	}
	dmapGlobals.mapPlanes.Clear();
	dmapGlobals.mapPlanes.SetGranularity( 1024 );
	// process the canonical form into utility form
	dmapGlobals.num_entities = 0;
	c_numMapPatches = 0;
	c_areaportals = 0;
	size = dmapGlobals.dmapFile->GetNumEntities() * sizeof( dmapGlobals.uEntities[0] );
	dmapGlobals.uEntities = ( uEntity_t * )Mem_Alloc( size );
	memset( dmapGlobals.uEntities, 0, size );
	// allocate a very large temporary brush for building
	// the brushes as they are loaded
	buildBrush = AllocBrush( MAX_BUILD_SIDES );
	for( i = 0 ; i < dmapGlobals.dmapFile->GetNumEntities() ; i++ ) {
		ProcessMapEntity( dmapGlobals.dmapFile->GetEntity( i ) );
	}
	CreateMapLights( dmapGlobals.dmapFile );
	brushes = 0;
	triSurfs = 0;
	mapBounds.Clear();
	for( prim = dmapGlobals.uEntities[0].primitives ; prim ; prim = prim->next ) {
		if( prim->brush ) {
			brushes++;
			mapBounds.AddBounds( prim->brush->bounds );
		} else if( prim->tris ) {
			triSurfs++;
		}
	}
	common->Printf( "%5i total world brushes\n", brushes );
	common->Printf( "%5i total world triSurfs\n", triSurfs );
	common->Printf( "%5i patches\n", c_numMapPatches );
	common->Printf( "%5i entities\n", dmapGlobals.num_entities );
	common->Printf( "%5i planes\n", dmapGlobals.mapPlanes.Num() );
	common->Printf( "%5i areaportals\n", c_areaportals );
	common->Printf( "size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", mapBounds[0][0], mapBounds[0][1], mapBounds[0][2],
					mapBounds[1][0], mapBounds[1][1], mapBounds[1][2] );
	return true;
}
/*
================
idCollisionModelManagerLocal::ParseBrushes
================
*/
void idCollisionModelManagerLocal::ParseBrushes( idLexer *src, cm_model_t *model )
{
	cm_brush_t	*b;
	int			i, numPlanes;
	idVec3		normal;
	idToken		token;
	
	if( src->CheckTokenType( TT_NUMBER, 0, &token ) )
	{
		model->brushBlock = static_cast<cm_brushBlock_t *>( Mem_Alloc( sizeof( cm_brushBlock_t ) + token.GetIntValue() ) );
		model->brushBlock->bytesRemaining = token.GetIntValue();
		model->brushBlock->next = ( reinterpret_cast<byte *>( model->brushBlock ) ) + sizeof( cm_brushBlock_t );
	}
	src->ExpectTokenString( "{" );
	
	while( !src->CheckTokenString( "}" ) )
	{
		// parse brush
		numPlanes = src->ParseInt();
		b = AllocBrush( model, numPlanes );
		b->numPlanes = numPlanes;
		src->ExpectTokenString( "{" );
		
		for( i = 0; i < b->numPlanes; i++ )
		{
			src->Parse1DMatrix( 3, normal.ToFloatPtr() );
			b->planes[i].SetNormal( normal );
			b->planes[i].SetDist( src->ParseFloat() );
		}
		src->ExpectTokenString( "}" );
		src->Parse1DMatrix( 3, b->bounds[0].ToFloatPtr() );
		src->Parse1DMatrix( 3, b->bounds[1].ToFloatPtr() );
		src->ReadToken( &token );
		
		if( token.type == TT_NUMBER )
		{
			b->contents = token.GetIntValue();		// old .cm files use a single integer
		}
		else
		{
			b->contents = ContentsFromString( token );
		}
		b->checkcount = 0;
		b->primitiveNum = 0;
		
		// filter brush into tree
		R_FilterBrushIntoTree( model, model->node, NULL, b );
	}
}
Example #7
0
/**
 * @brief Duplicates the brush, the sides, and the windings
 * @sa AllocBrush
 */
bspbrush_t* CopyBrush (const bspbrush_t* brush)
{
	bspbrush_t* newbrush;
	int i;
	const size_t size = offsetof(bspbrush_t, sides) + sizeof(((bspbrush_t*)0)->sides) * brush->numsides;

	newbrush = AllocBrush(brush->numsides);
	memcpy(newbrush, brush, size);

	for (i = 0; i < brush->numsides; i++) {
		const side_t* side = &brush->sides[i];
		if (side->winding)
			newbrush->sides[i].winding = CopyWinding(side->winding);
	}

	return newbrush;
}
Example #8
0
/*
==================
BrushFromBounds

Creates a new axial brush
==================
*/
brush_t	*BrushFromBounds (float minx, float miny, float minz, float maxx, float maxy, float maxz, shaderInfo_t *si)
{
    brush_t	*b;
    vec3_t mins, maxs;
    vec3_t normal;
    vec_t dist;
    int	i;

    b = AllocBrush (6);
    b->entityNum = mapEntityNum;
    b->original = b;
    b->contentShader = si;
    b->compileFlags = si->compileFlags;
    b->contentFlags = si->contentFlags;
    b->opaque = qtrue;
    b->detail = qfalse;
    b->numsides = 6;
    VectorSet(mins, minx, miny, minz);
    VectorSet(maxs, maxx, maxy, maxz);
    for (i=0 ; i<3 ; i++)
    {
        VectorClear (normal);
        normal[i] = 1;
        dist = maxs[i];
        b->sides[i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &maxs );
        b->sides[i].shaderInfo = si;
        b->sides[i].surfaceFlags = si->surfaceFlags;
        b->sides[i].contentFlags = si->contentFlags;
        b->sides[i].compileFlags = si->compileFlags;
        b->sides[i].value = si->value;

        normal[i] = -1;
        dist = -mins[i];
        b->sides[3+i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &mins );
        b->sides[3+i].shaderInfo = si;
        b->sides[3+i].surfaceFlags = si->surfaceFlags;
        b->sides[3+i].contentFlags = si->contentFlags;
        b->sides[3+i].compileFlags = si->compileFlags;
        b->sides[3+i].value = si->value;
    }

    CreateBrushWindings (b);

    return b;
}
Example #9
0
/**
 * @brief Duplicates the brush, the sides, and the windings
 */
brush_t *CopyBrush(brush_t *brush) {
	brush_t *newbrush;
	size_t size;
	int32_t i;

	size = (size_t) & (((brush_t *) 0)->sides[brush->num_sides]);

	newbrush = AllocBrush(brush->num_sides);
	memcpy(newbrush, brush, size);

	for (i = 0; i < brush->num_sides; i++) {
		if (brush->sides[i].winding) {
			newbrush->sides[i].winding = CopyWinding(brush->sides[i].winding);
		}
	}

	return newbrush;
}
Example #10
0
//===========================================================================
// Duplicates the brush, the sides, and the windings
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
bspbrush_t *CopyBrush (bspbrush_t *brush)
{
	bspbrush_t *newbrush;
	size_t		size;
	int			i;

	size = sizeof(*newbrush) + sizeof(*brush->sides) * brush->numsides;

	newbrush = AllocBrush (brush->numsides);
	memcpy (newbrush, brush, size);

	for (i=0 ; i<brush->numsides ; i++)
	{
		if (brush->sides[i].winding)
			newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
	}

	return newbrush;
} //end of the function CopyBrush
/*
==================
CopyBrush

Duplicates the brush, the sides, and the windings
==================
*/
bspbrush_t *CopyBrush (bspbrush_t *brush)
{
	bspbrush_t *newbrush;
	int			size;
	int			i;
	
	size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);

	newbrush = AllocBrush (brush->numsides);
	memcpy (newbrush, brush, size);

	for (i=0 ; i<brush->numsides ; i++)
	{
		if (brush->sides[i].winding)
			newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
	}

	return newbrush;
}
Example #12
0
/*
==================
CopyBrush

Duplicates the brush, the sides, and the windings
==================
*/
uBrush_t *CopyBrush (uBrush_t *brush)
{
	uBrush_t *newbrush;
	int			size;
	int			i;
	
	size = BrushSizeForSides( brush->numsides );

	newbrush = AllocBrush (brush->numsides);
	memcpy (newbrush, brush, size);

	for (i=0 ; i<brush->numsides ; i++)
	{
		if (brush->sides[i].winding)
			newbrush->sides[i].winding = brush->sides[i].winding->Copy();
	}

	return newbrush;
}
Example #13
0
/*
==================
BrushFromBounds

Creates a new axial brush
==================
*/
uBrush_t	*BrushFromBounds( const idBounds &bounds ) {
	uBrush_t	*b;
	int			i;
	idPlane		plane;

	b = AllocBrush (6);
	b->numsides = 6;
	for (i=0 ; i<3 ; i++) {
		plane[0] = plane[1] = plane[2] = 0;
		plane[i] = 1;
		plane[3] = -bounds[1][i];
		b->sides[i].planenum = FindFloatPlane( plane );

		plane[i] = -1;
		plane[3] = bounds[0][i];
		b->sides[3+i].planenum = FindFloatPlane( plane );
	}

	CreateBrushWindings (b);

	return b;
}
Example #14
0
/**
 * @brief Creates a new axial brush
 */
static brush_t *BrushFromBounds(vec3_t mins, vec3_t maxs) {
	brush_t *b;
	int32_t i;
	vec3_t normal;
	vec_t dist;

	b = AllocBrush(6);
	b->num_sides = 6;
	for (i = 0; i < 3; i++) {
		VectorClear(normal);
		normal[i] = 1;
		dist = maxs[i];
		b->sides[i].plane_num = FindPlane(normal, dist);

		normal[i] = -1;
		dist = -mins[i];
		b->sides[3 + i].plane_num = FindPlane(normal, dist);
	}

	CreateBrushWindings(b);

	return b;
}
Example #15
0
/**
 * @brief Generates two new brushes, leaving the original unchanged
 */
void SplitBrush(brush_t *brush, int32_t plane_num, brush_t **front, brush_t **back) {
	brush_t *b[2];
	int32_t i, j;
	winding_t *w, *cw[2], *midwinding;
	map_plane_t *plane, *plane2;
	side_t *s, *cs;
	vec_t d, d_front, d_back;

	*front = *back = NULL;
	plane = &map_planes[plane_num];

	// check all points
	d_front = d_back = 0;
	for (i = 0; i < brush->num_sides; i++) {
		w = brush->sides[i].winding;
		if (!w) {
			continue;
		}
		for (j = 0; j < w->num_points; j++) {
			d = DotProduct(w->points[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 = WindingForPlane(plane->normal, plane->dist);
	for (i = 0; i < brush->num_sides && w; i++) {
		plane2 = &map_planes[brush->sides[i].plane_num ^ 1];
		ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
	}

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

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

	if (WindingIsHuge(w)) {
		Mon_SendWinding(ERROR_WARN, (const vec3_t *) w->points, w->num_points, "Large winding");
	}

	midwinding = w;

	// split it for real

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

	// split all the current windings

	for (i = 0; i < brush->num_sides; 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;
			}

			cs = &b[j]->sides[b[j]->num_sides];
			b[j]->num_sides++;
			*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] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD) {
				Com_Debug(DEBUG_ALL, "bogus brush after clip\n");
				break;
			}
		}

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

	if (!(b[0] && b[1])) {
		if (!b[0] && !b[1]) {
			Com_Debug(DEBUG_ALL, "split removed brush\n");
		} else {
			Com_Debug(DEBUG_ALL, "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]->num_sides];
		b[i]->num_sides++;

		cs->plane_num = plane_num ^ 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;

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

	*front = b[0];
	*back = b[1];
}
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];
}
Example #17
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];
}
Example #18
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];
}
Example #19
0
//===========================================================================
// Generates two new brushes, leaving the original
// unchanged
//
// modified for Half-Life because there are quite a lot of tiny node leaves
// in the Half-Life bsps
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void Q1_SplitBrush(bspbrush_t *brush, int planenum, int nodenum,
                   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;
        } //end for
    } //end for

    if (d_front < 0.1) // PLANESIDE_EPSILON)
    {   // only on back
        *back = CopyBrush (brush);
        Log_Print("Q1_SplitBrush: only on back\n");
        return;
    } //end if
    if (d_back > -0.1) // PLANESIDE_EPSILON)
    {   // only on front
        *front = CopyBrush (brush);
        Log_Print("Q1_SplitBrush: only on front\n");
        return;
    } //end if

    // 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);
    } //end for

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

        Log_Print("Q1_SplitBrush: no split winding\n");
        side = BrushMostlyOnSide (brush, plane);
        if (side == PSIDE_FRONT)
            *front = CopyBrush (brush);
        if (side == PSIDE_BACK)
            *back = CopyBrush (brush);
        return;
    }

    if (WindingIsHuge(w))
    {
        Log_Print("Q1_SplitBrush: WARNING huge split winding\n");
    } //end of

    midwinding = w;

    // split it for real

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

    // 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->flags &= ~SFL_TESTED;
        } //end for
    } //end for


    // 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)
            {
                Log_Print("Q1_SplitBrush: bogus brush after clip\n");
                break;
            } //end if
        } //end for

        if (b[i]->numsides < 3 || j < 3)
        {
            FreeBrush (b[i]);
            b[i] = NULL;
            Log_Print("Q1_SplitBrush: numsides < 3\n");
        } //end if
    } //end for

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

    // 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 = 0;
        //store the node number in the surf to find the texinfo later on
        cs->surf = nodenum;
        //
        cs->flags &= ~SFL_VISIBLE;
        cs->flags &= ~SFL_TESTED;
        cs->flags &= ~SFL_TEXTURED;
        if (i==0)
            cs->winding = CopyWinding (midwinding);
        else
            cs->winding = midwinding;
    } //end for


    {
        vec_t v1;
        int i;

        for (i=0 ; i<2 ; i++)
        {
            v1 = BrushVolume (b[i]);
            if (v1 < 1)
            {
                FreeBrush (b[i]);
                b[i] = NULL;
                Log_Print("Q1_SplitBrush: tiny volume after clip\n");
            } //end if
        } //end for
    } //*/

    *front = b[0];
    *back = b[1];
} //end of the function Q1_SplitBrush
Example #20
0
/*
================
SplitBrush

Generates two new brushes, leaving the original
unchanged
================
*/
void SplitBrush( uBrush_t *brush, int planenum, uBrush_t **front, uBrush_t **back )
{
	uBrush_t	*b[2];
	int			i, j;
	idWinding	*w, *cw[2], *midwinding;
	side_t		*s, *cs;
	float		d, d_front, d_back;
	
	*front = *back = NULL;
	idPlane &plane = dmapGlobals.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->GetNumPoints(); j++ )
		{
			d = plane.Distance( ( *w ) [j].ToVec3() );
			
			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 = new idWinding( plane );
	
	for( i = 0; i < brush->numsides && w; i++ )
	{
		idPlane &plane2 = dmapGlobals.mapPlanes[brush->sides[i].planenum ^ 1];
		w = w->Clip( plane2, 0 ); // PLANESIDE_EPSILON);
	}
	
	if( !w || w->IsTiny() )
	{
		// 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( w->IsHuge() )
	{
		common->Printf( "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( uBrush_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;
		}
		
		w->Split( plane, 0, &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( !BoundBrush( b[i] ) )
		{
			break;
		}
		
		if( b[i]->numsides < 3 )
		{
			FreeBrush( b[i] );
			b[i] = NULL;
		}
	}
	
	if( !( b[0] && b[1] ) )
	{
		if( !b[0] && !b[1] )
		{
			common->Printf( "split removed brush\n" );
		}
		else
		{
			common->Printf( "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->material = NULL;
		
		if( i == 0 )
		{
			cs->winding = midwinding->Copy();
		}
		else
		{
			cs->winding = midwinding;
		}
	}
	
	for( i = 0; i < 2; i++ )
	{
		float v1 = BrushVolume( b[i] );
		
		if( v1 < 1.0 )
		{
			FreeBrush( b[i] );
			b[i] = NULL;
			//common->Printf ("tiny volume after clip\n");
		}
	}
	*front = b[0];
	*back = b[1];
}
Example #21
0
void InsertModel(char *name, int frame, matrix_t transform, matrix_t nTransform, remap_t * remap, shaderInfo_t * celShader, int eNum, int castShadows,
				 int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle)
{
	int             i, j, k, s, numSurfaces;
	matrix_t        identity;
	picoModel_t    *model;
	picoShader_t   *shader;
	picoSurface_t  *surface;
	shaderInfo_t   *si;
	mapDrawSurface_t *ds;
	bspDrawVert_t  *dv;
	char           *picoShaderName;
	char            shaderName[MAX_QPATH];
	picoVec_t      *xyz, *normal, *st;
	byte           *color;
	picoIndex_t    *indexes;
	remap_t        *rm, *glob;
	double          normalEpsilon_save;
	double          distanceEpsilon_save;


	/* get model */
	model = LoadModel(name, frame);
	if(model == NULL)
		return;

	/* handle null matrix */
	if(transform == NULL)
	{
		MatrixIdentity(identity);
		transform = identity;
	}

	/* create transform matrix for normals */
#if 0
	MatrixCopy(transform, nTransform);
	if(MatrixInverse(nTransform))
	{
		Sys_FPrintf(SYS_VRB, "WARNING: Can't invert model transform matrix, using transpose instead\n");
		MatrixTranspose(transform, nTransform);
	}
#endif

	/* fix bogus lightmap scale */
	if(lightmapScale <= 0.0f)
		lightmapScale = 1.0f;

	/* fix bogus shade angle */
	if(shadeAngle <= 0.0f)
		shadeAngle = 0.0f;

	/* each surface on the model will become a new map drawsurface */
	numSurfaces = PicoGetModelNumSurfaces(model);
	//% Sys_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces );
	for(s = 0; s < numSurfaces; s++)
	{
		/* get surface */
		surface = PicoGetModelSurface(model, s);
		if(surface == NULL)
			continue;

		/* only handle triangle surfaces initially (fixme: support patches) */
		if(PicoGetSurfaceType(surface) != PICO_TRIANGLES)
			continue;

		/* fix the surface's normals */
		PicoFixSurfaceNormals(surface);

		/* allocate a surface (ydnar: gs mods) */
		ds = AllocDrawSurface(SURFACE_TRIANGLES);
		ds->entityNum = eNum;
		ds->castShadows = castShadows;
		ds->recvShadows = recvShadows;

		/* get shader name */
		shader = PicoGetSurfaceShader(surface);
		if(shader == NULL)
			picoShaderName = "";
		else
			picoShaderName = PicoGetShaderName(shader);

		/* handle shader remapping */
		glob = NULL;
		for(rm = remap; rm != NULL; rm = rm->next)
		{
			if(rm->from[0] == '*' && rm->from[1] == '\0')
				glob = rm;
			else if(!Q_stricmp(picoShaderName, rm->from))
			{
				Sys_FPrintf(SYS_VRB, "Remapping %s to %s\n", picoShaderName, rm->to);
				picoShaderName = rm->to;
				glob = NULL;
				break;
			}
		}

		if(glob != NULL)
		{
			Sys_FPrintf(SYS_VRB, "Globbing %s to %s\n", picoShaderName, glob->to);
			picoShaderName = glob->to;
		}

		/* shader renaming for sof2 */
		if(renameModelShaders)
		{
			strcpy(shaderName, picoShaderName);
			StripExtension(shaderName);
			if(spawnFlags & 1)
				strcat(shaderName, "_RMG_BSP");
			else
				strcat(shaderName, "_BSP");
			si = ShaderInfoForShader(shaderName);
		}
		else
		{
			si = ShaderInfoForShader(picoShaderName);

			// Tr3B: HACK to support the messy Doom 3 materials provided by .ASE files
			if(!si->explicitDef)
			{
				picoShaderName = PicoGetShaderMapName(shader);

				Q_strncpyz(shaderName, picoShaderName, sizeof(shaderName));
				StripExtension(shaderName);

				i = 0;
				while(shaderName[i])
				{
					if(shaderName[i] == '\\')
						shaderName[i] = '/';
					i++;
				}

				if(strstr(shaderName, "base/"))
				{
					si = ShaderInfoForShader(strstr(shaderName, "base/") + strlen("base/"));
					Sys_FPrintf(SYS_WRN, "WARNING: Applied .ASE material loader HACK to '%s' -> '%s'\n", picoShaderName, si->shader);
				}

			}
		}

		/* set shader */
		ds->shaderInfo = si;

		/* force to meta? */
		if((si != NULL && si->forceMeta) || (spawnFlags & 4))	/* 3rd bit */
			ds->type = SURFACE_FORCED_META;

		/* fix the surface's normals (jal: conditioned by shader info) */
		//if(!(spawnFlags & 64) && (shadeAngle == 0.0f || ds->type != SURFACE_FORCED_META))
		//	PicoFixSurfaceNormals(surface);

		/* set sample size */
		if(lightmapSampleSize > 0.0f)
			ds->sampleSize = lightmapSampleSize;

		/* set lightmap scale */
		if(lightmapScale > 0.0f)
			ds->lightmapScale = lightmapScale;

		/* set shading angle */
		if(shadeAngle > 0.0f)
			ds->shadeAngleDegrees = shadeAngle;

		/* set particulars */
		ds->numVerts = PicoGetSurfaceNumVertexes(surface);
		ds->verts = safe_malloc(ds->numVerts * sizeof(ds->verts[0]));
		memset(ds->verts, 0, ds->numVerts * sizeof(ds->verts[0]));

		ds->numIndexes = PicoGetSurfaceNumIndexes(surface);
		ds->indexes = safe_malloc(ds->numIndexes * sizeof(ds->indexes[0]));
		memset(ds->indexes, 0, ds->numIndexes * sizeof(ds->indexes[0]));

		/* copy vertexes */
		for(i = 0; i < ds->numVerts; i++)
		{
			/* get vertex */
			dv = &ds->verts[i];

			/* xyz and normal */
			xyz = PicoGetSurfaceXYZ(surface, i);
			VectorCopy(xyz, dv->xyz);
			MatrixTransformPoint2(transform, dv->xyz);

			normal = PicoGetSurfaceNormal(surface, i);
			VectorCopy(normal, dv->normal);
			MatrixTransformNormal2(nTransform, dv->normal);
			VectorNormalize2(dv->normal, dv->normal);

			/* ydnar: tek-fu celshading support for flat shaded shit */
			if(flat)
			{
				dv->st[0] = si->stFlat[0];
				dv->st[1] = si->stFlat[1];
			}

			/* ydnar: gs mods: added support for explicit shader texcoord generation */
			else if(si->tcGen)
			{
				/* project the texture */
				dv->st[0] = DotProduct(si->vecs[0], dv->xyz);
				dv->st[1] = DotProduct(si->vecs[1], dv->xyz);
			}

			/* normal texture coordinates */
			else
			{
				st = PicoGetSurfaceST(surface, 0, i);
				dv->st[0] = st[0];
				dv->st[1] = st[1];
			}

			/* set lightmap/color bits */
			color = PicoGetSurfaceColor(surface, 0, i);

			dv->paintColor[0] = color[0] / 255.0f;
			dv->paintColor[1] = color[1] / 255.0f;
			dv->paintColor[2] = color[2] / 255.0f;
			dv->paintColor[3] = color[3] / 255.0f;

			for(j = 0; j < MAX_LIGHTMAPS; j++)
			{
				dv->lightmap[j][0] = 0.0f;
				dv->lightmap[j][1] = 0.0f;

				dv->lightColor[j][0] = 255;
				dv->lightColor[j][1] = 255;
				dv->lightColor[j][2] = 255;
				dv->lightColor[j][3] = 255;
			}
		}

		/* copy indexes */
		indexes = PicoGetSurfaceIndexes(surface, 0);
		for(i = 0; i < ds->numIndexes; i++)
			ds->indexes[i] = indexes[i];

		/* set cel shader */
		ds->celShader = celShader;

		/* ydnar: giant hack land: generate clipping brushes for model triangles */
		if(si->clipModel || (spawnFlags & 2))	/* 2nd bit */
		{
			vec3_t          points[4], backs[3];
			vec4_t          plane, reverse, pa, pb, pc;


			/* temp hack */
			if(!si->clipModel &&
			   (((si->compileFlags & C_TRANSLUCENT) && !(si->compileFlags & C_COLLISION)) || !(si->compileFlags & C_SOLID)))
				continue;

			/* walk triangle list */
			for(i = 0; i < ds->numIndexes; i += 3)
			{
				/* overflow hack */
				AUTOEXPAND_BY_REALLOC(mapplanes, (nummapplanes + 64) << 1, allocatedmapplanes, 1024);

				/* make points and back points */
				for(j = 0; j < 3; j++)
				{
					/* get vertex */
					dv = &ds->verts[ds->indexes[i + j]];

					/* copy xyz */
					VectorCopy(dv->xyz, points[j]);
					VectorCopy(dv->xyz, backs[j]);

					/* find nearest axial to normal and push back points opposite */
					/* note: this doesn't work as well as simply using the plane of the triangle, below */
					for(k = 0; k < 3; k++)
					{
						if(fabs(dv->normal[k]) >= fabs(dv->normal[(k + 1) % 3]) &&
						   fabs(dv->normal[k]) >= fabs(dv->normal[(k + 2) % 3]))
						{
							backs[j][k] += dv->normal[k] < 0.0f ? 64.0f : -64.0f;
							break;
						}
					}
				}

				VectorCopy(points[0], points[3]);	// for cyclic usage

				/* make plane for triangle */
				// div0: add some extra spawnflags:
				//   0: snap normals to axial planes for extrusion
				//   8: extrude with the original normals
				//  16: extrude only with up/down normals (ideal for terrain)
				//  24: extrude by distance zero (may need engine changes)
				if(PlaneFromPoints(plane, points[0], points[1], points[2], qtrue))
				{
					vec3_t          bestNormal;
					float           backPlaneDistance = 2;

					if(spawnFlags & 8)	// use a DOWN normal
					{
						if(spawnFlags & 16)
						{
							// 24: normal as is, and zero width (broken)
							VectorCopy(plane, bestNormal);
						}
						else
						{
							// 8: normal as is
							VectorCopy(plane, bestNormal);
						}
					}
					else
					{
						if(spawnFlags & 16)
						{
							// 16: UP/DOWN normal
							VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
						}
						else
						{
							// 0: axial normal
							if(fabs(plane[0]) > fabs(plane[1]))	// x>y
								if(fabs(plane[1]) > fabs(plane[2]))	// x>y, y>z
									VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
								else	// x>y, z>=y
								if(fabs(plane[0]) > fabs(plane[2]))	// x>z, z>=y
									VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
								else	// z>=x, x>y
									VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
							else	// y>=x
							if(fabs(plane[1]) > fabs(plane[2]))	// y>z, y>=x
								VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
							else	// z>=y, y>=x
								VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
						}
					}

					/* build a brush */
					buildBrush = AllocBrush(48);
					buildBrush->entityNum = mapEntityNum;
					buildBrush->original = buildBrush;
					buildBrush->contentShader = si;
					buildBrush->compileFlags = si->compileFlags;
					buildBrush->contentFlags = si->contentFlags;

					buildBrush->generatedClipBrush = qtrue;

					normalEpsilon_save = normalEpsilon;
					distanceEpsilon_save = distanceEpsilon;

					if(si->compileFlags & C_STRUCTURAL)	// allow forced structural brushes here
					{
						buildBrush->detail = qfalse;

						// only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
						if(normalEpsilon > 0)
							normalEpsilon = 0;
						if(distanceEpsilon > 0)
							distanceEpsilon = 0;
					}
					else
						buildBrush->detail = qtrue;

					/* regenerate back points */
					for(j = 0; j < 3; j++)
					{
						/* get vertex */
						dv = &ds->verts[ds->indexes[i + j]];

						// shift by some units
						VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]);	// 64 prevents roundoff errors a bit
					}

					/* make back plane */
					VectorScale(plane, -1.0f, reverse);
					reverse[3] = -plane[3];
					if((spawnFlags & 24) != 24)
						reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
					// that's at least sqrt(1/3) backPlaneDistance, unless in DOWN mode; in DOWN mode, we are screwed anyway if we encounter a plane that's perpendicular to the xy plane)

					if(PlaneFromPoints(pa, points[2], points[1], backs[1], qtrue) &&
					   PlaneFromPoints(pb, points[1], points[0], backs[0], qtrue) && PlaneFromPoints(pc, points[0], points[2], backs[2], qtrue))
					{
						/* set up brush sides */
						buildBrush->numsides = 5;
						buildBrush->sides[0].shaderInfo = si;
						for(j = 1; j < buildBrush->numsides; j++)
							buildBrush->sides[j].shaderInfo = NULL;	// don't emit these faces as draw surfaces, should make smaller BSPs; hope this works

						buildBrush->sides[0].planenum = FindFloatPlane(plane, plane[3], 3, points);
						buildBrush->sides[1].planenum = FindFloatPlane(pa, pa[3], 2, &points[1]);	// pa contains points[1] and points[2]
						buildBrush->sides[2].planenum = FindFloatPlane(pb, pb[3], 2, &points[0]);	// pb contains points[0] and points[1]
						buildBrush->sides[3].planenum = FindFloatPlane(pc, pc[3], 2, &points[2]);	// pc contains points[2] and points[0] (copied to points[3]
						buildBrush->sides[4].planenum = FindFloatPlane(reverse, reverse[3], 3, backs);
					}
					else
					{
						free(buildBrush);
						continue;
					}

					normalEpsilon = normalEpsilon_save;
					distanceEpsilon = distanceEpsilon_save;

					/* add to entity */
					if(CreateBrushWindings(buildBrush))
					{
						AddBrushBevels();
						//% EmitBrushes( buildBrush, NULL, NULL );
						buildBrush->next = entities[mapEntityNum].brushes;
						entities[mapEntityNum].brushes = buildBrush;
						entities[mapEntityNum].numBrushes++;
					}
					else
						free(buildBrush);
				}
			}
		}
	}
}
Example #22
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];
}
Example #23
0
/*
===============
LoadBrush

Converts a mapbrush to a bsp brush
===============
*/
brush_t *LoadBrush (mbrush_t *mb, int brushnum, int hullnum)
{
	brush_t		*b;
	int			contents;
	char		*name;
	mface_t		*f;

	//
	// check texture name for attributes
	//

	for (f = mb->faces;f;f = f->next)
	{
		name = miptex[texinfo[f->texinfo].miptex];
		if (hullnum == 0)
		{
			// textures which don't show up in the drawing hull
			if (!Q_strcasecmp(name, "clip"))
				return NULL;
			if (!Q_strcasecmp(name, "common/nodraw"))
				return NULL;
			if (!Q_strcasecmp(name, "textures/common/nodraw"))
				return NULL;
			if (!Q_strcasecmp(name, "textures/common/clip"))
				return NULL;
			if (!Q_strcasecmp(name, "textures/common/full_clip"))
				return NULL;
		}
		if (!Q_strcasecmp(name, "textures/editor/visportal"))
			return NULL;
	}

	name = miptex[texinfo[mb->faces->texinfo].miptex];

	// g-cont. without this check e1m3 won't compile
	if (name[0] == '!' && worldmodel )	// entities never use water merging
	{
		if (!Q_strncasecmp(name+1,"lava",4))
			contents = CONTENTS_LAVA;
		else if (!Q_strncasecmp(name+1,"slime",5))
			contents = CONTENTS_SLIME;
		else
			contents = CONTENTS_WATER;
	}
	else if (!Q_strncasecmp (name, "sky",3) && hullnum == 0)
		contents = CONTENTS_SKY;
	else
		contents = CONTENTS_SOLID;

	if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
		return NULL;		// water brushes don't show up in clipping hulls

	// no seperate textures on clip hull

	//
	// create the faces
	//
	brush_faces = NULL;

	numbrushfaces = 0;
	for (f=mb->faces ; f ; f=f->next)
	{
		faces[numbrushfaces] = *f;
		if (hullnum)
			faces[numbrushfaces].texinfo = 0;
		numbrushfaces++;
	}

	if (hullnum)
		ExpandBrush (hullnum);

	CreateBrushFaces ();

	if (!brush_faces)
	{
		printf ("WARNING: couldn't create faces for brush %i in entity %i (incomplete brush?)\n", brushnum, (int)(CurrentEntity - entities));
		return NULL;
	}

	//
	// create the brush
	//
	b = AllocBrush ();
	b->contents = contents;
	b->faces = brush_faces;
	VectorCopy (brush_mins, b->mins);
	VectorCopy (brush_maxs, b->maxs);
	// debugging code
	//printf("mapbrush\n");
	//for (f=mb->faces ; f ; f=f->next)
	//	printf("face %f %f %f %f \"%s\"\n", f->plane.normal[0], f->plane.normal[1], f->plane.normal[2], f->plane.dist, miptex[texinfo[f->texinfo].miptex]);
	//printf("bspbrush %i\n", numbrushfaces);
	//face_t		*face;
	//for (face=b->faces ; face ; face=face->next)
	//	printf("bspface %f %f %f %f\n", mapplanes[face->planenum].normal[0], mapplanes[face->planenum].normal[1], mapplanes[face->planenum].normal[2], mapplanes[face->planenum].dist);

	return b;
}
Example #24
0
//===========================================================================
// NOTE: can't keep brush->original intact
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *TryMergeBrushes(bspbrush_t *brush1, bspbrush_t *brush2)
{
	int i, j, k, n, shared;
	side_t *side1, *side2, *cs;
	plane_t *plane1, *plane2;
	bspbrush_t *newbrush;

	//check for bounding box overlapp
	for (i = 0; i < 3; i++)
	{
		if (brush1->mins[i] > brush2->maxs[i] + 2
				|| brush1->maxs[i] < brush2->mins[i] - 2)
		{
			return NULL;
		} //end if
	} //end for
	//
	shared = 0;
	//check if the brush is convex... flipped planes make a brush non-convex
	for (i = 0; i < brush1->numsides; i++)
	{
		side1 = &brush1->sides[i];
		//don't check the "shared" sides
		for (k = 0; k < brush2->numsides; k++)
		{
			side2 = &brush2->sides[k];
			if (side1->planenum == (side2->planenum^1))
			{
				shared++;
				//there may only be ONE shared side
				if (shared > 1) return NULL;
				break;
			} //end if
		} //end for
		if (k < brush2->numsides) continue;
		//
		for (j = 0; j < brush2->numsides; j++)
		{
			side2 = &brush2->sides[j];
			//don't check the "shared" sides
			for (n = 0; n < brush1->numsides; n++)
			{
				side1 = &brush1->sides[n];
				if (side1->planenum == (side2->planenum^1)) break;
			} //end for
			if (n < brush1->numsides) continue;
			//
			side1 = &brush1->sides[i];
			//if the side is in the same plane
			//*
			if (side1->planenum == side2->planenum)
			{
				if (side1->texinfo != TEXINFO_NODE &&
					side2->texinfo != TEXINFO_NODE &&
					side1->texinfo != side2->texinfo) return NULL;
				continue;
			} //end if
			//
			plane1 = &mapplanes[side1->planenum];
			plane2 = &mapplanes[side2->planenum];
			//
			if (WindingsNonConvex(side1->winding, side2->winding,
									plane1->normal, plane2->normal,
									plane1->dist, plane2->dist))
			{
				return NULL;
			} //end if
		} //end for
	} //end for
	newbrush = AllocBrush(brush1->numsides + brush2->numsides);
	newbrush->original = brush1->original;
	newbrush->numsides = 0;
	//newbrush->side = brush1->side;	//brush contents
	//fix texinfos for sides lying in the same plane
	for (i = 0; i < brush1->numsides; i++)
	{
		side1 = &brush1->sides[i];
		//
		for (n = 0; n < brush2->numsides; n++)
		{
			side2 = &brush2->sides[n];
			//if both sides are in the same plane get the texinfo right
			if (side1->planenum == side2->planenum)
			{
				if (side1->texinfo == TEXINFO_NODE) side1->texinfo = side2->texinfo;
				if (side2->texinfo == TEXINFO_NODE) side2->texinfo = side1->texinfo;
			} //end if
		} //end for
	} //end for
	//
	for (i = 0; i < brush1->numsides; i++)
	{
		side1 = &brush1->sides[i];
		//don't add the "shared" sides
		for (n = 0; n < brush2->numsides; n++)
		{
			side2 = &brush2->sides[n];
			if (side1->planenum == (side2->planenum ^ 1)) break;
		} //end for
		if (n < brush2->numsides) continue;
		//
		for (n = 0; n < newbrush->numsides; n++)
		{
			cs = &newbrush->sides[n];
			if (cs->planenum == side1->planenum)
			{
				Log_Print("brush duplicate plane\n");
				break;
			} //end if
		} //end if
		if (n < newbrush->numsides) continue;
		//add this side
		cs = &newbrush->sides[newbrush->numsides];
		newbrush->numsides++;
		*cs = *side1;
	} //end for
	for (j = 0; j < brush2->numsides; j++)
	{
		side2 = &brush2->sides[j];
		for (n = 0; n < brush1->numsides; n++)
		{
			side1 = &brush1->sides[n];
			//if the side is in the same plane
			if (side2->planenum == side1->planenum) break;
			//don't add the "shared" sides
			if (side2->planenum == (side1->planenum ^ 1)) break;
		} //end for
		if (n < brush1->numsides) continue;
		//
		for (n = 0; n < newbrush->numsides; n++)
		{
			cs = &newbrush->sides[n];
			if (cs->planenum == side2->planenum)
			{
				Log_Print("brush duplicate plane\n");
				break;
			} //end if
		} //end if
		if (n < newbrush->numsides) continue;
		//add this side
		cs = &newbrush->sides[newbrush->numsides];
		newbrush->numsides++;
		*cs = *side2;
	} //end for
	BSPBrushWindings(newbrush);
	BoundBrush(newbrush);
	CheckBSPBrush(newbrush);
	return newbrush;
} //end of the function TryMergeBrushes
Example #25
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *MakeBspBrushList(int startbrush, int endbrush,
											vec3_t clipmins, vec3_t clipmaxs)
{
	mapbrush_t	*mb;
	bspbrush_t	*brushlist, *newbrush;
	int			i, j;
	int			c_faces;
	int			c_brushes;
	int			numsides;
	int			vis;
	vec3_t		normal;
	float		dist;

	for (i=0 ; i<2 ; i++)
	{
		VectorClear (normal);
		normal[i] = 1;
		dist = clipmaxs[i];
		maxplanenums[i] = FindFloatPlane(normal, dist);
		dist = clipmins[i];
		minplanenums[i] = FindFloatPlane(normal, dist);
	}

	brushlist = NULL;
	c_faces = 0;
	c_brushes = 0;

	for (i=startbrush ; i<endbrush ; i++)
	{
		mb = &mapbrushes[i];

		numsides = mb->numsides;
		if (!numsides)
			continue;

		// make sure the brush has at least one face showing
		vis = 0;
		for (j=0 ; j<numsides ; j++)
			if ((mb->original_sides[j].flags & SFL_VISIBLE) && mb->original_sides[j].winding)
				vis++;
#if 0
		if (!vis)
			continue;	// no faces at all
#endif
		// if the brush is outside the clip area, skip it
		for (j=0 ; j<3 ; j++)
			if (mb->mins[j] >= clipmaxs[j]
			|| mb->maxs[j] <= clipmins[j])
			break;
		if (j != 3)
			continue;

		//
		// make a copy of the brush
		//
		newbrush = AllocBrush (mb->numsides);
		newbrush->original = mb;
		newbrush->numsides = mb->numsides;
		memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t));
		for (j=0 ; j<numsides ; j++)
		{
			if (newbrush->sides[j].winding)
				newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding);
			if (newbrush->sides[j].surf & SURF_HINT)
				newbrush->sides[j].flags |= SFL_VISIBLE;	// hints are always visible
		}
		VectorCopy (mb->mins, newbrush->mins);
		VectorCopy (mb->maxs, newbrush->maxs);

		//
		// carve off anything outside the clip box
		//
		newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs);
		if (!newbrush)
			continue;

		c_faces += vis;
		c_brushes++;

		newbrush->next = brushlist;
		brushlist = newbrush;
	}

	return brushlist;
} //end of the function MakeBspBrushList
Example #26
0
/*
===============
LoadBrush

Converts a mapbrush to a bsp brush
===============
*/
brush_t *LoadBrush (mbrush_t *mb, int hullnum)
{
	brush_t		*b;
	int			contents;
	char		*name;
	mface_t		*f;

//
// check texture name for attributes
//	
	name = miptex[texinfo[mb->faces->texinfo].miptex];

	if (!Q_strcasecmp(name, "clip") && hullnum == 0)
		return NULL;		// "clip" brushes don't show up in the draw hull
	
	if (name[0] == '*' && worldmodel)		// entities never use water merging
	{
		if (!Q_strncasecmp(name+1,"lava",4))
			contents = CONTENTS_LAVA;
		else if (!Q_strncasecmp(name+1,"slime",5))
			contents = CONTENTS_SLIME;
		else			
			contents = CONTENTS_WATER;
	}
	else if (!Q_strncasecmp (name, "sky",3) && worldmodel && hullnum == 0)
		contents = CONTENTS_SKY;
	else
		contents = CONTENTS_SOLID;

	if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
		return NULL;		// water brushes don't show up in clipping hulls

// no seperate textures on clip hull

//
// create the faces
//
	brush_faces = NULL;
	
	numbrushfaces = 0;
	for (f=mb->faces ; f ; f=f->next)
	{
		faces[numbrushfaces] = *f;
		if (hullnum)
			faces[numbrushfaces].texinfo = 0;
		numbrushfaces++;
	}
		
	CreateBrushFaces ();
	
	if (!brush_faces)
	{
		printf ("WARNING: couldn't create brush faces\n");
		return NULL;
	}

	if (hullnum)
	{
		ExpandBrush (hullnum);
		CreateBrushFaces ();
	}
	
//
// create the brush
//
	b = AllocBrush ();
	
	b->contents = contents;
	b->faces = brush_faces;
	VectorCopy (brush_mins, b->mins);
	VectorCopy (brush_maxs, b->maxs);

	return b;
}
Example #27
0
File: brush.c Project: kellyrm/Q1
/*
===============
LoadBrush

Converts a mapbrush to a bsp brush
===============
*/
brush_t *LoadBrush (mbrush_t *mb, int hullnum)
{
	brush_t		*b;
	int		contents, NoOfTex = 0, I, TexNo[3], MipTex1, MipTex2, Hull;
	char		*name, Str[512];
	mface_t		*f;

	CurrLine = mb->Line;

//
// check texture name for attributes
//
	name = miptex[MipTex1 = texinfo[mb->faces->texinfo].miptex];

	if (!Q_strcasecmp(name, "clip") && hullnum == 0)
		return NULL;		// "clip" brushes don't show up in the draw hull

	if (name[0] == '*' && worldmodel)		// entities never use water merging
	{
		if (!Q_strncasecmp(name+1,"lava",4))
			contents = CONTENTS_LAVA;
		else if (!Q_strncasecmp(name+1,"slime",5))
			contents = CONTENTS_SLIME;
		else
			contents = CONTENTS_WATER;
	}
	else if (!options.SolidMap && !Q_strncasecmp (name, "sky",3) && worldmodel && hullnum == 0)
		contents = CONTENTS_SKY;
	else
		contents = CONTENTS_SOLID;

	if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
		return NULL;		// water brushes don't show up in clipping hulls

// no seperate textures on clip hull

//
// create the faces
//
	brush_faces = NULL;

	numbrushfaces = 0;
	for (f=mb->faces ; f ; f=f->next)
	{
		faces[numbrushfaces] = *f;
		if (hullnum)
			faces[numbrushfaces].texinfo = 0;
		numbrushfaces++;

		if (numbrushfaces == MAX_FACES)
			Message (MSGERR, "LoadBrush: numbrushfaces == MAX_FACES (%d) on line %d", MAX_FACES, CurrLine);
	}

	CreateBrushFaces ();

	if (!brush_faces)
	{
		strcpy(Str, name);

		// Find max 3 extra unique texture names
		for (f = mb->faces; f; f = f->next)
		{
			MipTex2 = texinfo[f->texinfo].miptex;

			if (NoOfTex < 3 && MipTex2 != MipTex1)
			{
				for (I = 0; I < NoOfTex; ++I)
				{
					if (MipTex2 == TexNo[I])
						break;
				}

				if (I == NoOfTex)
					TexNo[NoOfTex++] = MipTex2;
			}
		}

		for (I = 0; I < NoOfTex; ++I)
		{
		        strcat(Str, " ");
		        strcat(Str, miptex[TexNo[I]]);
		}

		Message (MSGWARN, "Couldn't create brush on line %d with %d faces, %s", CurrLine, numbrushfaces, Str);
		return NULL;
	}

	Hull = hullnum == 0 ? options.visiblehull : hullnum;

	if (Hull || options.HullExpansion[1] > 0)
	{
		ExpandBrush (Hull);
		FreeBrushFaces(brush_faces);
		CreateBrushFaces ();
	}

//
// create the brush
//
	b = AllocBrush ();

	b->contents = contents;
	b->faces = brush_faces;
	VectorCopy (brush_mins, b->mins);
	VectorCopy (brush_maxs, b->maxs);

	return b;
}