src/circularprimitive.h

Mon, 20 Jun 2022 16:43:56 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Mon, 20 Jun 2022 16:43:56 +0300
changeset 233
5509bec02c81
parent 232
8efa3a33172e
child 247
07ad61423c3c
permissions
-rw-r--r--

fix various things

#pragma once
#include <glm/gtc/matrix_transform.hpp>
#include "basics.h"
#include "model.h"
#include "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 origin = xform({0, 0}, 0);
	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(edge(xform(p1, 0), xform(p2, 0)));
		});
		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(origin, xform(p1, 0), xform(p2, 0)));
		});
		break;
	case CircularPrimitive::Cylinder:
		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
			fn(quadrilateral(xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)));
		});
		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)));
				++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)));
		}
		break;
	}
}

mercurial