common: move SignedDegreesBetweenUnitVectors from qbsp, add test

This commit is contained in:
Eric Wasylishen 2017-04-26 14:04:33 -06:00
parent b1f86d7ac1
commit 15cc98eb27
3 changed files with 35 additions and 1 deletions

View File

@ -768,3 +768,26 @@ qvec3f ClosestPointOnLineSegment(const qvec3f &v, const qvec3f &w, const qvec3f&
return ClosestPointOnLine(v, w, p);
}
/// Returns degrees of clockwise rotation from start to end, assuming `normal` is pointing towards the viewer
float SignedDegreesBetweenUnitVectors(const vec3_t start, const vec3_t end, const vec3_t normal)
{
const float cosangle = qmax(-1.0, qmin(1.0, DotProduct(start, end)));
const float unsigned_degrees = acos(cosangle) * (360.0 / (2.0 * Q_PI));
if (unsigned_degrees < ANGLEEPSILON)
return 0;
// get a normal for the rotation plane using the right-hand rule
vec3_t rotationNormal;
CrossProduct(start, end, rotationNormal);
VectorNormalize(rotationNormal);
const float normalsCosAngle = DotProduct(rotationNormal, normal);
if (normalsCosAngle >= 0) {
// counterclockwise rotation
return -unsigned_degrees;
}
// clockwise rotation
return unsigned_degrees;
}

View File

@ -57,7 +57,7 @@ typedef struct {
extern const vec3_t vec3_origin;
#define EQUAL_EPSILON 0.001
#define ANGLEEPSILON 0.000001
#define ZERO_TRI_AREA_EPSILON 0.05f
#define POINT_EQUAL_EPSILON 0.05f
@ -313,6 +313,8 @@ float DistToLineSegment(const qvec3f &v, const qvec3f &w, const qvec3f &p);
qvec3f ClosestPointOnLineSegment(const qvec3f &v, const qvec3f &w, const qvec3f &p);
float SignedDegreesBetweenUnitVectors(const vec3_t start, const vec3_t end, const vec3_t normal);
// Returns weights for f(0,0), f(1,0), f(0,1), f(1,1)
// from: https://en.wikipedia.org/wiki/Bilinear_interpolation#Unit_Square
static inline qvec4f bilinearWeights(const float x, const float y) {

View File

@ -412,6 +412,15 @@ TEST(mathlib, ShrinkPoly2) {
EXPECT_TRUE(polysEqual(shrunkPoly, actualShrunk));
}
TEST(mathlib, SignedDegreesBetweenUnitVectors) {
const vec3_t up = {0, 0, 1};
const vec3_t fwd = {0, 1, 0};
const vec3_t right = {1, 0, 0};
EXPECT_FLOAT_EQ(-90, SignedDegreesBetweenUnitVectors(right, fwd, up));
EXPECT_FLOAT_EQ(90, SignedDegreesBetweenUnitVectors(fwd, right, up));
}
static const float MANGLE_EPSILON = 0.1f;
TEST(light, vec_from_mangle) {