Ejemplo n.º 1
0
//-----------------------------------------------------------------------------
// Purpose: Check to see if the SSolid with displacement surfaces has valid 
//          base face surfaces.
//-----------------------------------------------------------------------------
bool CSSolid::IsValidWithDisps( void )
{
	if ( !HasDisps() )
		return true;

	for ( int iFace = 0; iFace < m_nFaces; ++iFace )
	{
		// Get the face(s) that have displacements.
		CSSFace *pFace = &m_Faces[iFace];
		if ( pFace->m_hDisp == EDITDISPHANDLE_INVALID )
			continue;

		// Create a face point list.
		Vector *pFacePoints = CreatePointList( *pFace );

		// If the face has changed the number of points - via merges, etc.
		if ( pFace->nEdges != 4 )
			return false;

		// Check the face for validity.
		CCheckFaceInfo faceInfo;
		if ( !CheckFace( pFacePoints, pFace->nEdges, NULL, 0.0f, &faceInfo ) )
			return false;
	}

	return true;
}
Ejemplo n.º 2
0
// check faces for irregularities ->
void CSSolid::CheckFaces()
{
	for(int i = 0; i < m_nFaces; i++)
	{
		CSSFace &face = m_Faces[i];

		// get points for face
		Vector *pts = CreatePointList(face);

		// call checkface function
		CCheckFaceInfo cfi;

		while(CheckFace(pts, face.nEdges, NULL, 0, &cfi) == FALSE)
		{
			CString str;
			str.Format("face %d - %s", i, cfi.szDescription);
			AfxMessageBox(str);
		}

		delete[] pts;
	}
}
Ejemplo n.º 3
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);
	}	
}
Ejemplo n.º 4
0
/*
==================
SplitFace

==================
*/
void SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back)
{
	double	dists[MAXEDGES+1];
	int		sides[MAXEDGES+1];
	int		counts[3];
	double	dot;
	int		i, j;
	face_t	*newf, *new2;
	double	*p1, *p2;
	vec3_t	mid;

	if (in->numpoints < 0)
		Error ("%s: freed face", __thisfunc__);
	counts[0] = counts[1] = counts[2] = 0;

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

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

	*back = newf = NewFaceFromFace (in);
	*front = new2 = NewFaceFromFace (in);

// distribute the points and generate splits

	for (i = 0 ; i < in->numpoints ; i++)
	{
		if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
			Error ("%s: numpoints > MAXEDGES", __thisfunc__);

		p1 = in->pts[i];

		if (sides[i] == SIDE_ON)
		{
			VectorCopy (p1, newf->pts[newf->numpoints]);
			newf->numpoints++;
			VectorCopy (p1, new2->pts[new2->numpoints]);
			new2->numpoints++;
			continue;
		}

		if (sides[i] == SIDE_FRONT)
		{
			VectorCopy (p1, new2->pts[new2->numpoints]);
			new2->numpoints++;
		}
		else
		{
			VectorCopy (p1, newf->pts[newf->numpoints]);
			newf->numpoints++;
		}

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

	// generate a split point
		p2 = in->pts[(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 (split->normal[j] == 1)
				mid[j] = split->dist;
			else if (split->normal[j] == -1)
				mid[j] = -split->dist;
			else
				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
		}

		VectorCopy (mid, newf->pts[newf->numpoints]);
		newf->numpoints++;
		VectorCopy (mid, new2->pts[new2->numpoints]);
		new2->numpoints++;
	}

	if (newf->numpoints > MAXEDGES || new2->numpoints > MAXEDGES)
		Error ("%s: numpoints > MAXEDGES", __thisfunc__);

#if 0
	CheckFace (newf);
	CheckFace (new2);
#endif

// free the original face now that is is represented by the fragments
	FreeFace (in);
}
Ejemplo n.º 5
0
Archivo: brush.c Proyecto: kellyrm/Q1
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;
		}
	}
}
Ejemplo n.º 6
0
Archivo: brush.c Proyecto: kellyrm/Q1
/*
=================
CheckFace

Note: this will not catch 0 area polygons
=================
*/
void CheckFace (face_t *f)
{
	int	i, j;
	vec_t	*p1, *p2;
	vec_t	d, edgedist;
	vec3_t	dir, edgenormal, facenormal;

	if (f->numpoints < 3)
		Message (MSGWARN, "CheckFace: Face with too few (%i) points at %s", f->numpoints, GetCoord (f->pts[0]));

	VectorCopy (planes[f->planenum].normal, facenormal);
	if (f->planeside)
	{
		VectorSubtract (vec3_origin, facenormal, facenormal);
	}

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

		for (j=0 ; j<3 ; j++)
			if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
				Message (MSGERR, "CheckFace: BOGUS_RANGE: %s", GetCoord (p1));

		j = i+1 == f->numpoints ? 0 : i+1;

	// check the point is on the face plane
		d = DotProduct (p1, planes[f->planenum].normal) - planes[f->planenum].dist;
		if (d < -ON_EPSILON || d > ON_EPSILON)
		{
			Message (MSGWARN, "CheckFace: Healing point %s off plane by %.3g", GetCoord (p1), d);

			// Adjust point to plane
			VectorMA (p1, -d, planes[f->planenum].normal, f->pts[i]);
			p1 = f->pts[i];
		}

	// check the edge isn't degenerate
		p2 = f->pts[j];
		VectorSubtract (p2, p1, dir);

		if (VectorLength (dir) < ON_EPSILON)
		{
			Message (MSGWARN, "CheckFace: Healing degenerate edge at %s", GetCoord (p1));
			for (j=i+1; j<f->numpoints; j++)
				VectorCopy(f->pts[j], f->pts[j-1]);
			ResizeFace (f, f->numpoints - 1);
			CheckFace(f);
			break;
		}

		CrossProduct (facenormal, dir, edgenormal);
		VectorNormalize (edgenormal);
		edgedist = DotProduct (p1, edgenormal);
		edgedist += ON_EPSILON;

	// all other points must be on front side
		for (j=0 ; j<f->numpoints ; j++)
		{
			if (j == i)
				continue;
			d = DotProduct (f->pts[j], edgenormal);
			if (d > edgedist)
				Message (MSGERR, "CheckFace: Non-convex at %s", GetCoord (p1));
		}
	}
}