예제 #1
0
//===========================================================================
// returns the amount the face and the winding overlap
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
float Q3_FaceOnWinding(dsurface_t *surface, winding_t *winding)
{
    int i;
    float dist, area;
    dplane_t plane;
    vec_t *v1, *v2;
    vec3_t normal, edgevec;
    winding_t *w;

    //copy the winding before chopping
    w = CopyWinding(winding);
    //retrieve the surface plane
    Q3_SurfacePlane(surface, plane.normal, &plane.dist);
    //chop the winding with the surface edge planes
    for (i = 0; i < surface->numVerts && w; i++)
    {
        v1 = drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
        v2 = drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
        //create a plane through the edge from v1 to v2, orthogonal to the
        //surface plane and with the normal vector pointing inward
        VectorSubtract(v2, v1, edgevec);
        CrossProduct(edgevec, plane.normal, normal);
        VectorNormalize(normal);
        dist = DotProduct(normal, v1);
        //
        ChopWindingInPlace(&w, normal, dist, -0.1); //CLIP_EPSILON
    } //end for
    if (w)
    {
        area = WindingArea(w);
        FreeWinding(w);
        return area;
    } //end if
    return 0;
} //end of the function Q3_FaceOnWinding
예제 #2
0
파일: brush.c 프로젝트: xonotic/netradient
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;
}
예제 #3
0
//-----------------------------------------------------------------------------
// Purpose: Copies a face and its winding
// Input  : *pFace - 
// Output : face_t
//-----------------------------------------------------------------------------
face_t *CopyFace( face_t *pFace )
{
	face_t *f = NewFaceFromFace( pFace );
	f->w = CopyWinding( pFace->w );

	return f;
}
예제 #4
0
파일: polylib.c 프로젝트: clbr/netradiant
void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
				vec_t epsilon, winding_t **front, winding_t **back)
{
	ClipWindingEpsilonStrict(in, normal, dist, epsilon, front, back);
	/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
	if(!*front && !*back)
		*back = CopyWinding(in);
}
예제 #5
0
파일: qcsg.c 프로젝트: 6779660/halflife
bface_t	*CopyFace (bface_t *f)
{
	bface_t	*n;

	n = NewFaceFromFace (f);
	n->w = CopyWinding (f->w);
	VectorCopy (f->mins, n->mins);
	VectorCopy (f->maxs, n->maxs);
	return n;
}
예제 #6
0
파일: facebsp.c 프로젝트: otty/cake3
/*
=================
BspFaceForPortal
=================
*/
bspFace_t      *BspFaceForPortal(portal_t * p)
{
	bspFace_t      *f;

	f = AllocBspFace();
	f->w = CopyWinding(p->winding);
	f->planenum = p->onnode->planenum & ~1;

	return f;
}
예제 #7
0
face_t *MakeVisibleBSPFaceList( brush_t *list ){
	brush_t     *b;
	int i;
	side_t      *s;
	winding_t   *w;
	face_t      *f, *flist;


	flist = NULL;
	for ( b = list; b != NULL; b = b->next )
	{
		if ( b->detail ) {
			continue;
		}

		for ( i = 0; i < b->numsides; i++ )
		{
			/* get side and winding */
			s = &b->sides[ i ];
			w = s->visibleHull;
			if ( w == NULL ) {
				continue;
			}

			/* ydnar: skip certain faces */
			if ( s->compileFlags & C_SKIP ) {
				continue;
			}

			/* allocate a face */
			f = AllocBspFace();
			f->w = CopyWinding( w );
			f->planenum = s->planenum & ~1;
			f->compileFlags = s->compileFlags;  /* ydnar */

			/* ydnar: set priority */
			f->priority = 0;
			if ( f->compileFlags & C_HINT ) {
				f->priority += HINT_PRIORITY;
			}
			if ( f->compileFlags & C_ANTIPORTAL ) {
				f->priority += ANTIPORTAL_PRIORITY;
			}
			if ( f->compileFlags & C_AREAPORTAL ) {
				f->priority += AREAPORTAL_PRIORITY;
			}

			/* get next face */
			f->next = flist;
			flist = f;
		}
	}

	return flist;
}
예제 #8
0
void
DivideWinding (winding_t *in, plane_t *split, winding_t **front,
			   winding_t **back)
{
	int         i;
	int         counts[3];
	plane_t     plane;
	vec_t       dot;
	winding_t  *tmp;

	counts[0] = counts[1] = counts[2] = 0;

	// determine sides for each point
	for (i = 0; i < in->numpoints; i++) {
		dot = DotProduct (in->points[i], split->normal) - split->dist;
		if (dot > ON_EPSILON)
			counts[SIDE_FRONT]++;
		else if (dot < -ON_EPSILON)
			counts[SIDE_BACK]++;
	}

	*front = *back = NULL;

	if (!counts[SIDE_FRONT]) {
		*back = in;
		return;
	}
	if (!counts[SIDE_BACK]) {
		*front = in;
		return;
	}

	tmp = CopyWinding (in);
	*front = ClipWinding (tmp, split, 0);

	plane.dist = -split->dist;
	VectorNegate (split->normal, plane.normal);

	tmp = CopyWinding (in);
	*back = ClipWinding (tmp, &plane, 0);
}
예제 #9
0
파일: faces.cpp 프로젝트: ArkyRomania/ufoai
static face_t* FaceFromPortal (portal_t* p, bool pside)
{
	face_t* f;
	side_t* side = p->side;

	/* portal does not bridge different visible contents */
	if (!side)
		return nullptr;

	/* nodraw/caulk faces */
	if (side->surfaceFlags & SURF_NODRAW)
		return nullptr;

	f = AllocFace();

	f->texinfo = side->texinfo;
	f->planenum = (side->planenum & ~1) | pside;
	f->portal = p;

	if ((p->nodes[pside]->contentFlags & CONTENTS_WINDOW)
	 && VisibleContents(p->nodes[!pside]->contentFlags ^ p->nodes[pside]->contentFlags) == CONTENTS_WINDOW)
		return nullptr;	/* don't show insides of windows */

	/* do back-clipping */
	if (!config.nobackclip && mapplanes[f->planenum].normal[2] < -0.9) {
		/* this face is not visible from birds view - optimize away
		 * but only if it's not light emitting surface */
		const entity_t* e = &entities[side->brush->entitynum];
		if (!Q_streq(ValueForKey(e, "classname"), "func_rotating")) {
			if (!(curTile->texinfo[f->texinfo].surfaceFlags & SURF_LIGHT)) {
				/* e.g. water surfaces are removed if we set the surfaceFlags
				 * to SURF_NODRAW for this side */
				/*side->surfaceFlags |= SURF_NODRAW;*/
				return nullptr;
			}
		}
	}

	if (pside) {
		f->w = ReverseWinding(p->winding);
		f->contentFlags = p->nodes[1]->contentFlags;
	} else {
		f->w = CopyWinding(p->winding);
		f->contentFlags = p->nodes[0]->contentFlags;
	}
	return f;
}
예제 #10
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;
}
예제 #11
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;
}
예제 #12
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
예제 #13
0
//===========================================================================
// returns the amount the face and the winding overlap
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
float Q1_FaceOnWinding(q1_dface_t *face, winding_t *winding)
{
    int i, edgenum, side;
    float dist, area;
    q1_dplane_t plane;
    vec_t *v1, *v2;
    vec3_t normal, edgevec;
    winding_t *w;

    //
    w = CopyWinding(winding);
    memcpy(&plane, &q1_dplanes[face->planenum], sizeof(q1_dplane_t));
    //check on which side of the plane the face is
    if (face->side)
    {
        VectorNegate(plane.normal, plane.normal);
        plane.dist = -plane.dist;
    } //end if
    for (i = 0; i < face->numedges && w; i++)
    {
        //get the first and second vertex of the edge
        edgenum = q1_dsurfedges[face->firstedge + i];
        side = edgenum > 0;
        //if the face plane is flipped
        v1 = q1_dvertexes[q1_dedges[abs(edgenum)].v[side]].point;
        v2 = q1_dvertexes[q1_dedges[abs(edgenum)].v[!side]].point;
        //create a plane through the edge vector, orthogonal to the face plane
        //and with the normal vector pointing out of the face
        VectorSubtract(v1, v2, edgevec);
        CrossProduct(edgevec, plane.normal, normal);
        VectorNormalize(normal);
        dist = DotProduct(normal, v1);
        //
        ChopWindingInPlace(&w, normal, dist, 0.9); //CLIP_EPSILON
    } //end for
    if (w)
    {
        area = WindingArea(w);
        FreeWinding(w);
        return area;
    } //end if
    return 0;
} //end of the function Q1_FaceOnWinding
예제 #14
0
/*
==================
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;
}
예제 #15
0
//-----------------------------------------------------------------------------
// Purpose: Given an original side and chopped winding, make a face_t 
// Input  : *side - side of the original brush
//			*winding - winding for this face (portion of the side)
// Output : face_t
//-----------------------------------------------------------------------------
face_t *MakeBrushFace( side_t *originalSide, winding_t *winding )
{
	face_t *f = AllocFace();
	f->merged = NULL;
	f->split[0] = f->split[1] = NULL;
	f->w = CopyWinding( winding );
	f->originalface = originalSide;
	//
	// save material info
	//
	f->texinfo = originalSide->texinfo;
	f->dispinfo = -1;

	// save plane info
	f->planenum = originalSide->planenum;
	f->contents = originalSide->contents;

	return f;
}
예제 #16
0
파일: csg4.c 프로젝트: dommul/super8
/*
==================
CopyFacesToOutside
==================
*/
static void CopyFacesToOutside( const brush_t *b )
{
	face_t		*f, *newf;

	outside = NULL;
	for( f = b->faces; f; f = f->next ) {
		if( !f->winding )
			continue;

		numcsgbrushfaces++;
		newf = AllocFace ();
		newf->texturenum = f->texturenum;
		newf->planenum = f->planenum;
		newf->planeside = f->planeside;
		newf->original = f->original;
		newf->winding = CopyWinding( f->winding );
		newf->next = outside;
		newf->contents[0] = CONTENTS_EMPTY;
		newf->contents[1] = b->contents;
		outside = newf;
	}
}
예제 #17
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void DispGetFaceInfo( mapbrush_t *pBrush )
{
	int		i;
	side_t	*pSide;

	// we don't support displacement on entities at the moment!!
	if( pBrush->entitynum != 0 )
	{
		char* pszEntityName = ValueForKey( &entities[pBrush->entitynum], "classname" );
		Error( "Error: displacement found on a(n) %s entity - not supported\n", pszEntityName );
	}

	for( i = 0; i < pBrush->numsides; i++ )
	{
		pSide = &pBrush->original_sides[i];
		if( pSide->pMapDisp )
		{
			// error checking!!
			if( pSide->winding->numpoints != 4 )
				Error( "Trying to create a non-quad displacement!\n" );

			pSide->pMapDisp->face.originalface = pSide;
			pSide->pMapDisp->face.texinfo = pSide->texinfo;
			pSide->pMapDisp->face.dispinfo = -1;
			pSide->pMapDisp->face.planenum = pSide->planenum;
			pSide->pMapDisp->face.numpoints = pSide->winding->numpoints;
			pSide->pMapDisp->face.w = CopyWinding( pSide->winding );
			pSide->pMapDisp->face.contents = pBrush->contents;

			pSide->pMapDisp->face.merged = FALSE;
			pSide->pMapDisp->face.split[0] = FALSE;
			pSide->pMapDisp->face.split[1] = FALSE;

			pSide->pMapDisp->entitynum = pBrush->entitynum;
			pSide->pMapDisp->brushSideID = pSide->id;
		}
	}
}
예제 #18
0
파일: facebsp.c 프로젝트: otty/cake3
/*
=================
MakeVisibleBspFaceList
=================
*/
bspFace_t      *MakeVisibleBspFaceList(bspBrush_t * list)
{
	bspBrush_t     *b;
	int             i;
	side_t         *s;
	winding_t      *w;
	bspFace_t      *f, *flist;

	flist = NULL;
	for(b = list; b; b = b->next)
	{
		if(b->detail)
		{
			continue;
		}
		for(i = 0; i < b->numsides; i++)
		{
			s = &b->sides[i];
			w = s->visibleHull;
			if(!w)
			{
				continue;
			}
			f = AllocBspFace();
			f->w = CopyWinding(w);
			f->planenum = s->planenum & ~1;
			f->next = flist;
			if(s->surfaceFlags & SURF_HINT)
			{
				//f->priority = HINT_PRIORITY;
				f->hint = qtrue;
			}
			flist = f;
		}
	}

	return flist;
}
예제 #19
0
파일: csg4.c 프로젝트: AidHamza/eviltoys
/*
=================
CheckInside

Quick test before running ClipInside; move any faces that are completely
outside the brush to the outside list, without splitting them. This saves us
time in mergefaces later on (and sometimes a lot of memory)
=================
*/
static void
CheckInside(brush_t *b)
{
    face_t *f, *bf, *next;
    face_t *insidelist;
    plane_t clip;
    winding_t *w;

    insidelist = NULL;
    f = inside;
    while (f) {
	next = f->next;
	w = CopyWinding(&f->w);
	for (bf = b->faces; bf; bf = bf->next) {
	    clip = pPlanes[bf->planenum];
	    if (!bf->planeside) {
		VectorSubtract(vec3_origin, clip.normal, clip.normal);
		clip.dist = -clip.dist;
	    }
	    w = ClipWinding(w, &clip, true);
	    if (!w)
		break;
	}
	if (!w) {
	    /* The face is completely outside this brush */
	    f->next = outside;
	    outside = f;
	} else {
	    f->next = insidelist;
	    insidelist = f;
	    FreeMem(w, WINDING, 1);
	}
	f = next;
    }
    inside = insidelist;
}
예제 #20
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int CreateOrigFace( face_t *f )
{
    int         i, j;
    dface_t     *of;
    side_t      *side;
    int         vIndices[128];
    int         eIndex[2];
    winding_t   *pWinding;

    // not a real face!
    if( !f->w )
        return -1;

    // get the original face -- the "side"
    side = f->originalface;

    // get the original face winding
    if( !side->winding )
    {
        return -1;
    }

    //
    // get the next original face
    //
    if( numorigfaces >= MAX_MAP_FACES )
        Error( "Too many faces in map, max = %d", MAX_MAP_FACES );
    of = &dorigfaces[numorigfaces];
    numorigfaces++;

    // set original face to -1 -- it is an origianl face!
    of->origFace = -1;

    //
    // add side to plane list
    //
    side->next = pOrigFaceSideList[f->planenum];
    pOrigFaceSideList[f->planenum] = side;
    side->origIndex = numorigfaces - 1;

    pWinding = CopyWinding( side->winding );

    //
    // plane info
    //
    of->planenum = side->planenum;
    if ( side->contents & CONTENTS_DETAIL )
        of->onNode = 0;
    else
        of->onNode = 1;
    of->side = side->planenum & 1;

    //
    // edge info
    //
    of->firstedge = numsurfedges;
    of->numedges = side->winding->numpoints;

    //
    // material info
    //
    of->texinfo = side->texinfo;
    of->dispinfo = f->dispinfo;

    //
    // save the vertices
    //
    for( i = 0; i < pWinding->numpoints; i++ )
    {
        //
        // compare vertices
        //
        vIndices[i] = GetVertexnum( pWinding->p[i] );
    }

    //
    // save off points -- as edges
    //
    for( i = 0; i < pWinding->numpoints; i++ )
    {
        //
        // look for matching edges first
        //
        eIndex[0] = vIndices[i];
        eIndex[1] = vIndices[(i+1)%pWinding->numpoints];

        for( j = firstmodeledge; j < numedges; j++ )
        {
            if( ( eIndex[0] == dedges[j].v[1] ) &&
                    ( eIndex[1] == dedges[j].v[0] ) &&
                    ( edgefaces[j][0]->contents == f->contents ) )
            {
                // check for multiple backward edges!! -- shouldn't have
                if( edgefaces[j][1] )
                    continue;

                // set back edge
                edgefaces[j][1] = f;

                //
                // get next surface edge
                //
                if( numsurfedges >= MAX_MAP_SURFEDGES )
                    Error( "Too much brush geometry in bsp, numsurfedges == MAX_MAP_SURFEDGES" );
                dsurfedges[numsurfedges] = -j;
                numsurfedges++;
                break;
            }
        }

        if( j == numedges )
        {
            //
            // get next edge
            //
            AddEdge( eIndex[0], eIndex[1], f );

            //
            // get next surface edge
            //
            if( numsurfedges >= MAX_MAP_SURFEDGES )
                Error( "Too much brush geometry in bsp, numsurfedges == MAX_MAP_SURFEDGES" );
            dsurfedges[numsurfedges] = ( numedges - 1 );
            numsurfedges++;
        }
    }

    // return the index
    return ( numorigfaces - 1 );
}
예제 #21
0
void CM_AddFacetBevels( facet_t *facet ) {

	int i, j, k, l;
	int axis, dir, order, flipped;
	float plane[4], d, newplane[4];
	winding_t *w, *w2;
	vec3_t mins, maxs, vec, vec2;

#ifndef ADDBEVELS
	return;
#endif

	Vector4Copy( planes[ facet->surfacePlane ].plane, plane );

	w = BaseWindingForPlane( plane,  plane[3] );
	for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
		if ( facet->borderPlanes[j] == facet->surfacePlane ) {
			continue;
		}
		Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );

		if ( !facet->borderInward[j] ) {
			VectorSubtract( vec3_origin, plane, plane );
			plane[3] = -plane[3];
		}

		ChopWindingInPlace( &w, plane, plane[3], 0.1f );
	}
	if ( !w ) {
		return;
	}

	WindingBounds( w, mins, maxs );

	// add the axial planes
	order = 0;
	for ( axis = 0 ; axis < 3 ; axis++ )
	{
		for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
		{
			VectorClear( plane );
			plane[axis] = dir;
			if ( dir == 1 ) {
				plane[3] = maxs[axis];
			} else {
				plane[3] = -mins[axis];
			}
			//if it's the surface plane
			if ( CM_PlaneEqual( &planes[facet->surfacePlane], plane, &flipped ) ) {
				continue;
			}
			// see if the plane is allready present
			for ( i = 0 ; i < facet->numBorders ; i++ ) {
				if ( CM_PlaneEqual( &planes[facet->borderPlanes[i]], plane, &flipped ) ) {
					break;
				}
			}

			if ( i == facet->numBorders ) {
				if ( facet->numBorders > 4 + 6 + 16 ) {
					Com_Printf( "ERROR: too many bevels\n" );
				}
				facet->borderPlanes[facet->numBorders] = CM_FindPlane2( plane, &flipped );
				facet->borderNoAdjust[facet->numBorders] = 0;
				facet->borderInward[facet->numBorders] = flipped;
				facet->numBorders++;
			}
		}
	}
	//
	// add the edge bevels
	//
	// test the non-axial plane edges
	for ( j = 0 ; j < w->numpoints ; j++ )
	{
		k = ( j + 1 ) % w->numpoints;
		VectorSubtract( w->p[j], w->p[k], vec );
		//if it's a degenerate edge
		if ( VectorNormalize( vec ) < 0.5 ) {
			continue;
		}
		CM_SnapVector( vec );
		for ( k = 0; k < 3 ; k++ )
			if ( vec[k] == -1 || vec[k] == 1 ) {
				break;
			}           // axial
		if ( k < 3 ) {
			continue;   // only test non-axial edges

		}
		// try the six possible slanted axials from this edge
		for ( axis = 0 ; axis < 3 ; axis++ )
		{
			for ( dir = -1 ; dir <= 1 ; dir += 2 )
			{
				// construct a plane
				VectorClear( vec2 );
				vec2[axis] = dir;
				CrossProduct( vec, vec2, plane );
				if ( VectorNormalize( plane ) < 0.5 ) {
					continue;
				}
				plane[3] = DotProduct( w->p[j], plane );

				// if all the points of the facet winding are
				// behind this plane, it is a proper edge bevel
				for ( l = 0 ; l < w->numpoints ; l++ )
				{
					d = DotProduct( w->p[l], plane ) - plane[3];
					if ( d > 0.1 ) {
						break;  // point in front
					}
				}
				if ( l < w->numpoints ) {
					continue;
				}

				//if it's the surface plane
				if ( CM_PlaneEqual( &planes[facet->surfacePlane], plane, &flipped ) ) {
					continue;
				}
				// see if the plane is allready present
				for ( i = 0 ; i < facet->numBorders ; i++ ) {
					if ( CM_PlaneEqual( &planes[facet->borderPlanes[i]], plane, &flipped ) ) {
						break;
					}
				}

				if ( i == facet->numBorders ) {
					if ( facet->numBorders > 4 + 6 + 16 ) {
						Com_Printf( "ERROR: too many bevels\n" );
					}
					facet->borderPlanes[facet->numBorders] = CM_FindPlane2( plane, &flipped );

					for ( k = 0 ; k < facet->numBorders ; k++ ) {
						if ( facet->borderPlanes[facet->numBorders] ==
							 facet->borderPlanes[k] ) {
							Com_Printf( "WARNING: bevel plane already used\n" );
						}
					}

					facet->borderNoAdjust[facet->numBorders] = 0;
					facet->borderInward[facet->numBorders] = flipped;
					//
					w2 = CopyWinding( w );
					Vector4Copy( planes[facet->borderPlanes[facet->numBorders]].plane, newplane );
					if ( !facet->borderInward[facet->numBorders] ) {
						VectorNegate( newplane, newplane );
						newplane[3] = -newplane[3];
					} //end if
					ChopWindingInPlace( &w2, newplane, newplane[3], 0.1f );
					if ( !w2 ) {
						// TTimo - can't stand this, useless and noisy
						//Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
						continue;
					} else {
						FreeWinding( w2 );
					}
					//
					facet->numBorders++;
					//already got a bevel
//					break;
				}
			}
		}
	}
	FreeWinding( w );

#ifndef BSPC
	//add opposite plane
	facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
	facet->borderNoAdjust[facet->numBorders] = 0;
	facet->borderInward[facet->numBorders] = qtrue;
	facet->numBorders++;
#endif //BSPC

}
예제 #22
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];
}
예제 #23
0
파일: brush.c 프로젝트: xonotic/netradient
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];
}
예제 #24
0
//===========================================================================
// create a tmp AAS area from a leaf node
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
tmp_node_t *AAS_CreateArea(node_t *node)
{
	int pside;
	int areafaceflags;
	portal_t	*p;
	tmp_face_t *tmpface;
	tmp_area_t *tmparea;
	tmp_node_t *tmpnode;

	//create an area from this leaf
	tmparea = AAS_AllocTmpArea();
	tmparea->tmpfaces = NULL;
	//clear the area face flags
	areafaceflags = 0;
	//make aas faces from the portals
	for (p = node->portals; p; p = p->next[pside])
	{
		pside = (p->nodes[1] == node);
		//don't create faces from very small portals
//		if (WindingArea(p->winding) < 1) continue;
		//if there's already a face created for this portal
		if (p->tmpface)
		{
			//add the back side of the face to the area
			AAS_AddFaceSideToArea(p->tmpface, 1, tmparea);
		} //end if
		else
		{
			tmpface = AAS_AllocTmpFace();
			//set the face pointer at the portal so we can see from
			//the portal there's a face created for it
			p->tmpface = tmpface;
			//FIXME: test this change
			//tmpface->planenum = (p->planenum & ~1) | pside;
			tmpface->planenum = p->planenum ^ pside;
			if (pside) tmpface->winding = ReverseWinding(p->winding);
			else tmpface->winding = CopyWinding(p->winding);
#ifdef L_DEBUG
			//
			AAS_CheckFaceWindingPlane(tmpface);
#endif //L_DEBUG
			//if there's solid at the other side of the portal
			if (p->nodes[!pside]->contents & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP))
			{
				tmpface->faceflags |= FACE_SOLID;
			} //end if
			//else there is no solid at the other side and if there
			//is a liquid at this side
			else if (node->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA))
			{
				tmpface->faceflags |= FACE_LIQUID;
				//if there's no liquid at the other side
				if (!(p->nodes[!pside]->contents & (CONTENTS_WATER|CONTENTS_SLIME|CONTENTS_LAVA)))
				{
					tmpface->faceflags |= FACE_LIQUIDSURFACE;
				} //end if
			} //end else
			//if there's ladder contents at other side of the portal
			if ((p->nodes[pside]->contents & CONTENTS_LADDER) ||
					(p->nodes[!pside]->contents & CONTENTS_LADDER))
			{

				//NOTE: doesn't have to be solid at the other side because
				// when standing one can use a crouch area (which is not solid)
				// as a ladder
				// imagine a ladder one can walk underthrough,
				// under the ladder against the ladder is a crouch area
				// the (vertical) sides of this crouch area area also used as
				// ladder sides when standing (not crouched)
				tmpface->faceflags |= FACE_LADDER;
			} //end if
			//if it is possible to stand on the face
			if (AAS_GroundFace(tmpface))
			{
				tmpface->faceflags |= FACE_GROUND;
			} //end if
			//
			areafaceflags |= tmpface->faceflags;
			//no aas face number yet (zero is a dummy in the aasworld faces)
			tmpface->aasfacenum = 0;
			//add the front side of the face to the area
			AAS_AddFaceSideToArea(tmpface, 0, tmparea);
		} //end else
	} //end for
	qprintf("\r%6d", tmparea->areanum);
	//presence type in the area
	tmparea->presencetype = ~node->expansionbboxes & cfg.allpresencetypes;
	//
	tmparea->contents = 0;
	if (node->contents & CONTENTS_CLUSTERPORTAL) tmparea->contents |= AREACONTENTS_CLUSTERPORTAL;
	if (node->contents & CONTENTS_MOVER) tmparea->contents |= AREACONTENTS_MOVER;
	if (node->contents & CONTENTS_TELEPORTER) tmparea->contents |= AREACONTENTS_TELEPORTER;
	if (node->contents & CONTENTS_JUMPPAD) tmparea->contents |= AREACONTENTS_JUMPPAD;
	if (node->contents & CONTENTS_DONOTENTER) tmparea->contents |= AREACONTENTS_DONOTENTER;
	if (node->contents & CONTENTS_WATER) tmparea->contents |= AREACONTENTS_WATER;
	if (node->contents & CONTENTS_LAVA) tmparea->contents |= AREACONTENTS_LAVA;
	if (node->contents & CONTENTS_SLIME) tmparea->contents |= AREACONTENTS_SLIME;
	if (node->contents & CONTENTS_NOTTEAM1) tmparea->contents |= AREACONTENTS_NOTTEAM1;
	if (node->contents & CONTENTS_NOTTEAM2) tmparea->contents |= AREACONTENTS_NOTTEAM2;

	//store the bsp model that's inside this node
	tmparea->modelnum = node->modelnum;
	//sorta check for flipped area faces (remove??)
	AAS_FlipAreaFaces(tmparea);
	//check if the area is ok (remove??)
	AAS_CheckArea(tmparea);
	//
	tmpnode = AAS_AllocTmpNode();
	tmpnode->planenum = 0;
	tmpnode->children[0] = 0;
	tmpnode->children[1] = 0;
	tmpnode->tmparea = tmparea;
	//
	return tmpnode;
} //end of the function AAS_CreateArea
예제 #25
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];
}
예제 #26
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
예제 #27
0
void AddWindingToConvexHull(winding_t * w, winding_t ** hull, vec3_t normal) {
	int             i, j, k, numHullPoints, numNew;
	float          *p, *copy, d;
	vec3_t          dir;
	vec3_t          hullPoints[MAX_HULL_POINTS], newHullPoints[MAX_HULL_POINTS], hullDirs[MAX_HULL_POINTS];
	bool        hullSide[MAX_HULL_POINTS], outside;

	if(!*hull) {
		*hull = CopyWinding(w);
		return;
	}

	numHullPoints = (*hull)->numpoints;
	Com_Memcpy(hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t));

	for(i = 0; i < w->numpoints; i++) {
		p = w->p[i];

		// calculate hull side vectors
		for(j = 0; j < numHullPoints; j++) {
			k = (j + 1) % numHullPoints;

			VectorSubtract(hullPoints[k], hullPoints[j], dir);
			VectorNormalize2(dir, dir);
			CrossProduct(normal, dir, hullDirs[j]);
		}

		outside = false;
		for(j = 0; j < numHullPoints; j++) {
			VectorSubtract(p, hullPoints[j], dir);
			d = DotProduct(dir, hullDirs[j]);
			if(d >= ON_EPSILON) {
				outside = true;
			}
			if(d >= -ON_EPSILON) {
				hullSide[j] = true;
			} else {
				hullSide[j] = false;
			}
		}

		// if the point is effectively inside, do nothing
		if(!outside) {
			continue;
		}

		// find the back side to front side transition
		for(j = 0; j < numHullPoints; j++) {
			if(!hullSide[j % numHullPoints] && hullSide[(j + 1) % numHullPoints]) {
				break;
			}
		}
		if(j == numHullPoints) {
			continue;
		}

		// insert the point here
		VectorCopy(p, newHullPoints[0]);
		numNew = 1;

		// copy over all points that aren't double fronts
		j = (j + 1) % numHullPoints;
		for(k = 0; k < numHullPoints; k++) {
			if(hullSide[(j + k) % numHullPoints] && hullSide[(j + k + 1) % numHullPoints]) {
				continue;
			}
			copy = hullPoints[(j + k + 1) % numHullPoints];
			VectorCopy(copy, newHullPoints[numNew]);
			numNew++;
		}

		numHullPoints = numNew;
		Com_Memcpy(hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t));
	}

	FreeWinding(*hull);
	w = AllocWinding(numHullPoints);
	w->numpoints = numHullPoints;
	*hull = w;
	Com_Memcpy(w->p, hullPoints, numHullPoints * sizeof(vec3_t));
}
예제 #28
0
/*
=============
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilon(winding_t * in, vec3_t normal, vec_t dist, vec_t epsilon, winding_t ** front, winding_t ** back) {
	vec_t           dists[MAX_POINTS_ON_WINDING + 4], *p1, *p2;
	int             sides[MAX_POINTS_ON_WINDING + 4], counts[3], i, j, maxpts;
	static vec_t    dot; // VC 4.2 optimizer bug if not static
	vec3_t          mid;
	winding_t      *f, *b;

	counts[0] = counts[1] = counts[2] = 0;

	// determine sides for each point
	for(i = 0; i < in->numpoints; i++) {
		dot = DotProduct(in->p[i], normal);
		dot -= dist;
		dists[i] = dot;
		if(dot > epsilon) {
			sides[i] = SIDE_FRONT;
		}
		else if(dot < -epsilon) {
			sides[i] = SIDE_BACK;
		} else {
			sides[i] = SIDE_ON;
		}
		counts[sides[i]]++;
	}
	sides[i] = sides[0];
	dists[i] = dists[0];

	*front = *back = NULL;

	if(!counts[0]) {
		*back = CopyWinding(in);
		return;
	}
	if(!counts[1]) {
		*front = CopyWinding(in);
		return;
	}

	maxpts = in->numpoints + 4;	// cant use counts[0]+2 because
	// of fp grouping errors

	*front = f = AllocWinding(maxpts);
	*back = b = AllocWinding(maxpts);

	for(i = 0; i < in->numpoints; i++) {
		p1 = in->p[i];

		if(sides[i] == SIDE_ON) {
			VectorCopy(p1, f->p[f->numpoints]);
			f->numpoints++;
			VectorCopy(p1, b->p[b->numpoints]);
			b->numpoints++;
			continue;
		}

		if(sides[i] == SIDE_FRONT) {
			VectorCopy(p1, f->p[f->numpoints]);
			f->numpoints++;
		}
		if(sides[i] == SIDE_BACK) {
			VectorCopy(p1, b->p[b->numpoints]);
			b->numpoints++;
		}

		if(sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) {
			continue;
		}

		// generate a split point
		p2 = in->p[(i + 1) % in->numpoints];

		dot = dists[i] / (dists[i] - dists[i + 1]);
		for(j = 0; j < 3; j++) { // avoid round off error when possible
			if(normal[j] == 1) {
				mid[j] = dist;
			} else if(normal[j] == -1) {
				mid[j] = -dist;
			}else {
				mid[j] = p1[j] + dot * (p2[j] - p1[j]);
			}
		}

		VectorCopy(mid, f->p[f->numpoints]);
		f->numpoints++;
		VectorCopy(mid, b->p[b->numpoints]);
		b->numpoints++;
	}

	if(f->numpoints > maxpts || b->numpoints > maxpts) {
		Com_Error(ERR_DROP, "ClipWinding: points exceeded estimate");
	}
	if(f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) {
		Com_Error(ERR_DROP, "ClipWinding: MAX_POINTS_ON_WINDING");
	}
}
예제 #29
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];
}
예제 #30
0
파일: cm_patch.cpp 프로젝트: Jsoucek/q3ce
/*
==================
CM_AddFacetBevels
==================
*/
void CM_AddFacetBevels( facet_t *facet ) {

	int i, j, k, l;
	int axis, dir, order, flipped;
	planeDef_t plane,newplane;
	bfixed d;
	winding_t *w, *w2;
	bvec3_t mins, maxs;
	avec3_t vec, vec2;

	plane=planes[ facet->surfacePlane ].pd;

	w = BaseWindingForPlane( plane.normal,  plane.dist );
	for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
		if (facet->borderPlanes[j] == facet->surfacePlane) continue;
		plane=planes[ facet->borderPlanes[j] ].pd;

		if ( !facet->borderInward[j] ) {
			VectorSubtract( avec3_origin, plane.normal, plane.normal );
			plane.dist = -plane.dist;
		}

		ChopWindingInPlace( &w, plane.normal, plane.dist, BFIXED(0,1) );
	}
	if ( !w ) {
		return;
	}

	WindingBounds(w, mins, maxs);

	// add the axial planes
	order = 0;
	for ( axis = 0 ; axis < 3 ; axis++ )
	{
		for ( dir = -1 ; dir <= 1 ; dir += 2, order++ )
		{
			VectorClear(plane.normal);
			plane.normal[axis] = MAKE_AFIXED(dir);
			if (dir == 1) {
				plane.dist = maxs[axis];
			}
			else {
				plane.dist = -mins[axis];
			}
			//if it's the surface plane
			if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
				continue;
			}
			// see if the plane is allready present
			for ( i = 0 ; i < facet->numBorders ; i++ ) {
				if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped))
					break;
			}

			if ( i == facet->numBorders ) {
				if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
				facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);
				facet->borderNoAdjust[facet->numBorders] = 0;
				facet->borderInward[facet->numBorders] = flipped;
				facet->numBorders++;
			}
		}
	}
	//
	// add the edge bevels
	//
	// test the non-axial plane edges
	for ( j = 0 ; j < w->numpoints ; j++ )
	{
		k = (j+1)%w->numpoints;
		bvec3_t tmp;
		VectorSubtract (w->p[j], w->p[k], tmp);
		//if it's a degenerate edge
		if (VectorNormalizeB2A(tmp,vec) < BFIXED(0,5))
			continue;
		CM_SnapVector(vec);
		for ( k = 0; k < 3 ; k++ )
			if ( vec[k] == -AFIXED_1 || vec[k] == AFIXED_1 )
				break;	// axial
		if ( k < 3 )
			continue;	// only test non-axial edges

		// try the six possible slanted axials from this edge
		for ( axis = 0 ; axis < 3 ; axis++ )
		{
			for ( dir = -1 ; dir <= 1 ; dir += 2 )
			{
				// construct a plane
				VectorClear (vec2);
				vec2[axis] = MAKE_AFIXED(dir);
				CrossProduct (vec, vec2, plane.normal);
				if (VectorNormalize(plane.normal) < AFIXED(0,5))
					continue;
				plane.dist = FIXED_VEC3DOT (w->p[j], plane.normal);

				// if all the points of the facet winding are
				// behind this plane, it is a proper edge bevel
				for ( l = 0 ; l < w->numpoints ; l++ )
				{
					d = FIXED_VEC3DOT(w->p[l], plane.normal) - plane.dist;
					if (d > BFIXED(0,1))
						break;	// point in front
				}
				if ( l < w->numpoints )
					continue;

				//if it's the surface plane
				if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) {
					continue;
				}
				// see if the plane is allready present
				for ( i = 0 ; i < facet->numBorders ; i++ ) {
					if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) {
							break;
					}
				}

				if ( i == facet->numBorders ) {
					if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n");
					facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped);

					for ( k = 0 ; k < facet->numBorders ; k++ ) {
						if (facet->borderPlanes[facet->numBorders] ==
							facet->borderPlanes[k]) Com_Printf("WARNING: bevel plane already used\n");
					}

					facet->borderNoAdjust[facet->numBorders] = 0;
					facet->borderInward[facet->numBorders] = flipped;
					//
					w2 = CopyWinding(w);
					newplane=planes[facet->borderPlanes[facet->numBorders]].pd;
					if (!facet->borderInward[facet->numBorders])
					{
						VectorNegate(newplane.normal, newplane.normal);
						newplane.dist = -newplane.dist;
					} //end if
					ChopWindingInPlace( &w2, newplane.normal, newplane.dist, BFIXED(0,1) );
					if (!w2) {
						Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
						continue;
					}
					else {
						FreeWinding(w2);
					}
					//
					facet->numBorders++;
					//already got a bevel
//					break;
				}
			}
		}
	}
	FreeWinding( w );

#ifndef BSPC
	//add opposite plane
	facet->borderPlanes[facet->numBorders] = facet->surfacePlane;
	facet->borderNoAdjust[facet->numBorders] = 0;
	facet->borderInward[facet->numBorders] = qtrue;
	facet->numBorders++;
#endif //BSPC

}