diff --git a/common/mathlib.cc b/common/mathlib.cc index 9072b193..b0fdb80a 100644 --- a/common/mathlib.cc +++ b/common/mathlib.cc @@ -440,6 +440,24 @@ glm::vec3 GLM_ProjectPointOntoPlane(const glm::vec4 &plane, const glm::vec3 &poi return point + move; } +float GLM_PolyArea(const std::vector &points) +{ + Q_assert(points.size() >= 3); + + float poly_area = 0; + + const vec3 v0 = points.at(0); + for (int i = 2; i < points.size(); i++) { + const vec3 v1 = points.at(i-1); + const vec3 v2 = points.at(i); + + const float triarea = GLM_TriangleArea(v0, v1, v2); + + poly_area += triarea; + } + + return poly_area; +} glm::vec3 GLM_PolyCentroid(const std::vector &points) { diff --git a/include/common/mathlib.hh b/include/common/mathlib.hh index 0aedc0a4..5736f046 100644 --- a/include/common/mathlib.hh +++ b/include/common/mathlib.hh @@ -332,6 +332,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_ProjectPointOntoPlane(const glm::vec4 &plane, const glm::vec3 &point); +float GLM_PolyArea(const std::vector &points); glm::vec3 GLM_PolyCentroid(const std::vector &points); glm::vec4 GLM_PolyPlane(const std::vector &points); /// Returns the index of the polygon edge, and the closest point on that edge, to the given point diff --git a/light/test_light.cc b/light/test_light.cc index cc7411ea..71b593ce 100644 --- a/light/test_light.cc +++ b/light/test_light.cc @@ -187,6 +187,19 @@ TEST(mathlib, PolygonCentroid) { EXPECT_EQ(vec3(32,32,0), GLM_PolyCentroid(poly)); } +TEST(mathlib, PolygonArea) { + // poor test.. but at least checks that the colinear point is treated correctly + const vector poly { + { 0,0,0 }, + { 0,32,0 }, // colinear + { 0,64,0 }, + { 64,64,0 }, + { 64,0,0 } + }; + + EXPECT_EQ(64.0f * 64.0f, GLM_PolyArea(poly)); +} + TEST(mathlib, BarycentricFromPoint) { const tri_t tri = make_tuple( // clockwise { 0,0,0 },