Beispiel #1
0
	void Split(rplane &plane) {
		for(iterator i=begin();i!=end();)
		{
			RPortal *pPortal=*i;
			if(!IS_EQ_PLANE(pPortal->plane,plane))
			{
				RPortal *pFront=new RPortal;
				pFront->nID=g_nPortalCount++;
				pFront->pFrom=pPortal->pFrom;
				pFront->pTo=pPortal->pTo;
				pFront->pWinding=new RWinding(pPortal->pWinding);
				pFront->pWinding=ClipWinding(pFront->pWinding,plane);
				if(pFront->pWinding)
				{
					pFront->plane=pPortal->plane;
					i=insert(i,pFront);
					i++;
				}else
					delete pFront;

				// 뒷쪽winding 은 있는걸 활용한다..
				pPortal->pWinding=ClipWinding(pPortal->pWinding,-plane);
				if(!pPortal->pWinding)
				{
					delete(pPortal);
					i=erase(i);
					continue;
				}
			}
			i++;
		}
	}
Beispiel #2
0
/*
================
MakeHeadnodePortals

The created portals will face the global outside_node
================
*/
void MakeHeadnodePortals (node_t *node)
{
	vec3_t		bounds[2];
	int			i, j, n;
	portal_t	*p, *portals[6];
	plane_t		bplanes[6], *pl;
	int			side;
	
	Draw_ClearWindow ();
	
// pad with some space so there will never be null volume leafs
	for (i=0 ; i<3 ; i++)
	{
		bounds[0][i] = brushset->mins[i] - SIDESPACE;
		bounds[1][i] = brushset->maxs[i] + SIDESPACE;
	}
	
	outside_node.contents = CONTENTS_SOLID;
	outside_node.portals = NULL;

	for (i=0 ; i<3 ; i++)
		for (j=0 ; j<2 ; j++)
		{
			n = j*3 + i;

			p = AllocPortal ();
			portals[n] = p;
			
			pl = &bplanes[n];
			memset (pl, 0, sizeof(*pl));
			if (j)
			{
				pl->normal[i] = -1;
				pl->dist = -bounds[j][i];
			}
			else
			{
				pl->normal[i] = 1;
				pl->dist = bounds[j][i];
			}
			p->planenum = FindPlane (pl, &side);
	
			p->winding = BaseWindingForPlane (pl);
			if (side)
				AddPortalToNodes (p, &outside_node, node);
			else
				AddPortalToNodes (p, node, &outside_node);
		}
		
// clip the basewindings by all the other planes
	for (i=0 ; i<6 ; i++)
	{
		for (j=0 ; j<6 ; j++)
		{
			if (j == i)
				continue;
			portals[i]->winding = ClipWinding (portals[i]->winding, &bplanes[j], true);
		}
	}
}
Beispiel #3
0
/*
=================
ChopWinding

Returns the fragment of in that is on the front side
of the cliping plane.  The original is freed.
=================
*/
winding_t	*ChopWinding (winding_t *in, normal_t normal, fixed_t dist)
{
	winding_t	*f, *b;

	ClipWinding (in, normal, dist, &f, &b);
	Z_Free (in);
	if (b)
		Z_Free (b);
	return f;
}
Beispiel #4
0
/*
=================
ChopWinding

Returns the fragment of in that is on the front side
of the cliping plane.  The original is freed.
=================
*/
winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
{
	winding_t	*f, *b;

	ClipWinding (in, normal, dist, &f, &b);
	free (in);
	if (b)
		free (b);
	return f;
}
Beispiel #5
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);
}
Beispiel #6
0
/*	Returns the visible polygon on a face
*/
winding_t *MakeFaceWinding(brush_t *b,face_t *face)
{
	winding_t	*w;
	face_t		*clip;
	plane_t		plane;
	BOOL		past;

	// get a poly that covers an effectively infinite area
	w = BasePolyForPlane (&face->plane);

	// chop the poly by all of the other faces
	past = FALSE;
	for (clip = b->brush_faces ; clip && w ; clip=clip->next)
	{
		if (clip == face)
		{
			past = TRUE;
			continue;
		}
		if(Math_DotProduct (face->plane.normal, clip->plane.normal) > 0.999
			&& fabs(face->plane.dist - clip->plane.dist) < 0.01 )
		{	// identical plane, use the later one
			if (past)
			{
				free (w);
				return NULL;
			}
			continue;
		}

		// flip the plane, because we want to keep the back side
		Math_VectorSubtract(vec3_origin,clip->plane.normal,plane.normal);
		plane.dist = -clip->plane.dist;

		w = ClipWinding(w,&plane,FALSE);
		if (!w)
			return w;
	}

	if (w->numpoints < 3)
	{
		free(w);
		w = NULL;
	}

	if (!w)
		printf ("unused plane\n");

	return w;
}
Beispiel #7
0
/*
==================
MakeNodePortal

create the new portal by taking the full plane winding for the cutting plane
and clipping it by all of the planes from the other portals.

Each portal tracks the node that created it, so unused nodes
can be removed later.
==================
*/
void MakeNodePortal (node_t *node)
{
	portal_t	*new_portal, *p;
	dplane_t	*plane;
	dplane_t	clipplane;
	winding_t	*w;
	int			side;

	plane = &dplanes[node->planenum];
	w = BaseWindingForPlane (plane);

	new_portal = AllocPortal ();
	new_portal->plane = *plane;
	new_portal->onnode = node;

	side = 0;	// shut up compiler warning
	for (p = node->portals ; p ; p = p->next[side])	
	{
		clipplane = p->plane;
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
		{
			clipplane.dist = -clipplane.dist;
			VectorSubtract (vec3_origin, clipplane.normal, clipplane.normal);
			side = 1;
		}
		else
			Error ("MakeNodePortal: mislinked portal");

		w = ClipWinding (w, &clipplane, true);
		if (!w)
		{
			printf ("WARNING: MakeNodePortal:new portal was clipped away from node@(%.0f,%.0f,%.0f)-(%.0f,%.0f,%.0f)\n",
					node->mins[0], node->mins[1], node->mins[2], 
					node->maxs[0], node->maxs[1], node->maxs[2]);
			FreePortal (new_portal);
			return;
		}
	}

	new_portal->winding = w;	
	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
}
Beispiel #8
0
/*
=================
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;
}
Beispiel #9
0
void CreateBrushFaces (void)
{
	int				i,j, k;
	vec_t			r;
	face_t			*f;
	winding_t		*w;
	plane_t			plane;
	mface_t			*mf;
	
	brush_mins[0] = brush_mins[1] = brush_mins[2] = 99999;
	brush_maxs[0] = brush_maxs[1] = brush_maxs[2] = -99999;

	brush_faces = NULL;
	
	for (i=0 ; i<numbrushfaces ; i++)
	{
		mf = &faces[i];
		
		w = BaseWindingForPlane (&mf->plane);

		for (j=0 ; j<numbrushfaces && w ; j++)
		{
			if (j == i)
				continue;
		// flip the plane, because we want to keep the back side
			VectorSubtract (vec3_origin,faces[j].plane.normal, plane.normal);
			plane.dist = -faces[j].plane.dist;
			
			w = ClipWinding (w, &plane, false);
		}
		
		if (!w)
			continue;	// overcontrained plane
			
	// this face is a keeper
		f = AllocFace ();
		f->numpoints = w->numpoints;
		if (f->numpoints > MAXEDGES)
			Error ("f->numpoints > MAXEDGES");
	
		for (j=0 ; j<w->numpoints ; j++)
		{
			for (k=0 ; k<3 ; k++)
			{
				r = Q_rint (w->points[j][k]);
				if ( fabs(w->points[j][k] - r) < ZERO_EPSILON)
					f->pts[j][k] = r;
				else
					f->pts[j][k] = w->points[j][k];
					
				if (f->pts[j][k] < brush_mins[k])
					brush_mins[k] = f->pts[j][k];
				if (f->pts[j][k] > brush_maxs[k])
					brush_maxs[k] = f->pts[j][k];				
			}
			
		}
		FreeWinding (w);
		f->texturenum = mf->texinfo;
		f->planenum = FindPlane (&mf->plane, &f->planeside);
		f->next = brush_faces;
		brush_faces = f;
		CheckFace (f);
	}	
}
Beispiel #10
0
/*
=============
SubdividePatch
=============
*/
void	SubdividePatch (patch_t *patch)
{
	winding_t *w, *o1, *o2;
	vec3_t	total;
	vec3_t	split;
	vec_t	dist;
	vec_t	widest = -1;
	int		i, j, widest_axis = -1;
	int		subdivide_it = 0;
	vec_t	v;
	patch_t	*newp;

	w = patch->winding;

	VectorSubtract (patch->maxs, patch->mins, total);
	for (i=0 ; i<3 ; i++)
	{
		if ( total[i] > widest )
			{
			widest_axis = i;
			widest = total[i];
			}
		if ( total[i] > patch->chop
		  || (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] )
		  && total[i] > minchop )
		{
			subdivide_it = 1;
		}
	}

	if ( subdivide_it )
	{
		//
		// split the winding
		//
		VectorCopy (vec3_origin, split);
		split[widest_axis] = 1;
		dist = (patch->mins[widest_axis] + patch->maxs[widest_axis])*0.5f;
		ClipWinding (w, split, dist, &o1, &o2);

		//
		// create a new patch
		//
		if (num_patches == MAX_PATCHES)
			Error ("MAX_PATCHES");
		newp = &patches[num_patches];

		newp->next = patch->next;
		patch->next = newp;

		patch->winding = o1;
		newp->winding = o2;

		VectorCopy( patch->face_mins, newp->face_mins );
		VectorCopy( patch->face_maxs, newp->face_maxs );

		VectorCopy( patch->baselight, newp->baselight );
		VectorCopy( patch->directlight, newp->directlight );
		VectorCopy( patch->totallight, newp->totallight );
		VectorCopy( patch->reflectivity, newp->reflectivity );
		newp->plane = patch->plane;
		newp->sky = patch->sky;
		newp->chop = patch->chop;
		newp->faceNumber = patch->faceNumber;

		num_patches++;

		patch->area = WindingArea (patch->winding);
		newp->area = WindingArea (newp->winding);

		WindingCenter (patch->winding, patch->origin);
		WindingCenter (newp->winding, newp->origin);

#ifdef PHONG_NORMAL_PATCHES
// This seems to be a bad idea for some reason.  Leave it turned off for now.
		// Set (Copy or Calculate) the synthetic normal for these new patches
		VectorAdd (patch->origin, patch->plane->normal, patch->origin);
		VectorAdd (newp->origin, newp->plane->normal, newp->origin);
		GetPhongNormal( patch->faceNumber, patch->origin, patch->normal );
		GetPhongNormal( newp->faceNumber, newp->origin, newp->normal );
		VectorSubtract( patch->origin, patch->plane->normal, patch->origin);
		VectorSubtract( newp->origin, newp->plane->normal, newp->origin);
#else
		VectorCopy( patch->plane->normal, patch->normal );
		VectorCopy( newp->plane->normal, newp->normal );
#endif
		VectorAdd( patch->origin, patch->normal, patch->origin );
		VectorAdd( newp->origin, newp->normal, newp->origin );

		WindingBounds(patch->winding, patch->mins, patch->maxs);
		WindingBounds(newp->winding, newp->mins, newp->maxs);

		// Subdivide patch even more if on the edge of the face; this is a hack!
		VectorSubtract (patch->maxs, patch->mins, total);
		if ( total[0] < patch->chop && total[1] < patch->chop && total[2] < patch->chop )
			for ( i=0; i<3; i++ )
				if ( (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] )
				  && total[i] > minchop )
				{
					patch->chop = max( minchop, patch->chop / 2 );
					break;
				}

		SubdividePatch (patch);

		// Subdivide patch even more if on the edge of the face; this is a hack!
		VectorSubtract (newp->maxs, newp->mins, total);
		if ( total[0] < newp->chop && total[1] < newp->chop && total[2] < newp->chop )
			for ( i=0; i<3; i++ )
				if ( (newp->face_maxs[i] == newp->maxs[i] || newp->face_mins[i] == newp->mins[i] )
				  && total[i] > minchop )
				{
					newp->chop = max( minchop, newp->chop / 2 );
					break;
				}

		SubdividePatch (newp);
	}
}
Beispiel #11
0
static clipleaf_t *
carve_leaf (hull_t *hull, nodeleaf_t *nodeleafs, clipleaf_t *leaf, int num)
{
	mclipnode_t *node;
	plane_t    *plane;
	winding_t  *winding, *fw, *bw;
	clipport_t *portal;
	clipport_t *new_portal;
	clipport_t *next_portal;
	clipleaf_t *other_leaf;
	clipleaf_t *new_leaf;
	plane_t     clipplane;
	int         side;

	if (num < 0) {
		// we've hit a leaf. all done
		leaf->contents = num;
		return leaf;
	}
	node = hull->clipnodes + num;
	plane = hull->planes + node->planenum;

	winding = BaseWindingForPlane (plane);
	for (portal = leaf->portals; portal; portal = portal->next[side]) {
		clipplane = hull->planes[portal->planenum];
		side = (portal->leafs[1] == leaf);
		if (side)
			PlaneFlip (&clipplane, &clipplane);
		winding = ClipWinding (winding, &clipplane, true);
	}
	new_leaf = alloc_leaf ();
	portal = leaf->portals;
	leaf->portals = 0;
	for (; portal; portal = next_portal) {
		side = (portal->leafs[1] == leaf);
		next_portal = portal->next[side];
		other_leaf = portal->leafs[!side];
		remove_portal (portal, other_leaf);

		DivideWinding (portal->winding, plane, &fw, &bw);
		if (!fw) {
			if (side)
				add_portal (portal, other_leaf, new_leaf);
			else
				add_portal (portal, new_leaf, other_leaf);
			continue;
		}
		if (!bw) {
			if (side)
				add_portal (portal, other_leaf, leaf);
			else
				add_portal (portal, leaf, other_leaf);
			continue;
		}
		new_portal = alloc_portal ();
		new_portal->planenum = portal->planenum;
		new_portal->winding = bw;
		FreeWinding (portal->winding);
		portal->winding = fw;

		if (side) {
			add_portal (portal, other_leaf, leaf);
			add_portal (new_portal, other_leaf, new_leaf);
		} else {
			add_portal (portal, leaf, other_leaf);
			add_portal (new_portal, new_leaf, other_leaf);
		}
	}
	new_portal = alloc_portal ();
	new_portal->planenum = node->planenum;
	new_portal->winding = winding;
	add_portal (new_portal, leaf, new_leaf);

	nodeleafs[num].leafs[0] = carve_leaf (hull, nodeleafs, leaf,
										  node->children[0]);
	nodeleafs[num].leafs[1] = carve_leaf (hull, nodeleafs, new_leaf,
										  node->children[1]);
	return 0;
}
/*
================
CutNodePortals_r
================
*/
static void CutNodePortals_r (node_t *node)
{
	plane_t 	*plane, clipplane;
	node_t		*f, *b, *other_node;
	portal_t	*p, *new_portal, *next_portal;
	winding_t	*w, *frontwinding, *backwinding;
	int			side;

	// Vic: properly calculate the bounding box
	CalcNodeBounds (node);

	//
	// separate the portals on node into it's children
	//
	if (node->contents)
		return;			// at a leaf, no more dividing

	plane = &mapplanes[node->planenum];

	f = node->children[0];
	b = node->children[1];

	//
	// create the new portal by taking the full plane winding for the cutting plane
	// and clipping it by all of the planes from the other portals
	//
	w = BaseWindingForPlane (&mapplanes[node->planenum]);
	side = 0;	// shut up compiler warning
	for (p = node->portals ; p ; p = p->next[side])
	{
		clipplane = mapplanes[p->planenum];
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
		{
			clipplane.dist = -clipplane.dist;
			VectorNegate (clipplane.normal, clipplane.normal);
			side = 1;
		}
		else
			Error ("CutNodePortals_r: mislinked portal");

		w = ClipWinding (w, &clipplane, true);
		if (!w)
		{
			printf ("WARNING: CutNodePortals_r:new portal was clipped away\n");
			break;
		}
	}

	if (w)
	{
		// if the plane was not clipped on all sides, there was an error
		new_portal = AllocPortal ();
		new_portal->planenum = node->planenum;
		new_portal->winding = w;
		AddPortalToNodes (new_portal, f, b);
	}

	// partition the portals
	for (p = node->portals ; p ; p = next_portal)
	{
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
			side = 1;
		else
			Error ("CutNodePortals_r: mislinked portal");
		next_portal = p->next[side];

		other_node = p->nodes[!side];
		RemovePortalFromNode (p, p->nodes[0]);
		RemovePortalFromNode (p, p->nodes[1]);

		// cut the portal into two portals, one on each side of the cut plane
		DivideWindingEpsilon( p->winding, plane, &frontwinding, &backwinding, ON_EPSILON );

		if (!frontwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, b, other_node);
			else
				AddPortalToNodes (p, other_node, b);
			continue;
		}
		if (!backwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, f, other_node);
			else
				AddPortalToNodes (p, other_node, f);
			continue;
		}

		// the winding is split
		new_portal = AllocPortal ();
		*new_portal = *p;
		new_portal->winding = backwinding;
		FreeWinding (p->winding);
		p->winding = frontwinding;

		if (side == 0)
		{
			AddPortalToNodes (p, f, other_node);
			AddPortalToNodes (new_portal, b, other_node);
		}
		else
		{
			AddPortalToNodes (p, other_node, f);
			AddPortalToNodes (new_portal, other_node, b);
		}
	}

	CutNodePortals_r (f);
	CutNodePortals_r (b);
}
Beispiel #13
0
/*
================
CutNodePortals_r
================
*/
static void
CutNodePortals_r(node_t *node)
{
    plane_t *plane, clipplane;
    node_t *f, *b, *other_node;
    portal_t *p, *new_portal, *next_portal;
    winding_t *w, *frontwinding, *backwinding;
    int side;

#ifdef PARANOID
    CheckLeafPortalConsistancy (node);
#endif

    // separate the portals on node into it's children
    if (node->contents)
	return;			// at a leaf, no more dividing

    plane = &pPlanes[node->planenum];

    f = node->children[0];
    b = node->children[1];

    // create the new portal by taking the full plane winding for the cutting plane
    // and clipping it by all of the planes from the other portals
    new_portal = AllocMem(PORTAL, 1, true);
    new_portal->planenum = node->planenum;

    w = BaseWindingForPlane(&pPlanes[node->planenum]);
    side = 0;			// shut up compiler warning
    for (p = node->portals; p; p = p->next[side]) {
	clipplane = pPlanes[p->planenum];
	if (p->nodes[0] == node)
	    side = 0;
	else if (p->nodes[1] == node) {
	    clipplane.dist = -clipplane.dist;
	    VectorSubtract(vec3_origin, clipplane.normal, clipplane.normal);
	    side = 1;
	} else
	    Message(msgError, errMislinkedPortal);

	w = ClipWinding(w, &clipplane, true);
	if (!w) {
	    Message(msgWarning, warnPortalClippedAway);
	    break;
	}
    }

    if (w) {
	// if the plane was not clipped on all sides, there was an error
	new_portal->winding = w;
	AddPortalToNodes(new_portal, f, b);
    }
    // partition the portals
    for (p = node->portals; p; p = next_portal) {
	if (p->nodes[0] == node)
	    side = 0;
	else if (p->nodes[1] == node)
	    side = 1;
	else
	    Message(msgError, errMislinkedPortal);
	next_portal = p->next[side];

	other_node = p->nodes[!side];
	RemovePortalFromNode(p, p->nodes[0]);
	RemovePortalFromNode(p, p->nodes[1]);

	// cut the portal into two portals, one on each side of the cut plane
	DivideWinding(p->winding, plane, &frontwinding, &backwinding);

	if (!frontwinding) {
	    if (side == 0)
		AddPortalToNodes(p, b, other_node);
	    else
		AddPortalToNodes(p, other_node, b);
	    continue;
	}
	if (!backwinding) {
	    if (side == 0)
		AddPortalToNodes(p, f, other_node);
	    else
		AddPortalToNodes(p, other_node, f);
	    continue;
	}
	// the winding is split
	new_portal = AllocMem(PORTAL, 1, true);
	*new_portal = *p;
	new_portal->winding = backwinding;
	FreeMem(p->winding, WINDING, 1);
	p->winding = frontwinding;

	if (side == 0) {
	    AddPortalToNodes(p, f, other_node);
	    AddPortalToNodes(new_portal, b, other_node);
	} else {
	    AddPortalToNodes(p, other_node, f);
	    AddPortalToNodes(new_portal, other_node, b);
	}
    }

    // Display progress
    iNodesDone++;
    Message(msgPercent, iNodesDone, splitnodes);

    CutNodePortals_r(f);
    CutNodePortals_r(b);
}
Beispiel #14
0
void CreateBrushFaces (void)
{
	int	  i, j, k;
	vec3_t    offset, point;
	vec_t	  r, max, min;
	face_t	  *f;
	winding_t *w;
	plane_t	  plane;
	mface_t	  *mf;
	qboolean  IsRotate;

	offset[0] = offset[1] = offset[2] = 0;
	min = brush_mins[0] = brush_mins[1] = brush_mins[2] = 99999;
	max = brush_maxs[0] = brush_maxs[1] = brush_maxs[2] = -99999;

	// Hipnotic rotation
	IsRotate = !strncmp(ValueForKey(CurrEnt, "classname"), "rotate_", 7);

	if (IsRotate)
		FixRotateOrigin(CurrEnt, offset);

	brush_faces = NULL;

	for (i=0 ; i<numbrushfaces ; i++)
	{
		mf = &faces[i];

		w = BaseWindingForPlane (&mf->plane);

		for (j=0 ; j<numbrushfaces && w ; j++)
		{
			if (j == i)
				continue;
		// flip the plane, because we want to keep the back side
			VectorSubtract (vec3_origin,faces[j].plane.normal, plane.normal);
			plane.dist = -faces[j].plane.dist;

			w = ClipWinding (w, &plane, false);
		}

		if (!w)
			continue;	// overcontrained plane

	// this face is a keeper
		f = AllocFace ();
		ResizeFace (f, w->numpoints);
		if (f->numpoints > MAXEDGES)
			Message (MSGERR, "f->numpoints (%d) > MAXEDGES (%d)", f->numpoints, MAXEDGES);

		for (j=0 ; j<w->numpoints ; j++)
		{
			for (k=0 ; k<3 ; k++)
			{
				point[k] = w->points[j][k] - offset[k];
				r = Q_rint(point[k]);
				if (fabs(point[k] - r) < ZERO_EPSILON)
					f->pts[j][k] = r;
				else
					f->pts[j][k] = point[k];

				if (f->pts[j][k] < brush_mins[k])
					brush_mins[k] = f->pts[j][k];
				if (f->pts[j][k] > brush_maxs[k])
					brush_maxs[k] = f->pts[j][k];

				if (IsRotate)
				{
					if (f->pts[j][k] < min)
						min = f->pts[j][k];
					if (f->pts[j][k] > max)
						max = f->pts[j][k];
				}
			}
		}

		if (!IsRotate)
			plane = mf->plane;
		else
		{
			VectorCopy(mf->plane.normal, plane.normal);
			VectorScale(mf->plane.normal, mf->plane.dist, point);
			VectorSubtract(point, offset, point);
			plane.dist = DotProduct(plane.normal, point);
		}

		FreeWinding (w);
		f->texturenum = hullnum ? 0 : mf->texinfo;
		f->planenum = FindPlane (&plane, &f->planeside);
		f->next = brush_faces;
		brush_faces = f;
		CheckFace (f);
	}

	// Rotatable objects must have a bounding box big enough to
	// account for all its rotations
	if (IsRotate)
	{
		vec_t delta;

		delta = fabs(max);
		if (fabs(min) > delta)
			delta = fabs(min);

		for (k=0; k<3; k++)
		{
			brush_mins[k] = -delta;
			brush_maxs[k] = delta;
		}
	}
}
Beispiel #15
0
RWinding *ClipToSeperators ( RWinding *source, RWinding *pass, RWinding *target, CLIP_SEPERATOR_DIR clipdir )
{
	long	cur_src_point;
	long	next_src_point;
	long	cur_pass_point;
	rvector	v1, v2;
	rplane	plane;

	long	i;
	float	d;
	float	length;
	long	front_count;

	if( ! source || ! pass ) return target;

	//	source의 모서리와 pass의 한점을 선택하는 모든 조합을 만든다.
	for (cur_src_point=0 ; cur_src_point<source->nCount; cur_src_point++)
	{
		// source 로부터 한 모서리를 선택한다.
		next_src_point = (cur_src_point+1)%source->nCount;
		v1 = source->pVertices[next_src_point] - source->pVertices[cur_src_point];

		for (cur_pass_point=0 ; cur_pass_point<pass->nCount; cur_pass_point++)
		{
			// pass 로부터 한 점을 선택한다.
			v2 = pass->pVertices[cur_pass_point] - source->pVertices[cur_src_point];

			// 선택한 모서리와 점으로 평면(plane)을 만든다.
			rvector normal;
			CrossProduct( &normal,  v1 ,v2  );
			length = DotProduct( normal, normal );			
			if (length < ON_EPSILON)
				continue;
			length = (float)sqrt(length);
			plane.a = normal.x/length;
			plane.b = normal.y/length;
			plane.c = normal.z/length;
			plane.d = -D3DXPlaneDotNormal(&plane,&pass->pVertices[cur_pass_point]);

			// plane과 source의위치관계를 조사한다.
			front_count = 0;
			for (i=0 ; i<source->nCount ; i++)
			{
				if (i == cur_src_point || i == next_src_point)
					continue;
				d = D3DXPlaneDotCoord(&plane,&source->pVertices[i]);
				if (d < -ON_EPSILON)
					break;
				if (d > ON_EPSILON)
				{
					front_count++;
					// source는 plane의 양쪽에 걸쳐져 있을 수 없다.
					// 따라서 한점만 앞에있어도 source가 앞에있다고 판단.
					break;
				}
			}
			// source가 plane상에 있는경우는 취급하지 않는다.
			// 이것은 [ 가시성 판단 3 ] 에서 처리한다.
			// [ 가시성 판단 3 ] 을 수행하지 않고 이 함수를 수행하려 한다면
			// 함수가 좀 복잡해진다.
			if (i == source->nCount)
				continue;

			// source가 plane의 뒤쪽에 위치하도록 평면방정식을 조정한다.			
			if ( front_count )
				plane=-plane;

			// plane과 pass의위치관계를 조사한다.
			// pass가 plane의 앞쪽에 완전히 포함되는 경우,
			// plane으로 target을 클리핑한다.
			front_count = 0;
			for (i=0 ; i<pass->nCount; i++)
			{
				if (i==cur_pass_point)
					continue;
				d = D3DXPlaneDotCoord(&plane,&pass->pVertices[i]);
				if (d < -ON_EPSILON)
					break;
				if (d > ON_EPSILON)
					front_count++;
			}
			// 한점이라도 plane의 뒤쪽에 있으면 안된다.
			if (i != pass->nCount)
				continue;
			// pass가 평면에 포함되어서도 안된다.
			if ( ! front_count )
				continue;

			// 입력된 parameter 가
			// source -> pass -> target 순이 아니라
			// pass -> source -> target 순이라면 plane을 뒤집어야 한다.
			if ( clipdir == CLIP_SEPERATOR_BACKWARD )
			{
				plane=-plane;
			}

			// 여기까지 왔다면 plane은 뷰볼륨을 이루는 평면이다.
			// target을 잘라낸다.
			target = ClipWinding (target, plane);
			if (!target)
				return NULL;		// target is not visible
		}
	}

	return target;
}