Exemplo n.º 1
0
// NOTE: This is identical to ClipWindingEpsilon, but it does a pre/post translation to improve precision
void ClipWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, const Vector &offset )
{
	TranslateWinding( in, offset );
	ClipWindingEpsilon( in, normal, dist+DotProduct(offset,normal), epsilon, front, back );
	TranslateWinding( in, -offset );
	if ( front && *front )
	{
		TranslateWinding( *front, -offset );
	}
	if ( back && *back )
	{
		TranslateWinding( *back, -offset );
	}
}
Exemplo n.º 2
0
/*
==================
CreateBrushWindings

==================
*/
void CreateBrushWindings (bspbrush_t *brush)
{
	int			i, j;
	winding_t	*w;
	side_t		*side;
	plane_t		*plane;

	// translate the CSG problem to improve precision
	Vector insidePoint = PointInsideBrush( brush );
	Vector offset = -insidePoint;

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

		TranslateWinding( w, -offset );
		side->winding = w;
	}

	BoundBrush (brush);
}
Exemplo n.º 3
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];
}