Пример #1
0
bool Plane::Equals(const Plane &other, float epsilon) const
{
	return IsParallel(other, epsilon) && EqualAbs(d, other.d, epsilon);
}
Пример #2
0
bool Plane::Contains(const Circle &circle, float epsilon) const
{
	return Contains(circle.pos, epsilon) && (EqualAbs(Abs(Dot(normal, circle.normal)), 1.f) || circle.r <= epsilon);
}
Пример #3
0
bool Plane::SetEquals(const Plane &plane, float epsilon) const
{
	return (normal.Equals(plane.normal) && EqualAbs(d, plane.d, epsilon)) ||
		(normal.Equals(-plane.normal) && EqualAbs(-d, plane.d, epsilon));
}
Пример #4
0
bool Quat::IsNormalized(float epsilonSq) const
{
	return EqualAbs(LengthSq(), 1.f, epsilonSq);
}
Пример #5
0
bool Quat::Equals(const Quat &rhs, float epsilon) const
{
	return EqualAbs(x, rhs.x, epsilon) && EqualAbs(y, rhs.y, epsilon) && EqualAbs(z, rhs.z, epsilon) && EqualAbs(w, rhs.w, epsilon);
}
Пример #6
0
float4 float3x4::MulDir(const float4 &directionVector) const
{
	assume(EqualAbs(directionVector.w, 0.f));
	return this->TransformDir(directionVector);
}
Пример #7
0
/** Computes the (s,t) coordinates of the smallest sphere that passes through three points (0,0,0), ab and ac.
	@param ab The first point to fit the sphere through.
	@param ac The second point to fit the sphere through. The third point is hardcoded to (0,0,0). When fitting a sphere
		through three points a, b and c, pass in b-a as the parameter ab, and c-a as the parameter ac (i.e. translate
		the coordinate system center to lie at a).
	@param s [out] Outputs the s-coordinate of the sphere center (in the 2D barycentric UV convention)
	@param t [out] Outputs the t-coordinate of the sphere center (in the 2D barycentric UV convention) To
		compute the actual point, calculate the expression origin + s*ab + t*ac.
	@note The returned sphere is one that passes through the three points (0,0,0), ab and ac. It is NOT necessarily the
		smallest sphere that encloses these three points!
	@return True if the function succeeded. False on failure. This function fails if the points (0,0,0), ab and ac
		are collinear, in which case there does not exist a sphere that passes through the three given points. */
bool FitSphereThroughPoints(const vec &ab, const vec &ac, float &s, float &t)
{
	/* The task is to compute the minimal radius sphere through the three points
	   a, b and c. (Note that this is not necessarily the minimal radius sphere enclosing
	   the points a, b and c!)

	   Denote by p the sphere center position, and r the sphere radius. If the sphere
	   is to run through the points a, b and c, then the center point of the sphere
	   must be equidistant to these points, i.e.

	      || p - a || == || p - b || == || p - c ||,

	   or

	      a^2 - 2ap + p^2 == b^2 - 2bp + p^2 == c^2 - 2cp + p^2.

	   Subtracting pairwise, we get

	      (b-a)p == (b^2 - a^2)/2 and       (1)
	      (c-a)p == (c^2 - a^2)/2.          (2)

	   Additionally, the center point of the sphere must lie on the same plane as the triangle
	   defined by the points a, b and c. Therefore, the point p can be represented as a 2D
	   barycentric coordinates (s,t) as follows:

	      p == a + s*(b-a) + t*(c-a).        (3)

	   Now, without loss of generality, assume that the point a lies at origin (translate the origin
	   of the coordinate system to be centered at the point a), i.e. make the substitutions
	   A = (0,0,0), B = b-a, C = c-a, and we have:and we have:

	      BP == B^2/2,            (1')
	      CP == C^2/2 and         (2')
	       P == s*B + t*C.        (3') */

	const float BB = Dot(ab,ab);
	const float CC = Dot(ac,ac);
	const float BC = Dot(ab,ac);

	/* Substitute (3') into (1') and (2'), to obtain a matrix equation

	   ( B^2  BC  ) * (s) = (B^2 / 2)
	   ( BC   C^2 )   (t)   (C^2 / 2)

	   which equals
	
	   (s) = ( B^2  BC  )^-1  *  (B^2 / 2)
	   (t)   ( BC   C^2 )        (C^2 / 2)

	   	Use the formula for inverting a 2x2 matrix, and we have

	   (s) = 1 / (2 * B^2 * C^2 - (BC)^2) * ( C^2   -BC ) *  (B^2)
	   (t)                                  ( -BC   B^2 )    (C^2)
	*/

	float denom = BB*CC - BC*BC;

	if (EqualAbs(denom, 0.f, 5e-3f))
		return false;

	denom = 0.5f / denom; // == 1 / (2 * B^2 * C^2 - (BC)^2)

	s = (CC * BB - BC * CC) * denom;
	t = (CC * BB - BC * BB) * denom;

	return true;
}
Пример #8
0
float4 float3x4::MulPos(const float4 &pointVector) const
{
	assume(!EqualAbs(pointVector.w, 0.f));
	return this->Transform(pointVector);
}
Пример #9
0
bool float3x4::HasUniformScale(float epsilon) const
{
	float3 scale = ExtractScale();
	return EqualAbs(scale.x, scale.y, epsilon) && EqualAbs(scale.x, scale.z, epsilon);
}
Пример #10
0
bool float3x4::IsSymmetric(float epsilon) const
{
	return EqualAbs(v[0][1], v[1][0], epsilon) &&
		EqualAbs(v[0][2], v[2][0], epsilon) &&
		EqualAbs(v[1][2], v[2][1], epsilon);
}
Пример #11
0
bool float3x4::IsUpperTriangular(float epsilon) const
{
	return EqualAbs(v[1][0], 0.f, epsilon)
		&& EqualAbs(v[2][0], 0.f, epsilon)
		&& EqualAbs(v[2][1], 0.f, epsilon);
}
Пример #12
0
bool AABB::IntersectLineAABB_CPP(const vec &linePos, const vec &lineDir, float &tNear, float &tFar) const
{
	assume2(lineDir.IsNormalized(), lineDir, lineDir.LengthSq());
	assume2(tNear <= tFar && "AABB::IntersectLineAABB: User gave a degenerate line as input for the intersection test!", tNear, tFar);
	// The user should have inputted values for tNear and tFar to specify the desired subrange [tNear, tFar] of the line
	// for this intersection test.
	// For a Line-AABB test, pass in
	//    tNear = -FLOAT_INF;
	//    tFar = FLOAT_INF;
	// For a Ray-AABB test, pass in
	//    tNear = 0.f;
	//    tFar = FLOAT_INF;
	// For a LineSegment-AABB test, pass in
	//    tNear = 0.f;
	//    tFar = LineSegment.Length();

	// Test each cardinal plane (X, Y and Z) in turn.
	if (!EqualAbs(lineDir.x, 0.f))
	{
		float recipDir = RecipFast(lineDir.x);
		float t1 = (minPoint.x - linePos.x) * recipDir;
		float t2 = (maxPoint.x - linePos.x) * recipDir;

		// tNear tracks distance to intersect (enter) the AABB.
		// tFar tracks the distance to exit the AABB.
		if (t1 < t2)
			tNear = Max(t1, tNear), tFar = Min(t2, tFar);
		else // Swap t1 and t2.
			tNear = Max(t2, tNear), tFar = Min(t1, tFar);

		if (tNear > tFar)
			return false; // Box is missed since we "exit" before entering it.
	}
	else if (linePos.x < minPoint.x || linePos.x > maxPoint.x)
		return false; // The ray can't possibly enter the box, abort.

	if (!EqualAbs(lineDir.y, 0.f))
	{
		float recipDir = RecipFast(lineDir.y);
		float t1 = (minPoint.y - linePos.y) * recipDir;
		float t2 = (maxPoint.y - linePos.y) * recipDir;

		if (t1 < t2)
			tNear = Max(t1, tNear), tFar = Min(t2, tFar);
		else // Swap t1 and t2.
			tNear = Max(t2, tNear), tFar = Min(t1, tFar);

		if (tNear > tFar)
			return false; // Box is missed since we "exit" before entering it.
	}
	else if (linePos.y < minPoint.y || linePos.y > maxPoint.y)
		return false; // The ray can't possibly enter the box, abort.

	if (!EqualAbs(lineDir.z, 0.f)) // ray is parallel to plane in question
	{
		float recipDir = RecipFast(lineDir.z);
		float t1 = (minPoint.z - linePos.z) * recipDir;
		float t2 = (maxPoint.z - linePos.z) * recipDir;

		if (t1 < t2)
			tNear = Max(t1, tNear), tFar = Min(t2, tFar);
		else // Swap t1 and t2.
			tNear = Max(t2, tNear), tFar = Min(t1, tFar);
	}
	else if (linePos.z < minPoint.z || linePos.z > maxPoint.z)
		return false; // The ray can't possibly enter the box, abort.

	return tNear <= tFar;
}