예제 #1
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;

	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
	FreeWinding (in);
	if (b)
		FreeWinding (b);
	return f;
}
예제 #2
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 );
	}
}
예제 #3
0
//===========================================================================
// NOTE: the original face is invalid after splitting
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_SplitFace(tmp_face_t *face, vec3_t normal, float dist,
							tmp_face_t **frontface, tmp_face_t **backface)
{
	winding_t *frontw, *backw;

	//
	*frontface = *backface = NULL;

	ClipWindingEpsilon(face->winding, normal, dist, FACECLIP_EPSILON, &frontw, &backw);

#ifdef DEBUG
	//
	if (frontw)
	{
		if (WindingIsTiny(frontw))
		{
			Log_Write("AAS_SplitFace: tiny back face\r\n");
			FreeWinding(frontw);
			frontw = NULL;
		} //end if
	} //end if
	if (backw)
	{
		if (WindingIsTiny(backw))
		{
			Log_Write("AAS_SplitFace: tiny back face\r\n");
			FreeWinding(backw);
			backw = NULL;
		} //end if
	} //end if
#endif //DEBUG
	//if the winding was split
	if (frontw)
	{
		//check bounds
		(*frontface) = AAS_AllocTmpFace();
		(*frontface)->planenum = face->planenum;
		(*frontface)->winding = frontw;
		(*frontface)->faceflags = face->faceflags;
	} //end if
	if (backw)
	{
		//check bounds
		(*backface) = AAS_AllocTmpFace();
		(*backface)->planenum = face->planenum;
		(*backface)->winding = backw;
		(*backface)->faceflags = face->faceflags;
	} //end if
} //end of the function AAS_SplitFace
예제 #4
0
/*
   =============
   DicePatch

   Chops the patch by a global grid
   =============
 */
void    DicePatch( patch_t *patch ){
	winding_t *w, *o1, *o2;
	vec3_t mins, maxs;
	vec3_t split;
	vec_t dist;
	int i;
	patch_t *newp;

	w = patch->winding;
	WindingBounds( w, mins, maxs );
	for ( i = 0 ; i < 3 ; i++ )
		if ( floor( ( mins[i] + 1 ) / subdiv ) < floor( ( maxs[i] - 1 ) / subdiv ) ) {
			break;
		}
	if ( i == 3 ) {
		// no splitting needed
		return;
	}

	//
	// split the winding
	//
	VectorCopy( vec3_origin, split );
	split[i] = 1;
	dist = subdiv * ( 1 + floor( ( mins[i] + 1 ) / subdiv ) );
	ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );

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

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

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

	FinishSplit( patch, newp );

	DicePatch( patch );
	DicePatch( newp );
}
예제 #5
0
/**
 *	@brief Chops the patch by a global grid
 */
static void SubdividePatch(patch_t* patch)
{
	winding_t* w, *o1, *o2;
	vec3_t mins, maxs;
	vec3_t split;
	vec_t dist;
	int i;
	patch_t* newp;

	w = patch->winding;
	WindingBounds(w, mins, maxs);

	VectorClear(split);

	for (i = 0; i < 3; i++) {
		if (floor((mins[i] + 1) / PATCH_SUBDIVIDE) < floor((maxs[i] - 1) / PATCH_SUBDIVIDE)) {
			split[i] = 1.0;
			break;
		}
	}
	/* no splitting needed */
	if (i == 3)
		return;

	/* split the winding */
	dist = PATCH_SUBDIVIDE * (1 + floor((mins[i] + 1) / PATCH_SUBDIVIDE));
	ClipWindingEpsilon(w, split, dist, ON_EPSILON, &o1, &o2);

	/* create a new patch */
	newp = Mem_AllocType(patch_t);

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

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

	FinishSubdividePatch(patch, newp);

	SubdividePatch(patch);
	SubdividePatch(newp);
}
예제 #6
0
bool DWinding::ChopWinding(DPlane* chopPlane)
{
	DWinding *f, *b;

	ClipWindingEpsilon (chopPlane, (float)ON_EPSILON, &f, &b);

	if (b)
		delete (b);


	if(!f)
	{
		delete this;
		return FALSE;
	}

	delete[] p;
	p = f->p;
	f->p = NULL;
	numpoints = f->numpoints;
	delete f;

	return TRUE;
}
예제 #7
0
파일: portals.c 프로젝트: Diskutant/RTCW-SP
//===========================================================================
// Move or split the portals that bound node so that the node's
// children have portals instead of node.
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void SplitNodePortals(node_t *node)
{
	portal_t    *p, *next_portal, *new_portal;
	node_t *f, *b, *other_node;
	int side = 0; // TTimo: init
	plane_t *plane;
	winding_t *frontwinding, *backwinding;

	plane = &mapplanes[node->planenum];
	f = node->children[0];
	b = node->children[1];

	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("SplitNodePortals: 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
//
		ClipWindingEpsilon(p->winding, plane->normal, plane->dist,
		                   SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);

		if(frontwinding && WindingIsTiny(frontwinding))
		{
			FreeWinding(frontwinding);
			frontwinding = NULL;
			c_tinyportals++;
		} //end if

		if(backwinding && WindingIsTiny(backwinding))
		{
			FreeWinding(backwinding);
			backwinding = NULL;
			c_tinyportals++;
		} //end if

#ifdef DEBUG
		/*  //NOTE: don't use this winding ok check
		        // all the invalid windings only have a degenerate edge
		        if (frontwinding && WindingError(frontwinding))
		        {
		            Log_Print("SplitNodePortals: front %s\n", WindingErrorString());
		            FreeWinding(frontwinding);
		            frontwinding = NULL;
		        } //end if
		        if (backwinding && WindingError(backwinding))
		        {
		            Log_Print("SplitNodePortals: back %s\n", WindingErrorString());
		            FreeWinding(backwinding);
		            backwinding = NULL;
		        } //end if*/
#endif //DEBUG

		if(!frontwinding && !backwinding)      // tiny windings on both sides
		{
			continue;
		}

		if(!frontwinding)
		{
			FreeWinding(backwinding);

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

			continue;
		}

		if(!backwinding)
		{
			FreeWinding(frontwinding);

			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);
		} //end if
		else
		{
			AddPortalToNodes(p, other_node, f);
			AddPortalToNodes(new_portal, other_node, b);
		} //end else
	}

	node->portals = NULL;
} //end of the function SplitNodePortals
예제 #8
0
void BuildFaceTree_r(node_t * node, face_t * list)
{
	face_t         *split;
	face_t         *next;
	int             side;
	plane_t        *plane;
	face_t         *newFace;
	face_t         *childLists[2];
	winding_t      *frontWinding, *backWinding;
	int             i;
	int             splitPlaneNum, compileFlags;
	qboolean        isstruct = qfalse;
	int             splits, front, back;


	/* count faces left */
	i = CountFaceList(list);

#if defined(DEBUG_SPLITS)
	Sys_FPrintf(SYS_VRB, "faces left = %d\n", i);
#endif

	/* select the best split plane */
	SelectSplitPlaneNum(node, list, &splitPlaneNum, &compileFlags);

	/* if we don't have any more faces, this is a leaf */
	if(splitPlaneNum == -1)
	{
		node->planenum = PLANENUM_LEAF;
		node->has_structural_children = qfalse;
		c_faceLeafs++;
		return;
	}

	/* partition the list */
	node->planenum = splitPlaneNum;
	node->compileFlags = compileFlags;
	node->has_structural_children = !(compileFlags & C_DETAIL) && !node->opaque;
	plane = &mapplanes[splitPlaneNum];
	childLists[0] = NULL;
	childLists[1] = NULL;

	splits = front = back = 0;

	for(split = list; split; split = next)
	{
		/* set next */
		next = split->next;

		/* don't split by identical plane */
		if(split->planenum == node->planenum)
		{
			FreeBspFace(split);
			continue;
		}

		if(!(split->compileFlags & C_DETAIL))
			isstruct = 1;

		/* determine which side the face falls on */
		side = WindingOnPlaneSide(split->w, plane->normal, plane->dist);

		/* switch on side */
		if(side == SIDE_CROSS)
		{
			splits++;

			ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding);
			if(frontWinding)
			{
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[0] = newFace;

				front++;
			}
			if(backWinding)
			{
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[1] = newFace;

				back++;
			}
			FreeBspFace(split);
		}
		else if(side == SIDE_FRONT)
		{
			split->next = childLists[0];
			childLists[0] = split;

			front++;
		}
		else if(side == SIDE_BACK)
		{
			split->next = childLists[1];
			childLists[1] = split;

			back++;
		}
	}


	// recursively process children
	for(i = 0; i < 2; i++)
	{
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy(node->mins, node->children[i]->mins);
		VectorCopy(node->maxs, node->children[i]->maxs);

		c_faceNodes++;
	}

	for(i = 0; i < 3; i++)
	{
		if(plane->normal[i] == 1)
		{
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

#if 1
	if(drawBSP && drawTree)
	{
		drawChildLists[0] = childLists[0];
		drawChildLists[1] = childLists[1];
		drawSplitNode = node;
		Draw_Scene(DrawAll);
	}
#endif

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf1\n", node->has_structural_children);
#endif

	for(i = 0; i < 2; i++)
	{
		BuildFaceTree_r(node->children[i], childLists[i]);
		node->has_structural_children |= node->children[i]->has_structural_children;
	}

#if defined(DEBUG_SPLITS)
	if((node->compileFlags & C_DETAIL) && !(node->children[0]->compileFlags & C_DETAIL) &&
	   node->children[0]->planenum != PLANENUM_LEAF)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural\n", node->has_structural_children);
	if((node->compileFlags & C_DETAIL) && isstruct)
		Sys_FPrintf(SYS_ERR, "I am detail, my child is structural, this is a wtf2\n", node->has_structural_children);
#endif
}
예제 #9
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];
}
예제 #10
0
void BuildFaceTree_r( node_t *node, face_t *list ){
	face_t      *split;
	face_t      *next;
	int side;
	plane_t     *plane;
	face_t      *newFace;
	face_t      *childLists[2];
	winding_t   *frontWinding, *backWinding;
	int i;
	int splitPlaneNum, compileFlags;


	/* count faces left */
	i = CountFaceList( list );

	/* select the best split plane */
	SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags );

	/* if we don't have any more faces, this is a node */
	if ( splitPlaneNum == -1 ) {
		node->planenum = PLANENUM_LEAF;
		c_faceLeafs++;
		return;
	}

	/* partition the list */
	node->planenum = splitPlaneNum;
	node->compileFlags = compileFlags;
	plane = &mapplanes[ splitPlaneNum ];
	childLists[0] = NULL;
	childLists[1] = NULL;
	for ( split = list; split; split = next )
	{
		/* set next */
		next = split->next;

		/* don't split by identical plane */
		if ( split->planenum == node->planenum ) {
			FreeBspFace( split );
			continue;
		}

		/* determine which side the face falls on */
		side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );

		/* switch on side */
		if ( side == SIDE_CROSS ) {
			ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
								&frontWinding, &backWinding );
			if ( frontWinding ) {
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[0] = newFace;
			}
			if ( backWinding ) {
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->compileFlags = split->compileFlags;
				childLists[1] = newFace;
			}
			FreeBspFace( split );
		}
		else if ( side == SIDE_FRONT ) {
			split->next = childLists[0];
			childLists[0] = split;
		}
		else if ( side == SIDE_BACK ) {
			split->next = childLists[1];
			childLists[1] = split;
		}
	}


	// recursively process children
	for ( i = 0 ; i < 2 ; i++ ) {
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy( node->mins, node->children[i]->mins );
		VectorCopy( node->maxs, node->children[i]->maxs );
	}

	for ( i = 0 ; i < 3 ; i++ ) {
		if ( plane->normal[i] == 1 ) {
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

	for ( i = 0 ; i < 2 ; i++ ) {
		BuildFaceTree_r( node->children[i], childLists[i] );
	}
}
예제 #11
0
/*
==============
SplitNodePortals

Move or split the portals that bound node so that the node's
children have portals instead of node.
==============
*/
void SplitNodePortals (node_t *node)
{
	portal_t	*p, *next_portal, *new_portal;
	node_t		*f, *b, *other_node;
	int			side = 0;
	plane_t		*plane;
	winding_t	*frontwinding, *backwinding;

	plane = &mapplanes[node->planenum];
	f = node->children[0];
	b = node->children[1];

	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
//
		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);

		if (frontwinding && WindingIsTiny(frontwinding))
		{
			FreeWinding (frontwinding);
			frontwinding = NULL;
			c_tinyportals++;
		}

		if (backwinding && WindingIsTiny(backwinding))
		{
			FreeWinding (backwinding);
			backwinding = NULL;
			c_tinyportals++;
		}

		if (!frontwinding && !backwinding)
		{	// tiny windings on both sides
			continue;
		}

		if (!frontwinding)
		{
			FreeWinding (backwinding);
			if (side == 0)
				AddPortalToNodes (p, b, other_node);
			else
				AddPortalToNodes (p, other_node, b);
			continue;
		}
		if (!backwinding)
		{
			FreeWinding (frontwinding);
			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);
		}
	}

	node->portals = NULL;
}
예제 #12
0
파일: fog.c 프로젝트: DerSaidin/OpenWolf
qboolean ChopFaceSurfaceByBrush(entity_t * e, mapDrawSurface_t * ds, brush_t * b)
{
	int             i, j;
	side_t         *s;
	plane_t        *plane;
	winding_t      *w;
	winding_t      *front, *back;
	winding_t      *outside[MAX_BRUSH_SIDES];
	int             numOutside;
	mapDrawSurface_t *newds;


	/* dummy check */
	if(ds->sideRef == NULL || ds->sideRef->side == NULL)
		return qfalse;

	/* initial setup */
	w = WindingFromDrawSurf(ds);
	numOutside = 0;

	/* chop by each brush side */
	for(i = 0; i < b->numsides; i++)
	{
		/* get brush side and plane */
		s = &b->sides[i];
		plane = &mapplanes[s->planenum];

		/* handle coplanar outfacing (don't fog) */
		if(ds->sideRef->side->planenum == s->planenum)
			return qfalse;

		/* handle coplanar infacing (keep inside) */
		if((ds->sideRef->side->planenum ^ 1) == s->planenum)
			continue;

		/* general case */
		ClipWindingEpsilon(w, plane->normal, plane->dist, ON_EPSILON, &front, &back);
		FreeWinding(w);

		if(back == NULL)
		{
			/* nothing actually contained inside */
			for(j = 0; j < numOutside; j++)
				FreeWinding(outside[j]);
			return qfalse;
		}

		if(front != NULL)
		{
			if(numOutside == MAX_BRUSH_SIDES)
				Error("MAX_BRUSH_SIDES");
			outside[numOutside] = front;
			numOutside++;
		}

		w = back;
	}

	/* fixme: celshaded surface fragment errata */

	/* all of outside fragments become seperate drawsurfs */
	numFogFragments += numOutside;
	s = ds->sideRef->side;
	for(i = 0; i < numOutside; i++)
	{
		newds = DrawSurfaceForSide(e, ds->mapBrush, s, outside[i]);
		newds->fogNum = ds->fogNum;
		FreeWinding(outside[i]);
	}

	/* ydnar: the old code neglected to snap to 0.125 for the fragment
	   inside the fog brush, leading to sparklies. this new code does
	   the right thing and uses the original surface's brush side */

	/* build a drawsurf for it */
	newds = DrawSurfaceForSide(e, ds->mapBrush, s, w);
	if(newds == NULL)
		return qfalse;

	/* copy new to original */
	ClearSurface(ds);
	memcpy(ds, newds, sizeof(mapDrawSurface_t));

	/* didn't really add a new drawsurface... :) */
	numMapDrawSurfs--;

	/* return ok */
	return qtrue;
}
예제 #13
0
파일: facebsp.c 프로젝트: otty/cake3
/*
================
BuildFaceTree_r
================
*/
void BuildFaceTree_r(node_t * node, bspFace_t * list)
{
	bspFace_t      *split;
	bspFace_t      *next;
	int             side;
	plane_t        *plane;
	bspFace_t      *newFace;
	bspFace_t      *childLists[2];
	winding_t      *frontWinding, *backWinding;
	int             i;
	int             splitPlaneNum;
	int             hintSplit;

	i = CountFaceList(list);

	SelectSplitPlaneNum(node, list, &splitPlaneNum, &hintSplit);

	// if we don't have any more faces, this is a node
	if(splitPlaneNum == -1)
	{
		node->planenum = PLANENUM_LEAF;
		c_faceLeafs++;
		return;
	}

	// partition the list
	node->planenum = splitPlaneNum;
	node->hint = hintSplit;
	plane = &mapPlanes[splitPlaneNum];
	childLists[0] = NULL;
	childLists[1] = NULL;
	for(split = list; split; split = next)
	{
		next = split->next;

		if(split->planenum == node->planenum)
		{
			FreeBspFace(split);
			continue;
		}

		side = WindingOnPlaneSide(split->w, plane->normal, plane->dist);

		if(side == SIDE_CROSS)
		{
			ClipWindingEpsilon(split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, &frontWinding, &backWinding);
			if(frontWinding)
			{
				newFace = AllocBspFace();
				newFace->w = frontWinding;
				newFace->next = childLists[0];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->hint = split->hint;
				childLists[0] = newFace;
			}
			if(backWinding)
			{
				newFace = AllocBspFace();
				newFace->w = backWinding;
				newFace->next = childLists[1];
				newFace->planenum = split->planenum;
				newFace->priority = split->priority;
				newFace->hint = split->hint;
				childLists[1] = newFace;
			}
			FreeBspFace(split);
		}
		else if(side == SIDE_FRONT)
		{
			split->next = childLists[0];
			childLists[0] = split;
		}
		else if(side == SIDE_BACK)
		{
			split->next = childLists[1];
			childLists[1] = split;
		}
	}


	// recursively process children
	for(i = 0; i < 2; i++)
	{
		node->children[i] = AllocNode();
		node->children[i]->parent = node;
		VectorCopy(node->mins, node->children[i]->mins);
		VectorCopy(node->maxs, node->children[i]->maxs);
	}

	for(i = 0; i < 3; i++)
	{
		if(plane->normal[i] == 1)
		{
			node->children[0]->mins[i] = plane->dist;
			node->children[1]->maxs[i] = plane->dist;
			break;
		}
	}

	for(i = 0; i < 2; i++)
	{
		BuildFaceTree_r(node->children[i], childLists[i]);
	}
}
예제 #14
0
/*
   =============
   SubdividePatch

   Chops the patch only if its local bounds exceed the max size
   =============
 */
void    SubdividePatch( patch_t *patch ){
	winding_t *w, *o1, *o2;
	vec3_t mins, maxs, total;
	vec3_t split;
	vec_t dist;
	int i, j;
	vec_t v;
	patch_t *newp;

	w = patch->winding;
	mins[0] = mins[1] = mins[2] = 99999;
	maxs[0] = maxs[1] = maxs[2] = -99999;
	for ( i = 0 ; i < w->numpoints ; i++ )
	{
		for ( j = 0 ; j < 3 ; j++ )
		{
			v = w->p[i][j];
			if ( v < mins[j] ) {
				mins[j] = v;
			}
			if ( v > maxs[j] ) {
				maxs[j] = v;
			}
		}
	}
	VectorSubtract( maxs, mins, total );
	for ( i = 0 ; i < 3 ; i++ )
		if ( total[i] > ( subdiv + 1 ) ) {
			break;
		}
	if ( i == 3 ) {
		// no splitting needed
		return;
	}

	//
	// split the winding
	//
	VectorCopy( vec3_origin, split );
	split[i] = 1;
	dist = ( mins[i] + maxs[i] ) * 0.5;
	ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );

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

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

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

	FinishSplit( patch, newp );

	SubdividePatch( patch );
	SubdividePatch( newp );
}
예제 #15
0
/*
============
ExpandBrush
=============
*/
void ExpandBrush (int hullnum)
{
	int			i, x, s;
	vec3_t		corner;
	winding_t	*w;
	plane_t		plane;

	int				j, k, numwindings;
	vec_t			r;
	winding_t		**windings;
	plane_t			clipplane, faceplane;
	mface_t			*mf;
	vec3_t			point;
	vec3_t		mins, maxs;

	if (!numbrushfaces)
		return;

	num_hull_points = 0;
	num_hull_edges = 0;

	ClearBounds( mins, maxs );

	// generate windings and bounds data
	numwindings = 0;
	windings = calloc(numbrushfaces, sizeof(*windings));
	for (i = 0;i < numbrushfaces;i++)
	{
		mf = &faces[i];
		windings[i] = NULL;

		faceplane = mf->plane;
		w = BaseWindingForPlane (&faceplane);

		for (j = 0;j < numbrushfaces && w;j++)
		{
			clipplane = faces[j].plane;
			if( j == i )
				continue;

			// flip the plane, because we want to keep the back side
			VectorNegate(clipplane.normal, clipplane.normal);
			clipplane.dist *= -1;

			w = ClipWindingEpsilon (w, &clipplane, ON_EPSILON, true);
		}

		if (!w)
			continue;	// overcontrained plane

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

				// check for incomplete brushes
				if( w->points[j][k] >= BOGUS_RANGE || w->points[j][k] <= -BOGUS_RANGE )
					return;
			}

			AddPointToBounds( w->points[j], mins, maxs );
		}

		windings[i] = w;
	}

	// add all of the corner offsets
	for (i = 0;i < numwindings;i++)
	{
		w = windings[i];
		for (j = 0;j < w->numpoints;j++)
			AddHullPoint(w->points[j], hullnum);
	}

	// expand the face planes
	for (i = 0;i < numbrushfaces;i++)
	{
		mf = &faces[i];
		for (x=0 ; x<3 ; x++)
		{
			if (mf->plane.normal[x] > 0)
				corner[x] = -hullinfo.hullsizes[hullnum][0][x];
			else if (mf->plane.normal[x] < 0)
				corner[x] = -hullinfo.hullsizes[hullnum][1][x];
		}
		mf->plane.dist += DotProduct (corner, mf->plane.normal);
	}

	// add any axis planes not contained in the brush to bevel off corners
	for (x=0 ; x<3 ; x++)
		for (s=-1 ; s<=1 ; s+=2)
		{
			// add the plane
			VectorClear (plane.normal);
			plane.normal[x] = s;
			if (s == -1)
				plane.dist = -mins[x] + hullinfo.hullsizes[hullnum][1][x];
			else
				plane.dist = maxs[x] + -hullinfo.hullsizes[hullnum][0][x];
			AddBrushPlane (&plane);
		}

	// add all of the edge bevels
	for (i = 0;i < numwindings;i++)
	{
		w = windings[i];
		for (j = 0;j < w->numpoints;j++)
			AddHullEdge(w->points[j], w->points[(j+1)%w->numpoints], hullnum);
	}

	// free the windings as we no longer need them
	for (i = 0;i < numwindings;i++)
		if (windings[i])
			FreeWinding(windings[i]);
	free(windings);
}
예제 #16
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];
}
예제 #17
0
/*
=================
CreateBrushFaces
=================
*/
void CreateBrushFaces (void)
{
	int				i,j, k;
	vec_t			r;
	face_t			*f, *next;
	winding_t		*w;
	plane_t			clipplane, faceplane;
	mface_t			*mf;
	vec3_t			offset, point;

	offset[0] = offset[1] = offset[2] = 0;
	ClearBounds( brush_mins, brush_maxs );

	brush_faces = NULL;

	if (!strncmp(ValueForKey(CurrentEntity, "classname"), "rotate_", 7))
	{
		entity_t	*FoundEntity;
		char 		*searchstring;
		char		text[20];

		searchstring = ValueForKey (CurrentEntity, "target");
		FoundEntity = FindTargetEntity(searchstring);
		if (FoundEntity)
			GetVectorForKey(FoundEntity, "origin", offset);

		sprintf(text, "%g %g %g", offset[0], offset[1], offset[2]);
		SetKeyValue(CurrentEntity, "origin", text);
	}

	GetVectorForKey(CurrentEntity, "origin", offset);
	//printf("%i brushfaces at offset %f %f %f\n", numbrushfaces, offset[0], offset[1], offset[2]);

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

		//printf("plane %f %f %f %f\n", mf->plane.normal[0], mf->plane.normal[1], mf->plane.normal[2], mf->plane.dist);
		faceplane = mf->plane;
		w = BaseWindingForPlane (&faceplane);

		//VectorNegate( faceplane.normal, point );
		for (j = 0;j < numbrushfaces && w;j++)
		{
			clipplane = faces[j].plane;
			if( j == i/* || VectorCompare( clipplane.normal, point )*/ )
				continue;

			// flip the plane, because we want to keep the back side
			VectorNegate(clipplane.normal, clipplane.normal);
			clipplane.dist *= -1;

			w = ClipWindingEpsilon (w, &clipplane, ON_EPSILON, true);
		}

		if (!w)
		{
			//printf("----- skipped plane -----\n");
			continue;	// overcontrained plane
		}

		// this face is a keeper
		f = AllocFace ();
		f->winding = w;

		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)
					w->points[j][k] = r;
				else
					w->points[j][k] = point[k];

				// check for incomplete brushes
				if( w->points[j][k] >= BOGUS_RANGE || w->points[j][k] <= -BOGUS_RANGE )
					break;
			}

			// remove this brush
			if (k < 3)
			{
				FreeFace (f);
				for (f = brush_faces; f; f = next)
				{
					next = f->next;
					FreeFace (f);
				}
				brush_faces = NULL;
				//printf("----- skipped brush -----\n");
				return;
			}

			AddPointToBounds( w->points[j], brush_mins, brush_maxs );
		}

		CheckWinding( w );

		faceplane.dist -= DotProduct(faceplane.normal, offset);
		f->texturenum = mf->texinfo;
		f->planenum = FindPlane (&faceplane, &f->planeside);
		f->next = brush_faces;
		brush_faces = f;
	}

	// Rotatable objects have to have a bounding box big enough
	// to account for all its rotations.
	if (DotProduct(offset, offset))
	{
		vec_t delta;

		delta = RadiusFromBounds( brush_mins, brush_maxs );

		for (k = 0;k < 3;k++)
		{
			brush_mins[k] = -delta;
			brush_maxs[k] = delta;
		}
	}

	//printf("%i : %f %f %f : %f %f %f\n", numbrushfaces, brush_mins[0], brush_mins[1], brush_mins[2], brush_maxs[0], brush_maxs[1], brush_maxs[2]);
}
예제 #18
0
파일: fog.c 프로젝트: otty/cake3
/*
====================
ChopFaceByBrush

There may be a fragment contained in the brush
====================
*/
qboolean ChopFaceByBrush(drawSurface_t * ds, bspBrush_t * b)
{
	int             i, j;
	side_t         *s;
	plane_t        *plane;
	winding_t      *w;
	winding_t      *front, *back;
	winding_t      *outside[MAX_BRUSH_SIDES];
	int             numOutside;
	drawSurface_t  *newds;
	drawVert_t     *dv;
	shaderInfo_t   *si;
	float           mins[2];

	// brush primitive :
	// axis base
	vec3_t          texX, texY;
	vec_t           x, y;

	w = WindingFromDrawSurf(ds);
	numOutside = 0;

	for(i = 0; i < b->numsides; i++)
	{
		s = &b->sides[i];
		if(s->backSide)
		{
			continue;
		}
		plane = &mapPlanes[s->planenum];

		// handle coplanar outfacing (don't fog)
		if(ds->side->planenum == s->planenum)
		{
			return qfalse;
		}

		// handle coplanar infacing (keep inside)
		if((ds->side->planenum ^ 1) == s->planenum)
		{
			continue;
		}

		// general case
		ClipWindingEpsilon(w, plane->normal, plane->dist, ON_EPSILON, &front, &back);
		FreeWinding(w);
		if(!back)
		{
			// nothing actually contained inside
			for(j = 0; j < numOutside; j++)
			{
				FreeWinding(outside[j]);
			}
			return qfalse;
		}
		if(front)
		{
			if(numOutside == MAX_BRUSH_SIDES)
			{
				Error("MAX_BRUSH_SIDES");
			}
			outside[numOutside] = front;
			numOutside++;
		}
		w = back;
	}

	// all of outside fragments become seperate drawsurfs
	// linked to the same side
	c_fogFragment += numOutside;
	s = ds->side;

	for(i = 0; i < numOutside; i++)
	{
		newds = DrawSurfaceForSide(ds->mapBrush, s, outside[i]);
		FreeWinding(outside[i]);
	}


	// replace ds->verts with the verts for w
	ds->numVerts = w->numpoints;
	free(ds->verts);

	ds->verts = malloc(ds->numVerts * sizeof(*ds->verts));
	memset(ds->verts, 0, ds->numVerts * sizeof(*ds->verts));

	si = s->shaderInfo;

	mins[0] = 9999;
	mins[1] = 9999;

	// compute s/t coordinates from brush primitive texture matrix
	// compute axis base
	ComputeAxisBase(mapPlanes[s->planenum].normal, texX, texY);

	for(j = 0; j < w->numpoints; j++)
	{
		dv = ds->verts + j;
		VectorCopy(w->p[j], dv->xyz);

		if(g_bBrushPrimit == BPRIMIT_OLDBRUSHES)
		{
			// calculate texture s/t
			dv->st[0] = s->vecs[0][3] + DotProduct(s->vecs[0], dv->xyz);
			dv->st[1] = s->vecs[1][3] + DotProduct(s->vecs[1], dv->xyz);
			dv->st[0] /= si->width;
			dv->st[1] /= si->height;
		}
		else
		{
			// calculate texture s/t from brush primitive texture matrix
			x = DotProduct(dv->xyz, texX);
			y = DotProduct(dv->xyz, texY);
			dv->st[0] = s->texMat[0][0] * x + s->texMat[0][1] * y + s->texMat[0][2];
			dv->st[1] = s->texMat[1][0] * x + s->texMat[1][1] * y + s->texMat[1][2];
		}

		if(dv->st[0] < mins[0])
		{
			mins[0] = dv->st[0];
		}
		if(dv->st[1] < mins[1])
		{
			mins[1] = dv->st[1];
		}

		// copy normal
		VectorCopy(mapPlanes[s->planenum].normal, dv->normal);
	}

	// adjust the texture coordinates to be as close to 0 as possible
	if(!si->globalTexture)
	{
		mins[0] = floor(mins[0]);
		mins[1] = floor(mins[1]);
		for(i = 0; i < w->numpoints; i++)
		{
			dv = ds->verts + i;
			dv->st[0] -= mins[0];
			dv->st[1] -= mins[1];
		}
	}

	return qtrue;
}
예제 #19
0
static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w )
{
	int		i, j;
	float		d, d2, alpha;
	winding_t		*front, *back;
	mapDrawSurface_t	*ds2;
	bspDrawVert_t	*dv;
	vec4_t		plane;
	
	/* dummy check */
	if( w->numpoints < 3 )
	{
		FreeWinding( w );
		return;
	}
	
	/* offset by entity origin */
	for( i = 0; i < w->numpoints; i++ )
		VectorAdd( w->p[ i ], entityOrigin, w->p[ i ] );
	
	/* make a plane from the winding */
	if( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) )
	{
		FreeWinding( w );
		return;
	}
	
	/* backface check */
	d = DotProduct( dp->planes[ 0 ], plane );
	if( d < -0.0001f )
	{
		FreeWinding( w );
		return;
	}
	
	/* walk list of planes */
	for( i = 0; i < dp->numPlanes; i++ )
	{
		/* chop winding by the plane */
		ClipWindingEpsilon( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back );
		FreeWinding( w );
		
		/* lose the front fragment */
		if( front != NULL )
			FreeWinding( front );
		
		/* if nothing left in back, then bail */
		if( back == NULL )
			return;
		
		/* reset winding */
		w = back;
	}
	
	/* nothing left? */
	if( w == NULL || w->numpoints < 3 )
		return;
	
	/* add to counts */
	numDecalSurfaces++;
	
	/* make a new surface */
	ds2 = AllocDrawSurface( SURFACE_DECAL );
	
	/* set it up */
	ds2->entityNum = ds->entityNum;
	ds2->castShadows = ds->castShadows;
	ds2->recvShadows = ds->recvShadows;
	ds2->shaderInfo = dp->si;
	ds2->fogNum = ds->fogNum;	/* why was this -1? */
	ds2->lightmapScale = ds->lightmapScale;
	ds2->numVerts = w->numpoints;
	ds2->verts = Malloc( ds2->numVerts * sizeof( *ds2->verts ) );
	Mem_Set( ds2->verts, 0, ds2->numVerts * sizeof( *ds2->verts ) );
	
	/* set vertexes */
	for( i = 0; i < ds2->numVerts; i++ )
	{
		/* get vertex */
		dv = &ds2->verts[ i ];
		
		/* set alpha */
		d = DotProduct( w->p[ i ], dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
		d2 = DotProduct( w->p[ i ], dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
		alpha = 255.0f * d2 / (d + d2);
		if( alpha > 255 )
			alpha = 255;
		else if( alpha < 0 )
			alpha = 0;
		
		/* set misc */
		VectorSubtract( w->p[ i ], entityOrigin, dv->xyz );
		VectorCopy( plane, dv->normal );
		dv->st[ 0 ] = DotProduct( dv->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
		dv->st[ 1 ] = DotProduct( dv->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
		
		/* set color */
		for( j = 0; j < MAX_LIGHTMAPS; j++ )
		{
			dv->color[ j ][ 0 ] = 255;
			dv->color[ j ][ 1 ] = 255;
			dv->color[ j ][ 2 ] = 255;
			dv->color[ j ][ 3 ] = alpha;
		}
	}
}
예제 #20
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
예제 #21
0
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back ){
	brush_t     *b[2];
	int i, j;
	winding_t   *w, *cw[2], *midwinding;
	plane_t     *plane, *plane2;
	side_t      *s, *cs;
	float d, d_front, d_back;


	*front = NULL;
	*back = NULL;
	plane = &mapplanes[planenum];

	// check all points
	d_front = d_back = 0;
	for ( i = 0 ; i < brush->numsides ; i++ )
	{
		w = brush->sides[i].winding;
		if ( !w ) {
			continue;
		}
		for ( j = 0 ; j < w->numpoints ; j++ )
		{
			d = DotProduct( w->p[j], plane->normal ) - plane->dist;
			if ( d > 0 && d > d_front ) {
				d_front = d;
			}
			if ( d < 0 && d < d_back ) {
				d_back = d;
			}
		}
	}

	if ( d_front < 0.1 ) { // PLANESIDE_EPSILON)
		// only on back
		*back = CopyBrush( brush );
		return;
	}

	if ( d_back > -0.1 ) { // PLANESIDE_EPSILON)
		// only on front
		*front = CopyBrush( brush );
		return;
	}

	// create a new winding from the split plane
	w = BaseWindingForPlane( plane->normal, plane->dist );
	for ( i = 0 ; i < brush->numsides && w ; i++ )
	{
		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace( &w, plane2->normal, plane2->dist, 0 ); // PLANESIDE_EPSILON);
	}

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

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

	if ( WindingIsHuge( w ) ) {
		Sys_FPrintf( SYS_VRB,"WARNING: huge winding\n" );
	}

	midwinding = w;

	// split it for real

	for ( i = 0 ; i < 2 ; i++ )
	{
		b[i] = AllocBrush( brush->numsides + 1 );
		memcpy( b[i], brush, sizeof( brush_t ) - sizeof( brush->sides ) );
		b[i]->numsides = 0;
		b[i]->next = NULL;
		b[i]->original = brush->original;
	}

	// split all the current windings

	for ( i = 0 ; i < brush->numsides ; i++ )
	{
		s = &brush->sides[i];
		w = s->winding;
		if ( !w ) {
			continue;
		}
		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]->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];
}
예제 #22
0
/**
 * @brief Generates two new brushes, leaving the original unchanged
 */
void SplitBrush (const bspbrush_t* brush, uint16_t planenum, bspbrush_t** front, bspbrush_t** back)
{
	bspbrush_t* b[2];
	int i, j;
	winding_t* w, *cw[2], *midwinding;
	plane_t* plane;
	float d_front, d_back;

	*front = *back = nullptr;
	plane = &mapplanes[planenum];

	/* check all points */
	d_front = d_back = 0;
	for (i = 0; i < brush->numsides; i++) {
		w = brush->sides[i].winding;
		if (!w)
			continue;
		for (j = 0; j < w->numpoints; j++) {
			const float d = DotProduct(w->p[j], plane->normal) - plane->dist;
			if (d > 0 && d > d_front)
				d_front = d;
			else if (d < 0 && d < d_back)
				d_back = d;
		}
	}
	if (d_front < 0.1) { /* PLANESIDE_EPSILON) */
		/* only on back */
		*back = CopyBrush(brush);
		return;
	}
	if (d_back > -0.1) { /* PLANESIDE_EPSILON) */
		/* only on front */
		*front = CopyBrush(brush);
		return;
	}

	/* create a new winding from the split plane */
	w = BaseWindingForPlane(plane->normal, plane->dist);
	for (i = 0; i < brush->numsides && w; i++) {
		plane_t* plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
		ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); /* PLANESIDE_EPSILON); */
	}

	/* the brush isn't really split */
	if (!w || WindingIsTiny(w)) {
		const int side = BrushMostlyOnSide(brush, plane);
		if (side == PSIDE_FRONT)
			*front = CopyBrush(brush);
		else if (side == PSIDE_BACK)
			*back = CopyBrush(brush);
		return;
	}

	if (WindingIsHuge(w)) {
		/** @todo Print brush and entnum either of the brush that was splitted
		 * or the plane that was used as splitplane */
		Com_Printf("WARNING: Large winding\n");
	}

	midwinding = w;

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

	/* split all the current windings */
	for (i = 0; i < brush->numsides; i++) {
		const side_t* s = &brush->sides[i];
		w = s->winding;
		if (!w)
			continue;
		ClipWindingEpsilon(w, plane->normal, plane->dist,
			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
		for (j = 0; j < 2; j++) {
			side_t* cs;

			if (!cw[j])
				continue;

			cs = &b[j]->sides[b[j]->numsides];
			b[j]->numsides++;
			*cs = *s;

			cs->winding = cw[j];
			cs->tested = false;
		}
	}

	/* see if we have valid polygons on both sides */
	for (i = 0; i < 2; i++) {
		BoundBrush(b[i]);
		for (j = 0; j < 3; j++) {
			if (b[i]->mins[j] < -MAX_WORLD_WIDTH || b[i]->maxs[j] > MAX_WORLD_WIDTH) {
				/** @todo Print brush and entnum either of the brush that was split
				 * or the plane that was used as splitplane */
				Verb_Printf(VERB_EXTRA, "bogus brush after clip\n");
				break;
			}
		}

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

	if (!(b[0] && b[1])) {
		/** @todo Print brush and entnum either of the brush that was splitted
		 * or the plane that was used as splitplane */
		if (!b[0] && !b[1])
			Verb_Printf(VERB_EXTRA, "split removed brush\n");
		else
			Verb_Printf(VERB_EXTRA, "split not on both sides\n");
		if (b[0]) {
			FreeBrush(b[0]);
			*front = CopyBrush(brush);
		}
		if (b[1]) {
			FreeBrush(b[1]);
			*back = CopyBrush(brush);
		}
		return;
	}

	/* add the midwinding to both sides */
	for (i = 0; i < 2; i++) {
		side_t* cs = &b[i]->sides[b[i]->numsides];
		b[i]->numsides++;

		cs->planenum = planenum ^ i ^ 1;
		cs->texinfo = TEXINFO_NODE;
		cs->visible = false;
		cs->tested = false;
		if (i == 0)
			cs->winding = CopyWinding(midwinding);
		else
			cs->winding = midwinding;
	}

	for (i = 0; i < 2; i++) {
		const vec_t v1 = BrushVolume(b[i]);
		if (v1 < 1.0) {
			FreeBrush(b[i]);
			b[i] = nullptr;
			/** @todo Print brush and entnum either of the brush that was splitted
			 * or the plane that was used as splitplane */
			Verb_Printf(VERB_EXTRA, "tiny volume after clip\n");
		}
	}

	*front = b[0];
	*back = b[1];
}
예제 #23
0
/*
==================
ClipWinding
==================
*/
winding_t *ClipWinding( winding_t *in, plane_t *split, qboolean keepon ) {
	return ClipWindingEpsilon( in, split, WINDING_EPSILON, keepon );
}