src/circularprimitive.h

Fri, 01 Jul 2022 16:46:43 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Fri, 01 Jul 2022 16:46:43 +0300
changeset 312
2637134bc37c
parent 305
d891da20abca
child 379
8d88adffb779
permissions
-rw-r--r--

Fix right click to delete not really working properly
Instead of removing the point that had been added, it would remove
the point that is being drawn, which would cause it to overwrite the
previous point using the new point, causing a bit of a delay

#pragma once
#include <glm/gtc/matrix_transform.hpp>
#include "src/basics.h"
#include "src/model.h"
#include "src/ldrawalgorithm.h"

template<typename Fn>
void rasterize(const CircularPrimitive& circ, Fn&& fn)
{
	std::vector<ModelElement> result;
	const auto xform = [&circ](const glm::vec2& p, float y){
		return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}};
	};
	const glm::vec3 primitiveOrigin = xform({0, 0}, 0);
	const bool invertedMatrix = (glm::determinant(circ.transformation) < 0) != circ.inverted;
	switch(circ.type) {
	case CircularPrimitive::Circle:
		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
			fn(LineSegment{xform(p1, 0), xform(p2, 0)}, EDGE_COLOR);
		});
		break;
	case CircularPrimitive::Disc:
		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
			fn(Triangle{primitiveOrigin, xform(p1, 0), xform(p2, 0)}, MAIN_COLOR);
		});
		break;
	case CircularPrimitive::Cylinder:
		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
			Quadrilateral quad{xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)};
			if (invertedMatrix) {
				std::swap(quad.p2, quad.p4);
			}
			fn(quad, MAIN_COLOR);
		});
		break;
	case CircularPrimitive::CylinderOpen:
		rasterize(CircularPrimitive{
			.type = CircularPrimitive::Cylinder,
			.fraction = circ.fraction,
			.transformation = circ.transformation,
		}, fn);
		rasterize(CircularPrimitive{
			.type = CircularPrimitive::Circle,
			.fraction = circ.fraction,
			.transformation = circ.transformation,
		}, fn);
		rasterize(CircularPrimitive{
			.type = CircularPrimitive::Circle,
			.fraction = circ.fraction,
			.transformation = glm::translate(circ.transformation, {0, 1, 0}),
		}, fn);
		break;
	case CircularPrimitive::CylinderClosed:
		rasterize(CircularPrimitive{
			.type = CircularPrimitive::CylinderOpen,
			.fraction = circ.fraction,
			.transformation = circ.transformation,
		}, fn);
		rasterize(CircularPrimitive{
			.type = CircularPrimitive::Disc,
			.fraction = circ.fraction,
			.transformation = circ.transformation,
		}, fn);
		break;
	case CircularPrimitive::DiscNegative:
		{
			unsigned int i = 0;
			ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
			(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
				constexpr glm::vec2 corners[4] = {
					{+1, +1},
					{-1, +1},
					{-1, -1},
					{+1, -1},
				};
				const glm::vec2& corner = corners[i * 4 / circ.fraction.divisions];
				fn(Triangle{xform(p2, 0), xform(p1, 0), xform(corner, 0)}, MAIN_COLOR);
				++i;
			});
		}
		break;
	case CircularPrimitive::Chord:
		for (unsigned int i = 1; i < circ.fraction.segments; ++i) {
			const glm::vec2& p1 = ldraw::rimpoint(circ.fraction.divisions, i);
			const glm::vec2& p2 = ldraw::rimpoint(circ.fraction.divisions, i + 1);
			fn(Triangle{xform(p2, 0), xform(p1, 0), xform({1, 0}, 0)}, MAIN_COLOR);
		}
		break;
	}
}

mercurial