Beispiel #1
0
/**
 * @brief Creates a new axial brush
 */
bspbrush_t* BrushFromBounds (const vec3_t mins, const vec3_t maxs)
{
	bspbrush_t* b;
	int i;
	vec3_t normal;

	b = AllocBrush(6);
	b->numsides = 6;
	for (i = 0; i < 3; i++) {
		VectorClear(normal);
		normal[i] = 1;
		vec_t dist = maxs[i];
		b->sides[i].planenum = FindOrCreateFloatPlane(normal, dist);

		normal[i] = -1;
		dist = -mins[i];
		b->sides[3 + i].planenum = FindOrCreateFloatPlane(normal, dist);
	}

	CreateBrushWindings(b);

	return b;
}
Beispiel #2
0
/**
 * @brief Builds a plane normal and distance from three points on the plane.
 * If the normal is nearly axial, it will be snapped to be axial. Looks
 * up the plane in the unique planes.
 * @param[in] b The brush that the points belong to.
 * @param[in] p0 Three points on the plane. (A vector with plane coordinates)
 * @param[in] p1 Three points on the plane. (A vector with plane coordinates)
 * @param[in] p2 Three points on the plane. (A vector with plane coordinates)
 * @return the index of the plane in the planes list.
 */
static int16_t PlaneFromPoints (const mapbrush_t* b, const vec3_t p0, const vec3_t p1, const vec3_t p2)
{
	vec3_t t1, t2, normal;
	vec_t dist;

	VectorSubtract(p0, p1, t1);
	VectorSubtract(p2, p1, t2);
	CrossProduct(t1, t2, normal);
	VectorNormalize(normal);

	dist = DotProduct(p0, normal);

	if (!VectorNotEmpty(normal))
		Sys_Error("PlaneFromPoints: Bad normal (null) for brush %i", b->brushnum);

	return FindOrCreateFloatPlane(normal, dist);
}
Beispiel #3
0
/**
 * @brief If there was an origin brush, offset all of the planes and texinfo
 * @note Used for e.g. func_door or func_rotating
 */
static void AdjustBrushesForOrigin (const entity_t* ent)
{
	for (int i = 0; i < ent->numbrushes; i++) {
		mapbrush_t* b = &mapbrushes[ent->firstbrush + i];
		for (int j = 0; j < b->numsides; j++) {
			side_t* s = &b->original_sides[j];
			const ptrdiff_t index = s - brushsides;
			const vec_t newdist = mapplanes[s->planenum].dist -
				DotProduct(mapplanes[s->planenum].normal, ent->origin);
			s->surfaceFlags |= SURF_ORIGIN;
			side_brushtextures[index].surfaceFlags |= SURF_ORIGIN;
			s->planenum = FindOrCreateFloatPlane(mapplanes[s->planenum].normal, newdist);
			s->texinfo = TexinfoForBrushTexture(&mapplanes[s->planenum],
				&side_brushtextures[index], ent->origin, s->contentFlags & CONTENTS_TERRAIN);
			s->brush = b;
		}
		/* create windings for sides and bounds for brush */
		MakeBrushWindings(b);
	}
}
Beispiel #4
0
/**
 * @brief Writes the brush list to the bsp
 */
void EmitBrushes (void)
{
	int i, j, bnum, s, x;
	vec3_t normal;
	vec_t dist;
	int planenum;

	curTile->numbrushsides = 0;
	curTile->numbrushes = nummapbrushes;
	/* Clear out curTile->brushes */
	OBJZERO(curTile->brushes);

	for (bnum = 0; bnum < nummapbrushes; bnum++) {
		const mapbrush_t* b = &mapbrushes[bnum];
		dBspBrush_t* db = &curTile->dbrushes[bnum];
		cBspBrush_t* cb = &curTile->brushes[bnum];

		db->contentFlags = b->contentFlags;
		db->firstbrushside = curTile->numbrushsides;
		db->numsides = b->numsides;
		cb->contentFlags = b->contentFlags;
		cb->firstbrushside = curTile->numbrushsides;
		cb->numsides = b->numsides;
		cb->checkcount = 0;
		for (j = 0; j < b->numsides; j++) {
			if (curTile->numbrushsides == MAX_MAP_BRUSHSIDES) {
				Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides);
			} else {
				dBspBrushSide_t* cp = &curTile->brushsides[curTile->numbrushsides];
				curTile->numbrushsides++;
				cp->planenum = b->original_sides[j].planenum;
				cp->texinfo = b->original_sides[j].texinfo;
			}
		}

		/* 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 */
				VectorCopy(vec3_origin, normal);
				normal[x] = (float)s;
				if (s == -1)
					dist = -b->mins[x];
				else
					dist = b->maxs[x];
				planenum = FindOrCreateFloatPlane(normal, dist);
				for (i = 0; i < b->numsides; i++)
					if (b->original_sides[i].planenum == planenum)
						break;
				if (i == b->numsides) {
					if (curTile->numbrushsides >= MAX_MAP_BRUSHSIDES)
						Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides);

					curTile->brushsides[curTile->numbrushsides].planenum = planenum;
					curTile->brushsides[curTile->numbrushsides].texinfo = curTile->brushsides[curTile->numbrushsides - 1].texinfo;
					curTile->numbrushsides++;
					db->numsides++;
					cb->numsides++;
				}
			}
	}
}
Beispiel #5
0
/**
 * @brief Adds any additional planes necessary to allow the brush to be expanded
 * against axial bounding boxes
 */
static void AddBrushBevels (mapbrush_t* b)
{
	int axis, dir;
	int i, l, order;
	vec3_t normal;

	/* add the axial planes */
	order = 0;
	for (axis = 0; axis < 3; axis++) {
		for (dir = -1; dir <= 1; dir += 2, order++) {
			side_t* s;
			/* see if the plane is already present */
			for (i = 0, s = b->original_sides; i < b->numsides; i++, s++) {
				if (mapplanes[s->planenum].normal[axis] == dir)
					break;
			}

			if (i == b->numsides) {	/* add a new side */
				float dist;
				if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
					Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
				nummapbrushsides++;
				b->numsides++;
				VectorClear(normal);
				normal[axis] = dir;
				if (dir == 1)
					dist = b->mbBox.maxs[axis];
				else
					dist = -b->mbBox.mins[axis];
				s->planenum = FindOrCreateFloatPlane(normal, dist);
				s->texinfo = b->original_sides[0].texinfo;
				s->contentFlags = b->original_sides[0].contentFlags;
				s->bevel = true;
				c_boxbevels++;
			}

			/* if the plane is not in it canonical order, swap it */
			if (i != order) {
				const ptrdiff_t index = b->original_sides - brushsides;
				side_t sidetemp = b->original_sides[order];
				brush_texture_t tdtemp = side_brushtextures[index + order];

				b->original_sides[order] = b->original_sides[i];
				b->original_sides[i] = sidetemp;

				side_brushtextures[index + order] = side_brushtextures[index + i];
				side_brushtextures[index + i] = tdtemp;
			}
		}
	}

	/* add the edge bevels */
	if (b->numsides == 6)
		return;		/* pure axial */

	/* test the non-axial plane edges */
	for (i = 6; i < b->numsides; i++) {
		side_t* s = b->original_sides + i;
		winding_t* w = s->winding;
		if (!w)
			continue;

		for (int j = 0; j < w->numpoints; j++) {
			int k = (j + 1) % w->numpoints;
			vec3_t vec;

			VectorSubtract(w->p[j], w->p[k], vec);
			if (VectorNormalize(vec) < 0.5)
				continue;

			SnapVector(vec);

			for (k = 0; k < 3; k++)
				if (vec[k] == -1 || vec[k] == 1
				 || (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 */
					vec3_t vec2 = {0, 0, 0};
					float dist;
					side_t* s2;

					vec2[axis] = dir;
					CrossProduct(vec, vec2, normal);
					if (VectorNormalize(normal) < 0.5)
						continue;
					dist = DotProduct(w->p[j], normal);

					/* if all the points on all the sides are
					 * behind this plane, it is a proper edge bevel */
					for (k = 0; k < b->numsides; k++) {
						winding_t* w2;
						float minBack;

						/* @note: This leads to different results on different archs
						 * due to float rounding/precision errors - use the -ffloat-store
						 * feature of gcc to 'fix' this */
						/* if this plane has already been used, skip it */
						if (PlaneEqual(&mapplanes[b->original_sides[k].planenum], normal, dist))
							break;

						w2 = b->original_sides[k].winding;
						if (!w2)
							continue;
						minBack = 0.0f;
						for (l = 0; l < w2->numpoints; l++) {
							const float d = DotProduct(w2->p[l], normal) - dist;
							if (d > 0.1)
								break;	/* point in front */
							if (d < minBack)
								minBack = d;
						}
						/* if some point was at the front */
						if (l != w2->numpoints)
							break;
						/* if no points at the back then the winding is on the bevel plane */
						if (minBack > -0.1f)
							break;
					}

					if (k != b->numsides)
						continue;	/* wasn't part of the outer hull */
					/* add this plane */
					if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
						Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
					nummapbrushsides++;
					s2 = &b->original_sides[b->numsides];
					s2->planenum = FindOrCreateFloatPlane(normal, dist);
					s2->texinfo = b->original_sides[0].texinfo;
					s2->contentFlags = b->original_sides[0].contentFlags;
					s2->bevel = true;
					c_edgebevels++;
					b->numsides++;
				}
			}
		}
	}
}