/*
===============
SubdivideFace

If the face is >256 in either texture direction, carve a valid sized
piece off and insert the remainder in the next link
===============
*/
void SubdivideFace (face_t *f, face_t **prevptr)
{
	float		mins, maxs;
	double		v;
	int			axis, i;
	plane_t		plane;
	face_t		*front, *back, *next;
	texinfo_t	*tex;

// special (non-surface cached) faces don't need subdivision
	tex = &texinfo[f->texturenum];

	if ( tex->flags & TEX_SPECIAL)
		return;

	for (axis = 0 ; axis < 2 ; axis++)
	{
		while (1)
		{
			mins = 9999;
			maxs = -9999;

			for (i = 0 ; i < f->numpoints ; i++)
			{
				v = DotProduct (f->pts[i], tex->vecs[axis]);
				if (v < mins)
					mins = v;
				if (v > maxs)
					maxs = v;
			}

			if (maxs - mins <= 240)
				break;

		// split it
			subdivides++;

			VectorCopy (tex->vecs[axis], plane.normal);
			v = VectorLength (plane.normal);
			VectorNormalize (plane.normal);
			plane.dist = (mins + 224)/v;
			next = f->next;
			SplitFace (f, &plane, &front, &back);
			if (!front || !back)
				Error ("%s: didn't split the polygon", __thisfunc__);
			*prevptr = back;
			back->next = front;
			front->next = next;
			f = back;
		}
	}
}
示例#2
0
/*
===============
SubdivideFace

If the face is >256 in either texture direction, carve a valid sized
piece off and insert the remainder in the next link
===============
*/
void
SubdivideFace(face_t *f, face_t **prevptr)
{
    vec_t mins, maxs;
    vec_t v;
    int axis, i;
    plane_t plane;
    face_t *front, *back, *next;
    texinfo_t *tex;
    vec3_t tmp;

    /* special (non-surface cached) faces don't need subdivision */
    tex = (texinfo_t *)pWorldEnt->lumps[LUMP_TEXINFO].data + f->texinfo;
    if (tex->flags & (TEX_SPECIAL | TEX_SKIP | TEX_HINT))
        return;

    for (axis = 0; axis < 2; axis++) {
        while (1) {
            mins = VECT_MAX;
            maxs = -VECT_MAX;

            tmp[0] = tex->vecs[axis][0];
            tmp[1] = tex->vecs[axis][1];
            tmp[2] = tex->vecs[axis][2];

            for (i = 0; i < f->w.numpoints; i++) {
                v = DotProduct(f->w.points[i], tmp);
                if (v < mins)
                    mins = v;
                if (v > maxs)
                    maxs = v;
            }

            if (maxs - mins <= options.dxSubdivide)
                break;

            // split it
            VectorCopy(tmp, plane.normal);
            v = VectorLength(plane.normal);
            VectorNormalize(plane.normal);
            plane.dist = (mins + options.dxSubdivide - 16) / v;
            next = f->next;
            SplitFace(f, &plane, &front, &back);
            if (!front || !back)
                Error("Didn't split the polygon (%s)", __func__);
            *prevptr = back;
            back->next = front;
            front->next = next;
            f = back;
        }
    }
}
示例#3
0
/*
=================
ClipInside

Clips all of the faces in the inside list, possibly moving them to the
outside list or spliting it into a piece in each list.

Faces exactly on the plane will stay inside unless overdrawn by later brush

frontside is the side of the plane that holds the outside list
=================
*/
static void ClipInside (int splitplane, int frontside, qboolean precedence)
{
	face_t	*f, *next;
	face_t	*frags[2];
	face_t	*insidelist;
	plane_t *split;

	split = &planes[splitplane];

	insidelist = NULL;
	for (f = inside ; f ; f = next)
	{
		next = f->next;

		if (f->planenum == splitplane)
		{	// exactly on, handle special
			if ( frontside != f->planeside || precedence )
			{	// always clip off opposite faceing
				frags[frontside] = NULL;
				frags[!frontside] = f;
			}
			else
			{	// leave it on the outside
				frags[frontside] = f;
				frags[!frontside] = NULL;
			}
		}
		else
		{	// proper split
			SplitFace (f, split, &frags[0], &frags[1]);
		}

		if (frags[frontside])
		{
			frags[frontside]->next = outside;
			outside = frags[frontside];
		}
		if (frags[!frontside])
		{
			frags[!frontside]->next = insidelist;
			insidelist = frags[!frontside];
		}
	}

	inside = insidelist;
}
示例#4
0
/*
==================
DivideSurface
==================
*/
void DivideSurface (surface_t *in, dplane_t *split, surface_t **front, surface_t **back)
{
	face_t		*facet, *next;
	face_t		*frontlist, *backlist;
	face_t		*frontfrag, *backfrag;
	surface_t	*news;
	dplane_t	*inplane;	

	inplane = &dplanes[in->planenum];
	
	// parallel case is easy

	if (inplane->normal[0] == split->normal[0]
	&& inplane->normal[1] == split->normal[1]
	&& inplane->normal[2] == split->normal[2])
	{
		if (inplane->dist > split->dist)
		{
			*front = in;
			*back = NULL;
		}
		else if (inplane->dist < split->dist)
		{
			*front = NULL;
			*back = in;
		}
		else
		{	// split the surface into front and back
			frontlist = NULL;
			backlist = NULL;
			for (facet = in->faces ; facet ; facet = next)
			{
				next = facet->next;
				if (facet->planenum & 1)
				{
					facet->next = backlist;
					backlist = facet;
				}
				else
				{
					facet->next = frontlist;
					frontlist = facet;
				}
			}
			goto makesurfs;
		}
		return;
	}
	
// do a real split.  may still end up entirely on one side
// OPTIMIZE: use bounding box for fast test
	frontlist = NULL;
	backlist = NULL;
	
	for (facet = in->faces ; facet ; facet = next)
	{
		next = facet->next;
		SplitFace (facet, split, &frontfrag, &backfrag);
		if (frontfrag)
		{
			frontfrag->next = frontlist;
			frontlist = frontfrag;
		}
		if (backfrag)
		{
			backfrag->next = backlist;
			backlist = backfrag;
		}
	}

// if nothing actually got split, just move the in plane
makesurfs:
	if (frontlist == NULL)
	{
		*front = NULL;
		*back = in;
		in->faces = backlist;
		return;
	}

	if (backlist == NULL)
	{
		*front = in;
		*back = NULL;
		in->faces = frontlist;
		return;
	}
	

// stuff got split, so allocate one new surface and reuse in
	news = AllocSurface ();
	*news = *in;
	news->faces = backlist;
	*back = news;
	
	in->faces = frontlist;
	*front = in;
	
// recalc bboxes and flags
	CalcSurfaceInfo (news);
	CalcSurfaceInfo (in);	
}
示例#5
0
/*
===============
SubdivideFace

If the face is >256 in either texture direction, carve a valid sized
piece off and insert the remainder in the next link
===============
*/
void SubdivideFace (face_t *f, face_t **prevptr)
{
	float		mins, maxs;
	vec_t		v;
	int			axis, i;
	dplane_t	plane;
	face_t		*front, *back, *next;
	texinfo_t	*tex;
	vec3_t		temp;

// special (non-surface cached) faces don't need subdivision

	tex = &texinfo[f->texturenum];

	if ( tex->flags & TEX_SPECIAL)
		return;


	for (axis = 0 ; axis < 2 ; axis++)
	{
		while (1)
		{
			mins = 999999;
			maxs = -999999;
			
			for (i=0 ; i<f->numpoints ; i++)
			{
				v = DotProduct (f->pts[i], tex->vecs[axis]);
				if (v < mins)
					mins = v;
				if (v > maxs)
					maxs = v;
			}
		
			if (maxs - mins <= subdivide_size)
				break;
			
		// split it
			subdivides++;
			
			VectorCopy (tex->vecs[axis], temp);
			v = VectorNormalize (temp);	

			VectorCopy (temp, plane.normal);
			plane.dist = (mins + subdivide_size - 16)/v;
			next = f->next;
			SplitFace (f, &plane, &front, &back);
			if (!front || !back)
			{
				//PrintMemory();
				printf("SubdivideFace: didn't split the %d-sided polygon @(%.0f,%.0f,%.0f)", 
						f->numpoints, f->pts[0][0], f->pts[0][1], f->pts[0][2] );
				break;
			}
			*prevptr = back;
			back->next = front;
			front->next = next;
			f = back;
		}
	}
}
/*
===============
SubdivideFace

If the face is >256 in either texture direction, carve a valid sized
piece off and insert the remainder in the next link
===============
*/
void SubdivideFace (face_t *f, face_t **prevptr)
{
	vec3_t		mins, maxs;
	double		v;
	int			i, j;
	plane_t		plane;
	face_t		*front, *back, *next;
	float		size[3];

// special (non-surface cached) faces don't need subdivision
	if ( texinfo[f->texturenum].flags & TEX_SPECIAL)
		return;

	do
	{
		mins[0] = mins[1] = mins[2] = 9999;
		maxs[0] = maxs[1] = maxs[2] = -9999;

		for (i = 0 ; i < f->numpoints ; i++)
		{
			for (j = 0 ; j < 3 ; j++)
			{
				v = f->pts[i][j];
				if (v < mins[j])
					mins[j] = v;
				if (v > maxs[j])
					maxs[j] = v;
			}
		}

		for (i = 0 ; i < 3 ; i++)
			size[i] = maxs[i] - mins[i];

#	if 0
		if ( !size[0] && size[1] <= 496 && size[2] <= 496 && size[1]*size[2]<0x10000)
			return;
		if ( !size[1] && size[0] <= 496 && size[2] <= 496 && size[0]*size[2]<0x10000)
			return;
		if ( !size[2] && size[0] <= 496 && size[1] <= 496 && size[0]*size[1]<0x10000)
			return;
#	endif

		for (i = 0 ; i < 3 ; i++)
		{
			v = maxs[i] - mins[i];
			if (v <= 240)	// NOT 256, because of 16 pixel edge crossings
				continue;

		// split it
			subdivides++;

			plane.normal[0] = plane.normal[1] = plane.normal[2] = 0;
			plane.normal[i] = 1;
			plane.dist = maxs[i] - 224;	// not 240, because of epsilons
			next = f->next;
			SplitFace (f, &plane, &front, &back);
			if (!front || !back)
				Error ("%s: didn't split the polygon", __thisfunc__);
			*prevptr = front;
			front->next = back;
			back->next = next;
			f = front;
			break;
		}

	} while (i < 3);
}
示例#7
0
/*
==================
DividePlane
==================
*/
static void
DividePlane(surface_t *in, plane_t *split, surface_t **front,
	    surface_t **back)
{
    face_t *facet, *next;
    face_t *frontlist, *backlist;
    face_t *frontfrag, *backfrag;
    surface_t *news;
    plane_t *inplane;

    inplane = &pPlanes[in->planenum];
    *front = *back = NULL;

    // parallel case is easy
    if (VectorCompare(inplane->normal, split->normal)) {
	// check for exactly on node
	if (inplane->dist == split->dist) {
	    facet = in->faces;
	    in->faces = NULL;
	    in->onnode = true;

	    // divide the facets to the front and back sides
	    news = AllocMem(SURFACE, 1, true);
	    *news = *in;

	    // Prepend each face in facet list to either in or news lists
	    for (; facet; facet = next) {
		next = facet->next;
		if (facet->planeside == 1) {
		    facet->next = news->faces;
		    news->faces = facet;
		} else {
		    facet->next = in->faces;
		    in->faces = facet;
		}
	    }

	    if (in->faces)
		*front = in;
	    else
		FreeMem(in, SURFACE, 1);

	    if (news->faces)
		*back = news;
	    else
		FreeMem(news, SURFACE, 1);

	    return;
	}

	if (inplane->dist > split->dist)
	    *front = in;
	else
	    *back = in;
	return;
    }
// do a real split.  may still end up entirely on one side
// OPTIMIZE: use bounding box for fast test
    frontlist = NULL;
    backlist = NULL;

    for (facet = in->faces; facet; facet = next) {
	next = facet->next;
	SplitFace(facet, split, &frontfrag, &backfrag);
	if (frontfrag) {
	    frontfrag->next = frontlist;
	    frontlist = frontfrag;
	}
	if (backfrag) {
	    backfrag->next = backlist;
	    backlist = backfrag;
	}
    }

    // if nothing actually got split, just move the in plane
    if (frontlist == NULL) {
	*back = in;
	in->faces = backlist;
	return;
    }

    if (backlist == NULL) {
	*front = in;
	in->faces = frontlist;
	return;
    }

    // stuff got split, so allocate one new plane and reuse in
    news = AllocMem(SURFACE, 1, true);
    *news = *in;
    news->faces = backlist;
    *back = news;

    in->faces = frontlist;
    *front = in;

    // recalc bboxes and flags
    CalcSurfaceInfo(news);
    CalcSurfaceInfo(in);
}
示例#8
0
// =====================================================================================
//  SubdivideFace
//      If the face is >256 in either texture direction, carve a valid sized
//      piece off and insert the remainder in the next link
// =====================================================================================
void            SubdivideFace(face_t* f, face_t** prevptr)
{
    vec_t           mins, maxs;
    vec_t           v;
    int             axis;
    int             i;
    dplane_t        plane;
    face_t*         front;
    face_t*         back;
    face_t*         next;
    texinfo_t*      tex;
    vec3_t          temp;

    // special (non-surface cached) faces don't need subdivision

#ifdef HLCSG_HLBSP_VOIDTEXINFO
	if (f->texturenum == -1)
	{
		return;
	}
#endif
    tex = &g_texinfo[f->texturenum];

    if (tex->flags & TEX_SPECIAL) 
    {
        return;
    }

    if (f->facestyle == face_hint)
    {
        return;
    }
    if (f->facestyle == face_skip)
    {
        return;
    }

#ifdef ZHLT_NULLTEX    // AJM
    if (f->facestyle == face_null)
        return; // ideally these should have their tex_special flag set, so its here jic
#endif
#ifdef HLCSG_HLBSP_SOLIDHINT
	if (f->facestyle == face_discardable)
		return;
#endif
	
    for (axis = 0; axis < 2; axis++)
    {
        while (1)
        {
#ifdef HLBSP_SUBDIVIDE_INMID
			const int maxlightmapsize = g_subdivide_size / TEXTURE_STEP + 1;
			int lightmapmins, lightmapmaxs;
			if (f->numpoints == 0)
			{
				break;
			}
			for (i = 0; i < f->numpoints; i++)
			{
				v = DotProduct (f->pts[i], tex->vecs[axis]) + tex->vecs[axis][3];
				if (i == 0 || v < mins)
				{
					mins = v;
				}
				if (i == 0 || v > maxs)
				{
					maxs = v;
				}
			}
			lightmapmins = (int)floor (mins / TEXTURE_STEP - 0.05); // the worst case
			lightmapmaxs = (int)ceil (maxs / TEXTURE_STEP + 0.05); // the worst case
			if (lightmapmaxs - lightmapmins <= maxlightmapsize)
			{
				break;
			}
#else
            mins = 999999;
            maxs = -999999;

            for (i = 0; i < f->numpoints; i++)
            {
                v = DotProduct(f->pts[i], tex->vecs[axis]);
                if (v < mins)
                {
                    mins = v;
                }
                if (v > maxs)
                {
                    maxs = v;
                }
            }

            if ((maxs - mins) <= g_subdivide_size)
            {
                break;
            }
#endif
                
            // split it
            subdivides++;

            VectorCopy(tex->vecs[axis], temp);
            v = VectorNormalize(temp);

            VectorCopy(temp, plane.normal);
#ifdef HLBSP_SUBDIVIDE_INMID
			int splitpos;
			if ((lightmapmaxs - lightmapmins - 1) - (maxlightmapsize - 1) < (maxlightmapsize - 1) / 4) // don't create very thin face
			{
				splitpos = lightmapmins + (maxlightmapsize - 1) - (maxlightmapsize - 1) / 4;
			}
			else
			{
				splitpos = lightmapmins + (maxlightmapsize - 1);
			}
			plane.dist = ((splitpos + 0.5) * TEXTURE_STEP - tex->vecs[axis][3]) / v;
#else
            plane.dist = (mins + g_subdivide_size - TEXTURE_STEP) / v; //plane.dist = (mins + g_subdivide_size - 16) / v; //--vluzacn
#endif
            next = f->next;
            SplitFace(f, &plane, &front, &back);
            if (!front || !back)
            {
                Developer(DEVELOPER_LEVEL_SPAM, "SubdivideFace: didn't split the %d-sided polygon @(%.0f,%.0f,%.0f)",
                        f->numpoints, f->pts[0][0], f->pts[0][1], f->pts[0][2]);
#ifndef HLBSP_SubdivideFace_FIX
                break;
#endif
            }
#ifdef HLBSP_SubdivideFace_FIX
			f = next;
			if (front)
			{
				front->next = f;
				f = front;
			}
			if (back)
			{
				back->next = f;
				f = back;
			}
			*prevptr = f;
#else
            *prevptr = back;
            back->next = front;
            front->next = next;
            f = back;
#endif
        }
    }
}