Enable drawing clockwise shapes despite mapbox::earcut rewinding them

Wed, 29 Jun 2022 14:43:42 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Wed, 29 Jun 2022 14:43:42 +0300
changeset 306
6ad27b7d2697
parent 305
d891da20abca
child 307
4771720fe258

Enable drawing clockwise shapes despite mapbox::earcut rewinding them

src/invert.cpp file | annotate | diff | comparison | revisions
src/invert.h file | annotate | diff | comparison | revisions
src/layers/edittools.cpp file | annotate | diff | comparison | revisions
--- a/src/invert.cpp	Wed Jun 29 14:11:58 2022 +0300
+++ b/src/invert.cpp	Wed Jun 29 14:43:42 2022 +0300
@@ -41,10 +41,10 @@
 	visitPolygon<void>(
 		[](LineSegment&) {},
 		[](Triangle& tri) {
-			std::swap(tri.p1, tri.p2);
+			invert(tri);
 		},
 		[](Quadrilateral& quad) {
-			std::swap(quad.p1, quad.p3);
+			invert(quad);
 		},
 		[](ConditionalEdge&) {},
 		polygon);
--- a/src/invert.h	Wed Jun 29 14:11:58 2022 +0300
+++ b/src/invert.h	Wed Jun 29 14:43:42 2022 +0300
@@ -26,9 +26,32 @@
 {
 	glm::mat4 flipmatrix(Axis dimension);
 }
-//void invert(LDObject* obj, class DocumentManager* context);
+
+constexpr void invert(Quadrilateral& quad)
+{
+	std::swap(quad.p1, quad.p3);
+}
+
+constexpr Quadrilateral inverted(Quadrilateral quad)
+{
+	invert(quad);
+	return quad;
+}
+
+constexpr void invert(Triangle& tri)
+{
+	std::swap(tri.p1, tri.p2);
+}
+
+constexpr Triangle inverted(Triangle tri)
+{
+	invert(tri);
+	return tri;
+}
 
 namespace gl
 {
 	void invert(PolygonElement &polygon);
 }
+
+using gl::invert;
--- a/src/layers/edittools.cpp	Wed Jun 29 14:11:58 2022 +0300
+++ b/src/layers/edittools.cpp	Wed Jun 29 14:43:42 2022 +0300
@@ -24,6 +24,7 @@
 #include "src/gl/partrenderer.h"
 #include "src/circularprimitive.h"
 #include "src/layers/edittools.h"
+#include "src/invert.h"
 
 // Make mapbox::earcut work with glm::vec3
 template<> struct mapbox::util::nth<0, glm::vec3>
@@ -436,24 +437,38 @@
 		polygon2d.reserve(this->numpoints);
 		for (std::size_t i = 0; i < this->numpoints; ++i) {
 			polygon2d.push_back(inverseGrid * glm::vec4{this->polygon[i], 1});
-		}		
+		}
+		// mapbox::earcut will always produce a CCW polygon, so if we're drawing
+		// a CW polygon, we should invert the result afterwards
+		const float shouldInvert = glm::dot(
+			glm::vec3{inverseGrid[2]},
+			glm::cross(this->polygon[0] - this->polygon[1], this->polygon[2] - this->polygon[1]));
 		using indextype = std::uint16_t;
 		const std::vector<indextype> indices = mapbox::earcut<std::uint16_t>(polygons);
 		MergedTriangles mergedTriangles = mergeTriangles(indices, this->polygon);
-		for (const Quadrilateral& quad : mergedTriangles.quadrilaterals) {
+		for (Quadrilateral& quad : mergedTriangles.quadrilaterals) {
+			if (shouldInvert < 0) {
+				invert(quad);
+			}
 			result.push_back(AppendToModel{
 				.newElement = Colored<Quadrilateral>{quad, MAIN_COLOR},
 			});
 		}
 		for (std::size_t i = 0; i < indices.size(); i += 3) {
 			if (mergedTriangles.cutTriangles.find(i) == mergedTriangles.cutTriangles.end()) {
+				Triangle triangle{
+					Triangle{
+						.p1 = this->polygon[indices[i]],
+						.p2 = this->polygon[indices[i + 1]],
+						.p3 = this->polygon[indices[i + 2]],
+					}
+				};
+				if (shouldInvert < 0) {
+					invert(triangle);
+				}
 				result.push_back(AppendToModel{
 					.newElement = Colored<Triangle>{
-						Triangle{
-							.p1 = this->polygon[indices[i]],
-							.p2 = this->polygon[indices[i + 1]],
-							.p3 = this->polygon[indices[i + 2]],
-						},
+						triangle,
 						MAIN_COLOR,
 					}
 				});

mercurial