Exemple #1
0
/*
=======================================================================================================================================
RemoveColinearPoints
=======================================================================================================================================
*/
void RemoveColinearPoints(winding_t *w) {
	int i, j, k;
	vec3_t v1, v2;
	int nump = 0;
	vec3_t p[MAX_POINTS_ON_WINDING];

	for (i = 0; i < w->numpoints; i++) {
		j = (i + 1)%w->numpoints;
		k = (i + w->numpoints - 1)%w->numpoints;
		VectorSubtract(w->p[j], w->p[i], v1);
		VectorSubtract(w->p[i], w->p[k], v2);
		vec3_norm2(v1, v1);
		vec3_norm2(v2, v2);

		if (DotProduct(v1, v2) < 0.999f) {
			VectorCopy(w->p[i], p[nump]);
			nump++;
		}
	}

	if (nump == w->numpoints) {
		return;
	}

	c_removed += w->numpoints - nump;
	w->numpoints = nump;

	Com_Memcpy(w->p, p, nump * sizeof(p[0]));
}
Exemple #2
0
static box_t get_box(const vec3_t *p0, const vec3_t *p1, const vec3_t *n,
                     float r, const plane_t *plane)
{
    mat4_t rot;
    box_t box;
    if (p1 == NULL) {
        box = bbox_from_extents(*p0, r, r, r);
        box = box_swap_axis(box, 2, 0, 1);
        return box;
    }
    if (r == 0) {
        box = bbox_grow(bbox_from_points(*p0, *p1), 0.5, 0.5, 0.5);
        // Apply the plane rotation.
        rot = plane->mat;
        rot.vecs[3] = vec4(0, 0, 0, 1);
        mat4_imul(&box.mat, rot);
        return box;
    }

    // Create a box for a line:
    int i;
    const vec3_t AXES[] = {vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1)};

    box.mat = mat4_identity;
    box.p = vec3_mix(*p0, *p1, 0.5);
    box.d = vec3_sub(*p1, box.p);
    for (i = 0; i < 3; i++) {
        box.w = vec3_cross(box.d, AXES[i]);
        if (vec3_norm2(box.w) > 0) break;
    }
    if (i == 3) return box;
    box.w = vec3_mul(vec3_normalized(box.w), r);
    box.h = vec3_mul(vec3_normalized(vec3_cross(box.d, box.w)), r);
    return box;
}
Exemple #3
0
/*
=======================================================================================================================================
BaseWindingForPlane
=======================================================================================================================================
*/
winding_t *BaseWindingForPlane(vec3_t normal, vec_t dist) {
	int i, x = -1;
	vec_t max = -MAX_MAP_BOUNDS, v;
	vec3_t org, vright, vup;
	winding_t *w;

	// find the major axis
	for (i = 0; i < 3; i++) {
		v = Q_fabs(normal[i]);

		if (v > max) {
			x = i;
			max = v;
		}
	}

	if (x == -1) {
		Com_Error(ERR_DROP, "BaseWindingForPlane: no axis found");
	}

	VectorCopy(vec3_origin, vup);

	switch (x) {
		case 0:
		case 1:
			vup[2] = 1;
			break;
		case 2:
			vup[0] = 1;
			break;
	}

	v = DotProduct(vup, normal);

	VectorMA(vup, -v, normal, vup);
	vec3_norm2(vup, vup);
	VectorScale(normal, dist, org);
	vec3_cross(vup, normal, vright);
	VectorScale(vup, MAX_MAP_BOUNDS, vup);
	VectorScale(vright, MAX_MAP_BOUNDS, vright);
	// project a really big axis aligned box onto the plane
	w = AllocWinding(4);

	VectorSubtract(org, vright, w->p[0]);
	VectorAdd(w->p[0], vup, w->p[0]);
	VectorAdd(org, vright, w->p[1]);
	VectorAdd(w->p[1], vup, w->p[1]);
	VectorAdd(org, vright, w->p[2]);
	VectorSubtract(w->p[2], vup, w->p[2]);
	VectorSubtract(org, vright, w->p[3]);
	VectorSubtract(w->p[3], vup, w->p[3]);

	w->numpoints = 4;

	return w;
}
Exemple #4
0
/*
=======================================================================================================================================
WindingPlane
=======================================================================================================================================
*/
void WindingPlane(winding_t *w, vec3_t normal, vec_t *dist) {
	vec3_t v1, v2;

	VectorSubtract(w->p[1], w->p[0], v1);
	VectorSubtract(w->p[2], w->p[0], v2);
	vec3_cross(v2, v1, normal);
	vec3_norm2(normal, normal);

	*dist = DotProduct(w->p[0], normal);
}
Exemple #5
0
/*
=======================================================================================================================================
AddWindingToConvexHull

Both w and *hull are on the same plane.
=======================================================================================================================================
*/
void AddWindingToConvexHull(winding_t *w, winding_t **hull, vec3_t normal) {
	int i, j, k;
	float *p, *copy;
	vec3_t dir;
	float d;
	int numHullPoints, numNew;
	vec3_t hullPoints[MAX_HULL_POINTS];
	vec3_t newHullPoints[MAX_HULL_POINTS];
	vec3_t hullDirs[MAX_HULL_POINTS];
	qboolean hullSide[MAX_HULL_POINTS];
	qboolean outside;

	if (!*hull) {
		*hull = CopyWinding(w);
		return;
	}

	numHullPoints = (*hull)->numpoints;

	Com_Memcpy(hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t));

	for (i = 0; i < w->numpoints; i++) {
		p = w->p[i];
		// calculate hull side vectors
		for (j = 0; j < numHullPoints; j++) {
			k = (j + 1) % numHullPoints;

			VectorSubtract(hullPoints[k], hullPoints[j], dir);
			vec3_norm2(dir, dir);
			vec3_cross(normal, dir, hullDirs[j]);
		}

		outside = qfalse;

		for (j = 0; j < numHullPoints; j++) {
			VectorSubtract(p, hullPoints[j], dir);
			d = DotProduct(dir, hullDirs[j]);

			if (d >= ON_EPSILON) {
				outside = qtrue;
			}

			if (d >= -ON_EPSILON) {
				hullSide[j] = qtrue;
			} else {
				hullSide[j] = qfalse;
			}
		}
		// if the point is effectively inside, do nothing
		if (!outside) {
			continue;
		}
		// find the back side to front side transition
		for (j = 0; j < numHullPoints; j++) {
			if (!hullSide[j % numHullPoints] && hullSide[(j + 1) % numHullPoints]) {
				break;
			}
		}

		if (j == numHullPoints) {
			continue;
		}
		// insert the point here
		VectorCopy(p, newHullPoints[0]);

		numNew = 1;
		// copy over all points that aren't double fronts
		j = (j + 1)%numHullPoints;

		for (k = 0; k < numHullPoints; k++) {
			if (hullSide[(j + k) % numHullPoints] && hullSide[(j + k + 1) % numHullPoints]) {
				continue;
			}

			copy = hullPoints[(j + k + 1) % numHullPoints];

			VectorCopy(copy, newHullPoints[numNew]);

			numNew++;
		}

		numHullPoints = numNew;

		Com_Memcpy(hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t));
	}

	FreeWinding(*hull);

	w = AllocWinding(numHullPoints);
	w->numpoints = numHullPoints;
	*hull = w;

	Com_Memcpy(w->p, hullPoints, numHullPoints * sizeof(vec3_t));
}
Exemple #6
0
/*
=======================================================================================================================================
CheckWinding
=======================================================================================================================================
*/
void CheckWinding(winding_t *w) {
	int i, j;
	vec_t *p1, *p2;
	vec_t d, edgedist;
	vec3_t dir, edgenormal, facenormal;
	vec_t area;
	vec_t facedist;

	if (w->numpoints < 3) {
		Com_Error(ERR_DROP, "CheckWinding: %i points", w->numpoints);
	}

	area = WindingArea(w);

	if (area < 1) {
		Com_Error(ERR_DROP, "CheckWinding: %f area", (double)area);
	}

	WindingPlane(w, facenormal, &facedist);

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

		for (j = 0; j < 3; j++) {
			if (p1[j] > MAX_MAP_BOUNDS || p1[j] < -MAX_MAP_BOUNDS) {
				Com_Error(ERR_DROP, "CheckWinding: MAX_MAP_BOUNDS: %f", (double)p1[j]);
			}
		}

		j = i + 1 == w->numpoints ? 0 : i + 1;
		// check the point is on the face plane
		d = DotProduct(p1, facenormal) - facedist;

		if (d < -ON_EPSILON || d > ON_EPSILON) {
			Com_Error(ERR_DROP, "CheckWinding: point off plane");
		}
		// check the edge isn't degenerate
		p2 = w->p[j];

		VectorSubtract(p2, p1, dir);

		if (vec3_length(dir) < ON_EPSILON) {
			Com_Error(ERR_DROP, "CheckWinding: degenerate edge");
		}

		vec3_cross(facenormal, dir, edgenormal);
		vec3_norm2(edgenormal, edgenormal);

		edgedist = DotProduct(p1, edgenormal);
		edgedist += ON_EPSILON;
		// all other points must be on front side
		for (j = 0; j < w->numpoints; j++) {
			if (j == i) {
				continue;
			}

			d = DotProduct(w->p[j], edgenormal);

			if (d > edgedist) {
				Com_Error(ERR_DROP, "CheckWinding: non-convex");
			}
		}
	}
}