示例#1
0
/**
 * @param[in] tile Tile to check (normally 0 - except in assembled maps)
 * @param[in] start trace start vector
 * @param[in] end trace end vector
 * @param[in] mins box mins
 * @param[in] maxs box maxs
 * @param[in] headnode if < 0 we are in a leaf node
 * @param[in] contentmask content flags the trace should stop at (see MASK_*)
 * @param[in] brushrejects brushes the trace should ignore (see MASK_*)
 * @param[in] origin center for rotating objects
 * @param[in] angles current rotation status (in degrees) for rotating objects
 * @param[in] rmaShift how much the object was shifted by the RMA process (needed for doors)
 * @param[in] fraction The furthest distance needed to trace before we stop.
 * @brief Handles offseting and rotation of the end points for moving and rotating entities
 * @sa CM_BoxTrace
 */
trace_t CM_HintedTransformedBoxTrace (mapTile_t *tile, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, const int headnode, const int contentmask, const int brushrejects, const vec3_t origin, const vec3_t angles, const vec3_t rmaShift, const float fraction)
{
	trace_t trace;
	vec3_t start_l, end_l;
	vec3_t forward, right, up;
	vec3_t temp;
	bool rotated;

	/* subtract origin offset */
	VectorSubtract(start, origin, start_l);
	VectorSubtract(end, origin, end_l);

	/* rotate start and end into the models frame of reference */
	if (headnode != tile->box_headnode && VectorNotEmpty(angles)) {
		rotated = true;
	} else {
		rotated = false;
	}

	if (rotated) {
		AngleVectors(angles, forward, right, up);

		VectorCopy(start_l, temp);
		start_l[0] = DotProduct(temp, forward);
		start_l[1] = -DotProduct(temp, right);
		start_l[2] = DotProduct(temp, up);

		VectorCopy(end_l, temp);
		end_l[0] = DotProduct(temp, forward);
		end_l[1] = -DotProduct(temp, right);
		end_l[2] = DotProduct(temp, up);
	}

	/* When tracing through a model, we want to use the nodes, planes etc. as calculated by ufo2map.
	 * But nodes and planes have been shifted in case of an RMA. At least for doors we need to undo the shift. */
	if (VectorNotEmpty(origin)) {					/* only doors seem to have their origin set */
		VectorAdd(start_l, rmaShift, start_l);		/* undo the shift */
		VectorAdd(end_l, rmaShift, end_l);
	}

	/* sweep the box through the model */
	trace = TR_BoxTrace(tile, start_l, end_l, mins, maxs, headnode, contentmask, brushrejects, fraction);
	trace.mapTile = tile->idx;

	if (rotated && trace.fraction != 1.0) {
		vec3_t a;
		/** @todo figure out how to do this with existing angles */
		VectorNegate(angles, a);
		AngleVectors(a, forward, right, up);

		VectorCopy(trace.plane.normal, temp);
		trace.plane.normal[0] = DotProduct(temp, forward);
		trace.plane.normal[1] = -DotProduct(temp, right);
		trace.plane.normal[2] = DotProduct(temp, up);
	}

	VectorInterpolation(start, end, trace.fraction, trace.endpos);

	return trace;
}
示例#2
0
/**
 * @brief Rotates AABB around given origin point; note that it will expand the box unless all angles are multiples of 90 degrees
 * @note Not fully verified so far
 */
void AABB::rotateAround (const vec3_t origin, const vec3_t angles) {
	/* reject non-rotations */
	if (VectorEmpty(angles))
		return;

	/* construct box-centered coordinates (center and corners) */
	vec3_t center, halfDiagonal;

	VectorInterpolation(mins, maxs, 0.5f, center);
	VectorSubtract(maxs, center, halfDiagonal);

	/* offset coordinate frame to rotation origin */
	VectorSubtract(center, origin, center);

	/* rotate center by given angles */
	vec3_t m[3];
	VectorCreateRotationMatrix(angles, m);

	vec3_t newCenter;
	VectorRotate(m, center, newCenter);

	/* short-circuit calculation of the rotated box half-extents */
	/* shortcut is: instead of calculating all 8 AABB corners, use the symmetry by rotating box around it's center. */
	VectorAbs(m[0]);
	VectorAbs(m[1]);
	VectorAbs(m[2]);

	vec3_t newHalfDiagonal;
	VectorRotate(m, halfDiagonal, newHalfDiagonal);

	/* de-offset coordinate frame from rotation origin */
	VectorAdd(newCenter, origin, newCenter);

	/* finally, combine results into new AABB */
	VectorAdd(newCenter, newHalfDiagonal, maxs);
	VectorSubtract(newCenter, newHalfDiagonal, mins);
}