light: fix up barycentric coords code, add tests
This commit is contained in:
parent
6f72ab5eda
commit
8ed7544063
|
|
@ -142,11 +142,13 @@ void AABB_Grow(vec3_t mins, vec3_t maxs, const vec3_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
glm::vec2 Barycentric_FromPoint(const glm::vec3 &p, const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c)
|
||||
glm::vec3 Barycentric_FromPoint(const glm::vec3 &p, const tri_t &tri)
|
||||
{
|
||||
const glm::vec3 v0 = b - a;
|
||||
const glm::vec3 v1 = c - a;
|
||||
const glm::vec3 v2 = p - a;
|
||||
using std::get;
|
||||
|
||||
const glm::vec3 v0 = get<1>(tri) - get<0>(tri);
|
||||
const glm::vec3 v1 = get<2>(tri) - get<0>(tri);
|
||||
const glm::vec3 v2 = p - get<0>(tri);
|
||||
float d00 = glm::dot(v0, v0);
|
||||
float d01 = glm::dot(v0, v1);
|
||||
float d11 = glm::dot(v1, v1);
|
||||
|
|
@ -155,26 +157,34 @@ glm::vec2 Barycentric_FromPoint(const glm::vec3 &p, const glm::vec3 &a, const gl
|
|||
float invDenom = (d00 * d11 - d01 * d01);
|
||||
invDenom = 1.0/invDenom;
|
||||
|
||||
glm::vec2 res((d11 * d20 - d01 * d21) * invDenom,
|
||||
(d00 * d21 - d01 * d20) * invDenom);
|
||||
glm::vec3 res;
|
||||
res[1] = (d11 * d20 - d01 * d21) * invDenom;
|
||||
res[2] = (d00 * d21 - d01 * d20) * invDenom;
|
||||
res[0] = 1.0f - res[1] - res[2];
|
||||
return res;
|
||||
}
|
||||
|
||||
// from global illumination total compendium p. 12
|
||||
glm::vec2 Barycentric_Random(const float r1, const float r2)
|
||||
glm::vec3 Barycentric_Random(const float r1, const float r2)
|
||||
{
|
||||
glm::vec2 res(1.0f - sqrtf(r1),
|
||||
r2 * sqrtf(r1));
|
||||
glm::vec3 res;
|
||||
res.x = 1.0f - sqrtf(r1);
|
||||
res.y = r2 * sqrtf(r1);
|
||||
res.z = 1.0f - res.x - res.y;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Evaluates the given barycentric coord for the given triangle
|
||||
glm::vec3 Barycentric_ToPoint(const glm::vec2 &bary,
|
||||
const glm::vec3 &a,
|
||||
const glm::vec3 &b,
|
||||
const glm::vec3 &c)
|
||||
glm::vec3 Barycentric_ToPoint(const glm::vec3 &bary,
|
||||
const tri_t &tri)
|
||||
{
|
||||
const glm::vec3 pt = a + (bary.s * (b - a)) + (bary.t * (c - a));
|
||||
using std::get;
|
||||
|
||||
const glm::vec3 pt = \
|
||||
(bary.x * get<0>(tri))
|
||||
+ (bary.y * get<1>(tri))
|
||||
+ (bary.z * get<2>(tri));
|
||||
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
|
@ -297,6 +307,13 @@ glm::vec3 GLM_FaceNormal(std::vector<glm::vec3> points)
|
|||
return normal;
|
||||
}
|
||||
|
||||
glm::vec4 GLM_PolyPlane(const std::vector<glm::vec3> &points)
|
||||
{
|
||||
const vec3 normal = GLM_FaceNormal(points);
|
||||
const float dist = dot(points.at(0), normal);
|
||||
return vec4(normal, dist);
|
||||
}
|
||||
|
||||
vector<vec4>
|
||||
GLM_MakeInwardFacingEdgePlanes(std::vector<vec3> points)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -279,16 +279,16 @@ public:
|
|||
using aabb3 = aabb<glm::vec3>;
|
||||
using aabb2 = aabb<glm::vec2>;
|
||||
|
||||
using tri_t = std::tuple<glm::vec3, glm::vec3, glm::vec3>;
|
||||
|
||||
/// abc - clockwise ordered triangle
|
||||
/// p - point to get the barycentric coords of
|
||||
glm::vec2 Barycentric_FromPoint(const glm::vec3 &p, const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c);
|
||||
glm::vec2 Barycentric_Random(const float r1, const float r2);
|
||||
glm::vec3 Barycentric_FromPoint(const glm::vec3 &p, const tri_t &tri);
|
||||
glm::vec3 Barycentric_Random(const float r1, const float r2);
|
||||
|
||||
/// Evaluates the given barycentric coord for the given triangle
|
||||
glm::vec3 Barycentric_ToPoint(const glm::vec2 &bary,
|
||||
const glm::vec3 &a,
|
||||
const glm::vec3 &b,
|
||||
const glm::vec3 &c);
|
||||
glm::vec3 Barycentric_ToPoint(const glm::vec3 &bary,
|
||||
const tri_t &tri);
|
||||
|
||||
vec_t TriangleArea(const vec3_t v0, const vec3_t v1, const vec3_t v2);
|
||||
|
||||
|
|
@ -325,6 +325,7 @@ glm::vec3 GLM_TriangleCentroid(const glm::vec3 &v0, const glm::vec3 &v1, const g
|
|||
float GLM_TriangleArea(const glm::vec3 &v0, const glm::vec3 &v1, const glm::vec3 &v2);
|
||||
float GLM_DistAbovePlane(const glm::vec4 &plane, const glm::vec3 &point);
|
||||
glm::vec3 GLM_PolyCentroid(const std::vector<glm::vec3> &points);
|
||||
glm::vec4 GLM_PolyPlane(const std::vector<glm::vec3> &points);
|
||||
/// Returns the index of the polygon edge, and the closest point on that edge, to the given point
|
||||
std::pair<int, glm::vec3> GLM_ClosestPointOnPolyBoundary(const std::vector<glm::vec3> &poly, const glm::vec3 &point);
|
||||
|
||||
|
|
|
|||
|
|
@ -251,9 +251,9 @@ struct face_tris_t {
|
|||
Vertex_GetPos_E(bsp, get<1>(tri)),
|
||||
Vertex_GetPos_E(bsp, get<2>(tri)));
|
||||
|
||||
const glm::vec2 randomBary = Barycentric_Random(Random(), Random());
|
||||
const glm::vec3 randomBary = Barycentric_Random(Random(), Random());
|
||||
|
||||
const glm::vec3 pt = Barycentric_ToPoint(randomBary, get<0>(triPts), get<1>(triPts), get<2>(triPts));
|
||||
const glm::vec3 pt = Barycentric_ToPoint(randomBary, triPts);
|
||||
return pt;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -293,3 +293,78 @@ TEST(mathlib, ClosestPointOnPolyBoundary) {
|
|||
|
||||
EXPECT_EQ(make_pair(0, vec3(0,0,0)), GLM_ClosestPointOnPolyBoundary(poly, vec3(-1,-1,0)));
|
||||
}
|
||||
|
||||
TEST(mathlib, PolygonCentroid) {
|
||||
// poor test.. but at least checks that the colinear point is treated correctly
|
||||
const vector<vec3> poly {
|
||||
{ 0,0,0 },
|
||||
{ 0,32,0 }, // colinear
|
||||
{ 0,64,0 },
|
||||
{ 64,64,0 },
|
||||
{ 64,0,0 }
|
||||
};
|
||||
|
||||
EXPECT_EQ(vec3(32,32,0), GLM_PolyCentroid(poly));
|
||||
}
|
||||
|
||||
TEST(mathlib, BarycentricFromPoint) {
|
||||
const tri_t tri = make_tuple<vec3,vec3,vec3>( // clockwise
|
||||
{ 0,0,0 },
|
||||
{ 0,64,0 },
|
||||
{ 64,0,0 }
|
||||
);
|
||||
|
||||
EXPECT_EQ(vec3(1,0,0), Barycentric_FromPoint(get<0>(tri), tri));
|
||||
EXPECT_EQ(vec3(0,1,0), Barycentric_FromPoint(get<1>(tri), tri));
|
||||
EXPECT_EQ(vec3(0,0,1), Barycentric_FromPoint(get<2>(tri), tri));
|
||||
|
||||
EXPECT_EQ(vec3(0.5, 0.5, 0.0), Barycentric_FromPoint(vec3(0,32,0), tri));
|
||||
EXPECT_EQ(vec3(0.0, 0.5, 0.5), Barycentric_FromPoint(vec3(32,32,0), tri));
|
||||
EXPECT_EQ(vec3(0.5, 0.0, 0.5), Barycentric_FromPoint(vec3(32,0,0), tri));
|
||||
}
|
||||
|
||||
TEST(mathlib, BarycentricToPoint) {
|
||||
const tri_t tri = make_tuple<vec3,vec3,vec3>( // clockwise
|
||||
{ 0,0,0 },
|
||||
{ 0,64,0 },
|
||||
{ 64,0,0 }
|
||||
);
|
||||
|
||||
EXPECT_EQ(get<0>(tri), Barycentric_ToPoint(vec3(1,0,0), tri));
|
||||
EXPECT_EQ(get<1>(tri), Barycentric_ToPoint(vec3(0,1,0), tri));
|
||||
EXPECT_EQ(get<2>(tri), Barycentric_ToPoint(vec3(0,0,1), tri));
|
||||
|
||||
EXPECT_EQ(vec3(0,32,0), Barycentric_ToPoint(vec3(0.5, 0.5, 0.0), tri));
|
||||
EXPECT_EQ(vec3(32,32,0), Barycentric_ToPoint(vec3(0.0, 0.5, 0.5), tri));
|
||||
EXPECT_EQ(vec3(32,0,0), Barycentric_ToPoint(vec3(0.5, 0.0, 0.5), tri));
|
||||
}
|
||||
|
||||
TEST(mathlib, BarycentricRandom) {
|
||||
const tri_t tri = make_tuple<vec3,vec3,vec3>( // clockwise
|
||||
{ 0,0,0 },
|
||||
{ 0,64,0 },
|
||||
{ 64,0,0 }
|
||||
);
|
||||
|
||||
const auto triAsVec = vector<vec3>{get<0>(tri), get<1>(tri), get<2>(tri)};
|
||||
const auto edges = GLM_MakeInwardFacingEdgePlanes(triAsVec);
|
||||
const auto plane = GLM_PolyPlane(triAsVec);
|
||||
|
||||
for (int i=0; i<100; i++) {
|
||||
const float r0 = Random();
|
||||
const float r1 = Random();
|
||||
|
||||
ASSERT_GE(r0, 0);
|
||||
ASSERT_GE(r1, 0);
|
||||
ASSERT_LE(r0, 1);
|
||||
ASSERT_LE(r1, 1);
|
||||
|
||||
const auto bary = Barycentric_Random(r0, r1);
|
||||
EXPECT_FLOAT_EQ(1.0f, bary.x + bary.y + bary.z);
|
||||
|
||||
const vec3 point = Barycentric_ToPoint(bary, tri);
|
||||
EXPECT_TRUE(GLM_EdgePlanes_PointInside(edges, point));
|
||||
|
||||
EXPECT_FLOAT_EQ(0.0f, GLM_DistAbovePlane(plane, point));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue