Esempio n. 1
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];
}
Esempio n. 2
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
Esempio n. 3
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_WRN | SYS_VRBflag, "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;
		}
		ClipWindingEpsilonStrict( w, plane->normal, plane->dist,
								  0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1] ); /* strict, in parallel case we get the face back because it also is the midwinding */
		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_WRN | SYS_VRBflag, "bogus brush after clip\n" );
			}
			FreeBrush( b[i] );
			b[i] = NULL;
		}
	}

	if ( !( b[0] && b[1] ) ) {
		if ( !b[0] && !b[1] ) {
			Sys_FPrintf( SYS_WRN | SYS_VRBflag, "split removed brush\n" );
		}
		else{
			Sys_FPrintf( SYS_WRN | SYS_VRBflag, "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_WRN | SYS_VRBflag, "tiny volume after clip\n" );
			}
		}
	}

	*front = b[0];
	*back = b[1];
}
Esempio n. 4
0
File: bsp.c Progetto: Teivaz/nebula2
void ProcessSubModel( void )
{
    entity_t    *e;
    tree_t        *tree;
    brush_t        *b, *bc;
    node_t        *node;
    
    
    /* start a brush model */
    BeginModel();
    e = &entities[ mapEntityNum ];
    e->firstDrawSurf = numMapDrawSurfs;
    
    /* ydnar: gs mods */
    ClearMetaTriangles();
    
    /* check for patches with adjacent edges that need to lod together */
    PatchMapDrawSurfs( e );
    
    /* allocate a tree */
    node = AllocNode();
    node->planenum = PLANENUM_LEAF;
    tree = AllocTree();
    tree->headnode = node;
    
    /* add the sides to the tree */
    ClipSidesIntoTree( e, tree );
    
    /* ydnar: create drawsurfs for triangle models */
    AddTriangleModels( e );
    
    /* create drawsurfs for surface models */
    AddEntitySurfaceModels( e );
    
    /* generate bsp brushes from map brushes */
    EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );

    /* just put all the brushes in headnode */
    for( b = e->brushes; b; b = b->next )
    {
        bc = CopyBrush( b );
        bc->next = node->brushlist;
        node->brushlist = bc;
    }
    
    /* subdivide each drawsurf as required by shader tesselation */
    if( !nosubdivide )
        SubdivideFaceSurfaces( e, tree );
    
    /* add in any vertexes required to fix t-junctions */
    if( !notjunc )
        FixTJunctions( e );
    
    /* ydnar: classify the surfaces and project lightmaps */
    ClassifyEntitySurfaces( e );
    
    /* ydnar: project decals */
    MakeEntityDecals( e );
    
    /* ydnar: meta surfaces */
    MakeEntityMetaTriangles( e );
    SmoothMetaTriangles();
    FixMetaTJunctions();
    MergeMetaTriangles();
    
    /* add references to the final drawsurfs in the apropriate clusters */
    FilterDrawsurfsIntoTree( e, tree );
    
    /* match drawsurfaces back to original brushsides (sof2) */
    FixBrushSides( e );
    
    /* finish */
    EndModel( e, node );
    FreeTree( tree );
}
Esempio n. 5
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];
}
Esempio n. 6
0
/*
=================
FinishBrush

produces a final brush based on the buildBrush->sides array
and links it to the current entity
=================
*/
brush_t *FinishBrush( void )
{
	brush_t		*b;
	
	// create windings for sides and bounds for brush
	if( !CreateBrushWindings( buildBrush ))
		return NULL;

	// origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
	// after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush
	if( buildBrush->compileFlags & C_ORIGIN )
	{
		char	string[32];
		vec3_t	size, movedir, origin;

		if( numEntities == 1 )
		{
			Msg( "Entity %i, Brush %i: origin brushes not allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
		
		// calcualte movedir (Xash 0.4 style)
		VectorAverage( buildBrush->mins, buildBrush->maxs, origin );
		VectorSubtract( buildBrush->maxs, buildBrush->mins, size );

		if( size[2] > size[0] && size[2] > size[1] )
            		VectorSet( movedir, 0.0f, 1.0f, 0.0f );	// x-rotate
		else if( size[1] > size[2] && size[1] > size[0] )
            		VectorSet( movedir, 1.0f, 0.0f, 0.0f );	// y-rotate
		else if( size[0] > size[2] && size[0] > size[1] )
			VectorSet( movedir, 0.0f, 0.0f, 1.0f );	// z-rotate
		else VectorClear( movedir ); // custom movedir

#if 0
		if( !VectorIsNull( movedir ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)movedir[0], (int)movedir[1], (int)movedir[2] );
			SetKeyValue( &entities[numEntities - 1], "movedir", string );
		}
#endif
		if(!VectorIsNull( origin ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2] );
			SetKeyValue( &entities[numEntities - 1], "origin", string );
			VectorCopy( origin, entities[numEntities - 1].origin );
                    }

		// don't keep this brush
		return NULL;
	}
	
	// determine if the brush is an area portal
	if( buildBrush->compileFlags & C_AREAPORTAL )
	{
		if( numEntities != 1 )
		{
			Msg( "Entity %i, Brush %i: areaportals only allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
	}
	
	AddBrushBevels();
	
	b = CopyBrush( buildBrush );
	
	b->entityNum = mapEnt->mapEntityNum;
	b->brushNum = entitySourceBrushes;
	
	b->original = b;
	
	// link opaque brushes to head of list, translucent brushes to end
	if( b->opaque || mapEnt->lastBrush == NULL )
	{
		b->next = mapEnt->brushes;
		mapEnt->brushes = b;
		if( mapEnt->lastBrush == NULL )
			mapEnt->lastBrush = b;
	}
	else
	{
		b->next = NULL;
		mapEnt->lastBrush->next = b;
		mapEnt->lastBrush = b;
	}
	
	// link colorMod volume brushes to the entity directly
	if( b->contentShader != NULL && b->contentShader->colorMod != NULL && b->contentShader->colorMod->type == CM_VOLUME )
	{
		b->nextColorModBrush = mapEnt->colorModBrushes;
		mapEnt->colorModBrushes = b;
	}
	return b;
}
Esempio n. 7
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. 8
0
File: brush.c Progetto: otty/cake3
/*
================
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++)
	{
		if(brush->sides[i].backSide)
		{
			continue;			// fake back-sided polygons never split
		}
		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(bspBrush_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;
		ClipWindingEpsilon(w, plane->normal, plane->dist, 0 /*PLANESIDE_EPSILON */ , &cw[0], &cw[1]);
		for(j = 0; j < 2; j++)
		{
			if(!cw[j])
				continue;
/*
			if (WindingIsTiny (cw[j]))
			{
				FreeWinding (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++)
	{
		BoundBrush(b[i]);
		for(j = 0; j < 3; j++)
		{
			if(b[i]->mins[j] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD)
			{
				Sys_FPrintf(SYS_VRB, "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])
			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;
//          qprintf ("tiny volume after clip\n");
			}
		}
	}

	*front = b[0];
	*back = b[1];
}
Esempio n. 9
0
void CSG_SplitBrush_new( cbspbrush_t *in, cplane_t *plane, cbspbrush_t **front, cbspbrush_t **back )
{
	int		i;
	int		exact;
	polygon_t	*splitpoly;
	cbspbrush_t	*b, *f;

	*front = *back = NULL;

	//
	// split plane part of brush ?
	//

	exact = CSG_IsExactOnPlane( in, plane );

	if ( exact == BRUSH_BACK_ON )
	{
		*back = CopyBrush( in );
		return;
	}
	if ( exact == BRUSH_FRONT_ON )
	{
		*front = CopyBrush( in );
		return;
	}

	//
	// real check
	//

	splitpoly = BasePolygonForPlane( plane->norm, plane->dist );

	for ( i = 0; i < in->surfacenum; i++ )
	{
		ClipPolygonInPlace( &splitpoly, in->surfaces[i].pl->norm, in->surfaces[i].pl->dist );
		if ( !splitpoly )
			break;
	}

	if ( !splitpoly )
	{
		// no splitpoly => brush is not split by plane
		// determine on which side of plane is the complete brush

		int	check = -1;

		for ( i = 0; i < in->surfacenum; i++ )
		{
			if ( !in->surfaces[i].p )
				continue;
			check = CheckPolygonWithPlane( in->surfaces[i].p, plane->norm, plane->dist );
			if ( check == POLY_BACK )
				break;
			else if ( check == POLY_FRONT )
				break;
			else if ( check == POLY_ON )
				continue;
			printf( "?" );
		}
		
		if ( check == POLY_BACK )
		{
			*back = CopyBrush( in );
			return;
		}
		else if ( check == POLY_FRONT )
		{
			*front = CopyBrush( in );
			return;
		}
		else
		{
			printf( "can't get planeside of brush.\n" );
			*front = NULL;
			*back = NULL;
			return;
		}
	}

	//
	// split input brush
	//
	
	f = NewBrush( in->surfacenum + 2 );
	b = NewBrush( in->surfacenum + 2 );
	f->surfacenum = b->surfacenum = 0;

	f->original = in->original;
	b->original = in->original;
	f->contents = in->contents;
	b->contents = in->contents;

	for( i = 0; i < in->surfacenum; i++ )
	{
		polygon_t	*fpoly, *bpoly;

		SplitPolygon( in->surfaces[i].p, plane->norm, plane->dist, &fpoly, &bpoly );

		if ( fpoly )
		{
			// add polygon to front brush and copy the rest
			if ( f->surfacenum == in->surfacenum + 2 )
				Error( "reached max surfs\n" );
			memcpy( &f->surfaces[f->surfacenum], &in->surfaces[i], sizeof( csurface_t ) );
			f->surfaces[f->surfacenum].p = fpoly;
			f->surfacenum++;
		}
		if ( bpoly )
		{
			// add polygon to back brush and copy the rest
			if ( b->surfacenum == in->surfacenum + 2 )
				Error( "reached max surfs\n" );
			memcpy( &b->surfaces[b->surfacenum], &in->surfaces[i], sizeof( csurface_t ) );
			b->surfaces[b->surfacenum].p = bpoly;
			b->surfacenum++;
		}
	}

	//
	// add split plane to front and back brush
	//

	// the backside brush gets the plane
	if ( f->surfacenum == in->surfacenum + 2 )
		Error( "reached max surfs\n" );
	b->surfaces[b->surfacenum].pl = plane;
	b->surfaces[b->surfacenum].td = NULL;
	b->surfaces[b->surfacenum].state = SURFACE_STATE_BYSPLIT;
	b->surfaces[b->surfacenum].contents = 0;
	b->surfaces[b->surfacenum].p = splitpoly;
	b->surfacenum++;

	// the frontside brush gets the flipplane
	if ( b->surfacenum == in->surfacenum + 2 )
		Error( "reached max surfs\n" );
	f->surfaces[f->surfacenum].pl = plane->flipplane;
	f->surfaces[f->surfacenum].td = NULL;
	f->surfaces[f->surfacenum].state = SURFACE_STATE_BYSPLIT;
	f->surfaces[f->surfacenum].contents = 0;
	f->surfaces[f->surfacenum].p = PolygonFlip( splitpoly );
	f->surfacenum++;
	
	if ( b->surfacenum < 4 )
	{
		printf( "no back %d\n", b->surfacenum );
		FreeBrush( b );
		b = NULL;
	}
	if ( f->surfacenum < 4 )
	{
		printf( "no front %d\n", f->surfacenum );
		FreeBrush( f );
		f = NULL;
	}

	if ( b )
		CalcBrushBounds( b );
	if ( f )
		CalcBrushBounds( f );

	*back = b;
	*front = f;
}
Esempio n. 10
0
//===========================================================================
// Generates two new brushes, leaving the original
// unchanged
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
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.2 ) { // PLANESIDE_EPSILON)
		// only on back
		*back = CopyBrush( brush );
		return;
	}
	if ( d_back > -0.2 ) { // 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 );
		}
		//free a possible winding
		if ( w ) {
			FreeWinding( w );
		}
		return;
	}

	if ( WindingIsHuge( w ) ) {
		Log_Write( "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->original = s->original;
			cs->winding = cw[j];
			cs->flags &= ~SFL_TESTED;
		}
	}


	// 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_MAP_BOUNDS || b[i]->maxs[j] > MAX_MAP_BOUNDS ) {
				Log_Write( "bogus brush after clip" );
				break;
			}
		}

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

	if ( !( b[0] && b[1] ) ) {
		if ( !b[0] && !b[1] ) {
			Log_Write( "split removed brush\r\n" );
		} else {
			Log_Write( "split not on both sides\r\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; //never use these sides as splitters
		cs->flags &= ~SFL_VISIBLE;
		cs->flags &= ~SFL_TESTED;
		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;
				//Log_Write("tiny volume after clip");
			}
		}
		if ( !b[0] && !b[1] ) {
			Log_Write( "two tiny brushes\r\n" );
		} //end if
	}

	*front = b[0];
	*back = b[1];
} //end of the function SplitBrush
Esempio n. 11
0
File: bsp.c Progetto: otty/cake3
/*
============
ProcessSubModel
============
*/
void ProcessSubModel(int entityNum)
{
	entity_t       *e;
	tree_t         *tree;
	bspBrush_t     *b, *bc;
	node_t         *node;

	e = &entities[entityNum];
	e->firstDrawSurf = numMapDrawSurfs;

	BeginModel(e);

	PatchMapDrawSurfs(e);

	// just put all the brushes in an empty leaf
	// FIXME: patches?
	node = AllocNode();
	node->planenum = PLANENUM_LEAF;
	for(b = e->brushes; b; b = b->next)
	{
		bc = CopyBrush(b);
		bc->next = node->brushlist;
		node->brushlist = bc;
	}

	tree = AllocTree();
	tree->headnode = node;

	ClipSidesIntoTree(e, tree);

	// create drawsurfs for triangle models
	AddTriangleModel(e, qfalse);

	// subdivide each drawsurf as required by shader tesselation or fog
	if(!nosubdivide)
	{
		SubdivideDrawSurfs(e, tree);
	}

	// merge together all common shaders on the same plane and remove 
	// all colinear points, so extra tjunctions won't be generated
	if(!nomerge)
	{
		MergeSides(e, tree);	// !@# testing
	}

	// add in any vertexes required to fix tjunctions
	if(!notjunc)
	{
		FixTJunctions(e);
	}

	// allocate lightmaps for faces and patches
	AllocateLightmaps(e);

	// add references to the final drawsurfs in the apropriate clusters
	FilterDrawsurfsIntoTree(e, tree);

	EndModel(e, node);

	FreeTree(tree);
}