light: add FacePairConcavity
This commit is contained in:
parent
a2db5a4ebe
commit
82e3aef283
|
|
@ -835,17 +835,15 @@ qvec3f ClosestPointOnLineSegment(const qvec3f &v, const qvec3f &w, const qvec3f&
|
|||
}
|
||||
|
||||
/// 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)
|
||||
float SignedDegreesBetweenUnitVectors(const qvec3f &start, const qvec3f &end, const qvec3f &normal)
|
||||
{
|
||||
const float cosangle = qmax(-1.0, qmin(1.0, DotProduct(start, end)));
|
||||
const float cosangle = qmax(-1.0, qmin(1.0, qv::dot(start, end)));
|
||||
const float unsigned_degrees = acos(cosangle) * (360.0 / (2.0 * Q_PI));
|
||||
|
||||
// get a normal for the rotation plane using the right-hand rule
|
||||
vec3_t rotationNormal;
|
||||
CrossProduct(start, end, rotationNormal);
|
||||
VectorNormalize(rotationNormal);
|
||||
const qvec3f rotationNormal = qv::normalize(qv::cross(start, end));
|
||||
|
||||
const float normalsCosAngle = DotProduct(rotationNormal, normal);
|
||||
const float normalsCosAngle = qv::dot(rotationNormal, normal);
|
||||
if (normalsCosAngle >= 0) {
|
||||
// counterclockwise rotation
|
||||
return -unsigned_degrees;
|
||||
|
|
@ -854,6 +852,24 @@ float SignedDegreesBetweenUnitVectors(const vec3_t start, const vec3_t end, cons
|
|||
return unsigned_degrees;
|
||||
}
|
||||
|
||||
concavity_t FacePairConcavity(const qvec3f &face1Center,
|
||||
const qvec3f &face1Normal,
|
||||
const qvec3f &face2Center,
|
||||
const qvec3f &face2Normal)
|
||||
{
|
||||
const qvec3f face1to2_dir = qv::normalize(face2Center - face1Center);
|
||||
const qvec3f towards_viewer_dir = qv::cross(face1to2_dir, face1Normal);
|
||||
|
||||
const float degrees = SignedDegreesBetweenUnitVectors(face1Normal, face2Normal, towards_viewer_dir);
|
||||
if (fabs(degrees) < DEGREES_EPSILON) {
|
||||
return concavity_t::Coplanar;
|
||||
} else if (degrees < 0.0f) {
|
||||
return concavity_t::Concave;
|
||||
} else {
|
||||
return concavity_t::Convex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* do the line segments overlap at all?
|
||||
* - if not colinear, returns false.
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ extern const vec3_t vec3_origin;
|
|||
#define POINT_EQUAL_EPSILON 0.05f
|
||||
|
||||
#define NORMAL_EPSILON 0.000001
|
||||
#define DEGREES_EPSILON 0.001
|
||||
|
||||
qboolean VectorCompare(const vec3_t v1, const vec3_t v2, vec_t epsilon);
|
||||
|
||||
|
|
@ -367,7 +368,18 @@ 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);
|
||||
float SignedDegreesBetweenUnitVectors(const qvec3f &start, const qvec3f &end, const qvec3f &normal);
|
||||
|
||||
enum class concavity_t {
|
||||
Coplanar,
|
||||
Concave,
|
||||
Convex
|
||||
};
|
||||
|
||||
concavity_t FacePairConcavity(const qvec3f &face1Center,
|
||||
const qvec3f &face1Normal,
|
||||
const qvec3f &face2Center,
|
||||
const qvec3f &face2Normal);
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -422,15 +422,64 @@ TEST(mathlib, ShrinkPoly2) {
|
|||
}
|
||||
|
||||
TEST(mathlib, SignedDegreesBetweenUnitVectors) {
|
||||
const vec3_t up = {0, 0, 1};
|
||||
const vec3_t fwd = {0, 1, 0};
|
||||
const vec3_t right = {1, 0, 0};
|
||||
const qvec3f up {0, 0, 1};
|
||||
const qvec3f fwd {0, 1, 0};
|
||||
const qvec3f right {1, 0, 0};
|
||||
|
||||
EXPECT_FLOAT_EQ(-90, SignedDegreesBetweenUnitVectors(right, fwd, up));
|
||||
EXPECT_FLOAT_EQ(90, SignedDegreesBetweenUnitVectors(fwd, right, up));
|
||||
EXPECT_FLOAT_EQ(0, SignedDegreesBetweenUnitVectors(right, right, up));
|
||||
}
|
||||
|
||||
TEST(mathlib, ConcavityTest_concave) {
|
||||
const qvec3f face1center {0, 0, 10};
|
||||
const qvec3f face2center {10, 0, 200};
|
||||
|
||||
const qvec3f face1normal {0, 0, 1};
|
||||
const qvec3f face2normal {-1, 0, 0};
|
||||
|
||||
EXPECT_EQ(concavity_t::Concave, FacePairConcavity(face1center, face1normal, face2center, face2normal));
|
||||
}
|
||||
|
||||
TEST(mathlib, ConcavityTest_concave2) {
|
||||
const qvec3f face1center {0, 0, 10};
|
||||
const qvec3f face2center {-10, 0, 200};
|
||||
|
||||
const qvec3f face1normal {0, 0, 1};
|
||||
const qvec3f face2normal {1, 0, 0};
|
||||
|
||||
EXPECT_EQ(concavity_t::Concave, FacePairConcavity(face1center, face1normal, face2center, face2normal));
|
||||
}
|
||||
|
||||
TEST(mathlib, ConcavityTest_convex) {
|
||||
const qvec3f face1center {0, 0, 10};
|
||||
const qvec3f face2center {10, 0, 5};
|
||||
|
||||
const qvec3f face1normal {0, 0, 1};
|
||||
const qvec3f face2normal {1, 0, 0};
|
||||
|
||||
EXPECT_EQ(concavity_t::Convex, FacePairConcavity(face1center, face1normal, face2center, face2normal));
|
||||
}
|
||||
|
||||
TEST(mathlib, ConcavityTest_convex2) {
|
||||
const qvec3f face1center {0, 0, 10};
|
||||
const qvec3f face2center {-10, 0, 5};
|
||||
|
||||
const qvec3f face1normal {0, 0, 1};
|
||||
const qvec3f face2normal {-1, 0, 0};
|
||||
|
||||
EXPECT_EQ(concavity_t::Convex, FacePairConcavity(face1center, face1normal, face2center, face2normal));
|
||||
}
|
||||
|
||||
TEST(mathlib, ConcavityTest_coplanar) {
|
||||
const qvec3f face1center {0, 0, 10};
|
||||
const qvec3f face2center {100, 100, 10};
|
||||
|
||||
const qvec3f face1normal {0, 0, 1};
|
||||
const qvec3f face2normal {0, 0, 1};
|
||||
|
||||
EXPECT_EQ(concavity_t::Coplanar, FacePairConcavity(face1center, face1normal, face2center, face2normal));
|
||||
}
|
||||
static const float MANGLE_EPSILON = 0.1f;
|
||||
|
||||
TEST(light, vec_from_mangle) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue