Beispiel #1
0
/*
==================
CM_ValidateFacet

If the facet isn't bounded by its borders, we screwed up.
==================
*/
static qboolean CM_ValidateFacet(facet_t *facet)
{
	float     plane[4];
	int       j;
	winding_t *w;
	vec3_t    bounds[2];

	if (facet->surfacePlane == -1)
	{
		return qfalse;
	}

	Vector4Copy(planes[facet->surfacePlane].plane, plane);
	w = BaseWindingForPlane(plane, plane[3]);
	for (j = 0 ; j < facet->numBorders && w ; j++)
	{
		if (facet->borderPlanes[j] == -1)
		{
			FreeWinding(w);
			return qfalse;
		}
		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 qfalse;      // winding was completely chopped away
	}

	// see if the facet is unreasonably large
	WindingBounds(w, bounds[0], bounds[1]);
	FreeWinding(w);

	for (j = 0 ; j < 3 ; j++)
	{
		if (bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS)
		{
			return qfalse;      // we must be missing a plane
		}
		if (bounds[0][j] >= MAX_MAP_BOUNDS)
		{
			return qfalse;
		}
		if (bounds[1][j] <= -MAX_MAP_BOUNDS)
		{
			return qfalse;
		}
	}
	return qtrue;       // winding is fine
}
Beispiel #2
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 );
}
Beispiel #3
0
/*
==================
CM_ValidateFacet

If the facet isn't bounded by its borders, we screwed up.
==================
*/
static qboolean CM_ValidateFacet( facet_t *facet ) {
	planeDef_t	plane;
	int			j;
	winding_t	*w;
	bvec3_t		bounds[2];

	if ( facet->surfacePlane == -1 ) {
		return qfalse;
	}

	plane=planes[ facet->surfacePlane ].pd;
	w = BaseWindingForPlane( plane.normal,  plane.dist );
	for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
		if ( facet->borderPlanes[j] == -1 ) {
			return qfalse;
		}
		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 qfalse;		// winding was completely chopped away
	}

	// see if the facet is unreasonably large
	WindingBounds( w, bounds[0], bounds[1] );
	FreeWinding( w );
	
	for ( j = 0 ; j < 3 ; j++ ) {
		if ( bounds[1][j] - bounds[0][j] > BFIXED(MAX_MAP_BOUNDS,0) ) {
			return qfalse;		// we must be missing a plane
		}
		if ( bounds[0][j] >= BFIXED(MAX_MAP_BOUNDS,0) ) {
			return qfalse;
		}
		if ( bounds[1][j] <= -BFIXED(MAX_MAP_BOUNDS,0) ) {
			return qfalse;
		}
	}
	return qtrue;		// winding is fine
}
Beispiel #4
0
/*
==================
CopyFacesToOutside

Make a copy of all the faces of the brush, so they
can be chewed up by other brushes.

All of the faces start on the outside list.
As other brushes take bites out of the faces, the
fragments are moved to the inside list, so they
can be freed when they are determined to be
completely enclosed in solid.
==================
*/
bface_t *CopyFacesToOutside (brushhull_t *bh)
{
	bface_t		*f, *newf;
	bface_t		*outside;

	outside = NULL;
	
	for (f=bh->faces ; f ; f=f->next)
	{
		brushfaces++;

		newf = CopyFace (f);
		WindingBounds (newf->w, newf->mins, newf->maxs);
		newf->next = outside;
		outside = newf;
	}

	return outside;
}
Beispiel #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);
}
Beispiel #6
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

}
Beispiel #7
0
/*
==================
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

}
Beispiel #8
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 #9
0
void MakePatchForFace (int fn, winding_t *w)
{
	dface_t *f = dfaces + fn;

	// No patches at all for the sky!
	if ( !IsSky(f) )
	{
		float	area;
		patch_t		*patch;
		vec3_t light;
		vec3_t		centroid = {0,0,0};
		int			i, j;
		texinfo_t	*tx = &texinfo[f->texinfo];

		area = WindingArea (w);
		totalarea += area;

		patch = &patches[num_patches];
		if (num_patches == MAX_PATCHES)
			Error ("num_patches == MAX_PATCHES");
		patch->next = face_patches[fn];
		face_patches[fn] = patch;

		if ( texscale )
			{
			// Compute the texture "scale" in s,t
			for( i=0; i<2; i++ )
				{
				patch->scale[i] = 0.0;
				for( j=0; j<3; j++ )
					patch->scale[i] += tx->vecs[i][j] * tx->vecs[i][j];
				patch->scale[i] = sqrt( patch->scale[i] );
				}
			}
		else
			patch->scale[0] = patch->scale[1] = 1.0;

		patch->area = area;
		patch->chop = maxchop / (int)((patch->scale[0]+patch->scale[1])/2);
		patch->sky = FALSE;

		patch->winding = w;

		if (f->side)
			patch->plane = &backplanes[f->planenum];
		else
			patch->plane = &dplanes[f->planenum];

		for (j=0 ; j<f->numedges ; j++)
		{
			int edge = dsurfedges[ f->firstedge + j ];
			int edge2 = dsurfedges[ j==f->numedges-1 ? f->firstedge : f->firstedge + j + 1 ];

			if (edge > 0)
			{
				VectorAdd( dvertexes[dedges[edge].v[0]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[edge].v[1]].point, centroid, centroid );
			}
			else
			{
				VectorAdd( dvertexes[dedges[-edge].v[1]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[-edge].v[0]].point, centroid, centroid );
			}
		}
		VectorScale( centroid, 1.0 / (f->numedges * 2), centroid );
		VectorCopy( centroid, face_centroids[fn] );  // Save them for generating the patch normals later.

		patch->faceNumber = fn;
		WindingCenter (w, patch->origin);

#ifdef PHONG_NORMAL_PATCHES
// This seems to be a bad idea for some reason.  Leave it turned off for now.
		VectorAdd (patch->origin, patch->plane->normal, patch->origin);
		GetPhongNormal( fn, patch->origin, patch->normal );
		VectorSubtract (patch->origin, patch->plane->normal, patch->origin);
		if ( !VectorCompare( patch->plane->normal, patch->normal ) )
			patch->chop = 16; // Chop it fine!
#else
		VectorCopy( patch->plane->normal, patch->normal );
#endif
		VectorAdd (patch->origin, patch->normal, patch->origin);

		WindingBounds (w, patch->face_mins, patch->face_maxs);
		VectorCopy( patch->face_mins, patch->mins );
		VectorCopy( patch->face_maxs, patch->maxs );

		BaseLightForFace( f, light, patch->reflectivity );
		VectorCopy( light, patch->totallight );
		VectorCopy( light, patch->baselight );

		// Chop all texlights very fine.
		if ( !VectorCompare( light, vec3_origin ) )
			patch->chop = extra ? minchop / 2 : minchop;

		num_patches++;
	}
}
Beispiel #10
0
void AAS_CreateCurveBrushes(void)
{
	int i, j, n, planenum, numcurvebrushes = 0;
	q3_dsurface_t *surface;
	q3_drawVert_t *dv_p;
	vec3_t points[MAX_PATCH_VERTS];
	int width, height, c;
	patchCollide_t *pc;
	facet_t *facet;
	mapbrush_t *brush;
	side_t *side;
	entity_t *mapent;
	winding_t *winding;

	qprintf("nummapbrushsides = %d\n", nummapbrushsides);
	mapent = &entities[0];

	for(i = 0; i < q3_numDrawSurfaces; i++)
	{
		surface = &q3_drawSurfaces[i];

		if(!surface->patchWidth)
		{
			continue;
		}

		//if the curve is not solid
		if(!(q3_dshaders[surface->shaderNum].contentFlags & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP)))
		{
			//Log_Print("skipped non-solid curve\n");
			continue;
		} //end if

		//
		width = surface->patchWidth;
		height = surface->patchHeight;
		c = width * height;

		if(c > MAX_PATCH_VERTS)
		{
			Error("ParseMesh: MAX_PATCH_VERTS");
		} //end if

		dv_p = q3_drawVerts + surface->firstVert;

		for(j = 0 ; j < c ; j++, dv_p++)
		{
			points[j][0] = dv_p->xyz[0];
			points[j][1] = dv_p->xyz[1];
			points[j][2] = dv_p->xyz[2];
		} //end for

		// create the internal facet structure
		pc = CM_GeneratePatchCollide(width, height, points);

		//
		for(j = 0; j < pc->numFacets; j++)
		{
			facet = &pc->facets[j];
			//
			brush = &mapbrushes[nummapbrushes];
			brush->original_sides = &brushsides[nummapbrushsides];
			brush->entitynum = 0;
			brush->brushnum = nummapbrushes - mapent->firstbrush;
			//
			brush->numsides = facet->numBorders + 2;
			nummapbrushsides += brush->numsides;
			brush->contents = CONTENTS_SOLID;
			//
			//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
			qprintf("\r%6d curve brushes", ++numcurvebrushes);
			//
			planenum = FindFloatPlane(pc->planes[facet->surfacePlane].plane, pc->planes[facet->surfacePlane].plane[3]);
			//
			side = &brush->original_sides[0];
			side->planenum = planenum;
			side->contents = CONTENTS_SOLID;
			side->flags |= SFL_TEXTURED | SFL_VISIBLE | SFL_CURVE;
			side->surf = 0;
			//
			side = &brush->original_sides[1];

			if(create_aas)
			{
				//the plane is expanded later so it's not a problem that
				//these first two opposite sides are coplanar
				side->planenum = planenum ^ 1;
			} //end if
			else
			{
				side->planenum = FindFloatPlane(mapplanes[planenum ^ 1].normal, mapplanes[planenum ^ 1].dist + 1);
				side->flags |= SFL_TEXTURED | SFL_VISIBLE;
			} //end else

			side->contents = CONTENTS_SOLID;
			side->flags |= SFL_CURVE;
			side->surf = 0;
			//
			winding = BaseWindingForPlane(mapplanes[side->planenum].normal, mapplanes[side->planenum].dist);

			for(n = 0; n < facet->numBorders; n++)
			{
				//never use the surface plane as a border
				if(facet->borderPlanes[n] == facet->surfacePlane)
				{
					continue;
				}

				//
				side = &brush->original_sides[2 + n];
				side->planenum = FindFloatPlane(pc->planes[facet->borderPlanes[n]].plane, pc->planes[facet->borderPlanes[n]].plane[3]);

				if(facet->borderInward[n])
				{
					side->planenum ^= 1;
				}

				side->contents = CONTENTS_SOLID;
				side->flags |= SFL_TEXTURED | SFL_CURVE;
				side->surf = 0;

				//chop the winding in place
				if(winding)
				{
					ChopWindingInPlace(&winding, mapplanes[side->planenum ^ 1].normal, mapplanes[side->planenum ^ 1].dist, 0.1);      //CLIP_EPSILON);
				}
			} //end for

			//VectorCopy(pc->bounds[0], brush->mins);
			//VectorCopy(pc->bounds[1], brush->maxs);
			if(!winding)
			{
				Log_Print("WARNING: AAS_CreateCurveBrushes: no winding\n");
				brush->numsides = 0;
				continue;
			} //end if

			brush->original_sides[0].winding = winding;
			WindingBounds(winding, brush->mins, brush->maxs);

			for(n = 0; n < 3; n++)
			{
				//IDBUG: all the indexes into the mins and maxs were zero (not using i)
				if(brush->mins[n] < -MAX_MAP_BOUNDS || brush->maxs[n] > MAX_MAP_BOUNDS)
				{
					Log_Print("entity %i, brush %i: bounds out of range\n", brush->entitynum, brush->brushnum);
					Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
					brush->numsides = 0; //remove the brush
					break;
				} //end if

				if(brush->mins[n] > MAX_MAP_BOUNDS || brush->maxs[n] < -MAX_MAP_BOUNDS)
				{
					Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
					Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
					brush->numsides = 0; //remove the brush
					break;
				} //end if
			} //end for

			if(create_aas)
			{
				//NOTE: brush bevels now already added
				//AddBrushBevels(brush);
				AAS_CreateMapBrushes(brush, mapent, false);
			} //end if
			else
			{
				// create windings for sides and bounds for brush
				MakeBrushWindings(brush);
				AddBrushBevels(brush);
				nummapbrushes++;
				mapent->numbrushes++;
			} //end else
		} //end for
	} //end for

	//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
	qprintf("\r%6d curve brushes\n", numcurvebrushes);
} //end of the function AAS_CreateCurveBrushes
Beispiel #11
0
/**
 * @brief CM_AddFacetBevels
 * @param[in,out] facet
 */
void CM_AddFacetBevels(facet_t *facet)
{
	int       i, j, k, l;
	int       axis, dir, flipped;
	float     plane[4], d, minBack, 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
	for (axis = 0; axis < 3; axis++)
	{
		for (dir = -1; dir <= 1; dir += 2)
		{
			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 already 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("CM_AddFacetBevels: ERROR - too many bevels\n");
					continue;
				}
				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 (vec3_norm(vec) < 0.5f)
		{
			continue;
		}
		CM_SnapVector(vec);
		for (k = 0; k < 3; k++)
		{
			if (vec[k] == -1.0f || vec[k] == 1.0f || (vec[k] == 0.0f && vec[(k + 1) % 3] == 0.0f))
			{
				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;
				vec3_cross(vec, vec2, plane);
				if (vec3_norm(plane) < 0.5f)
				{
					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
				minBack = 0.0f;
				for (l = 0; l < w->numpoints; l++)
				{
					d = DotProduct(w->p[l], plane) - plane[3];
					if (d > 0.1f)
					{
						break;  // point in front
					}
					if (d < minBack)
					{
						minBack = d;
					}
				}
				// if some point was at the front
				if (l < w->numpoints)
				{
					continue;
				}

				// if no points at the back then the winding is on the bevel plane
				if (minBack > -0.1f)
				{
					break;
				}

				// if it's the surface plane
				if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped))
				{
					continue;
				}
				// see if the plane is already 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("CM_AddFacetBevels: ERROR - too many bevels\n");
						continue;
					}
					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("CM_AddFacetBevels: 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];
					}
					ChopWindingInPlace(&w2, newplane, newplane[3], 0.1f);
					if (!w2)
					{
						// any map load spams with this error .. don't print it anymore
						//Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n");
						continue;
					}
					else
					{
						FreeWinding(w2);
					}

					facet->numBorders++;
					// already got a bevel
					//break;
				}
			}
		}
	}
	FreeWinding(w);

	// add opposite plane
	if (facet->numBorders >= 4 + 6 + 16)
	{
		Com_Printf("CM_AddFacetBevels: ERROR - too many bevels at end\n");
		return;
	}

	facet->borderPlanes[facet->numBorders]   = facet->surfacePlane;
	facet->borderNoAdjust[facet->numBorders] = 0;
	facet->borderInward[facet->numBorders]   = qtrue;
	facet->numBorders++;
}
Beispiel #12
0
bface_t *ClipFace (brush_t *b, bface_t *f, bface_t **outside,
				 int splitplane, qboolean precedence)
{
	bface_t		*front;
	winding_t	*fw, *bw;
	vec_t		d;
	plane_t		*split;
	int			i, count[3];

	// handle exact plane matches special

	if (f->planenum == (splitplane^1) )
	{	// opposite side, so put on inside list
		return f;
	}

	if ( f->planenum == splitplane )
	{
		// coplanar
		if (precedence)
		{	// this fragment will go to the inside, because
			// the earlier one was clipped to the outside
			return f;
		}
		f->next = *outside;
		*outside = f;
		return NULL;
	}

	split = &mapplanes[splitplane];
#if 0
	count[0] = count[1] = count[2] = 0;
	for (i=0 ; i<f->w->numpoints ; i++)
	{
		d = DotProduct (f->w->p[i], split->normal) - split->dist;
		if (d < -SPLIT_EPSILON)
			count[1]++;
		else if (d > SPLIT_EPSILON)
			count[0]++;
		else
			count[2]++;
	}

	if (!count[0])
	{
		fw = NULL;
		bw = f->w;
	}
	else if (!count[1])
	{
		fw = f->w;
		bw = NULL;
	}
	else
#endif
		ClipWindingNoCopy (f->w, split->normal, split->dist, &fw, &bw);

	if (!fw)
		return f;

	if (!bw)
	{
		f->next = *outside;
		*outside = f;
		return NULL;
	}

	FreeWinding (f->w);

	front = NewFaceFromFace (f);
	front->w = fw;
	WindingBounds (fw, front->mins, front->maxs);
	front->next = *outside;
	*outside = front;

	f->w = bw;
	WindingBounds (bw, f->mins, f->maxs);

	return f;
}