summaryrefslogtreecommitdiff
path: root/assetFactory/cylinder.cpp
blob: cf0dbfb4f3e961291961f8869e58671973439454 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "cylinder.h"
#include "maths.h"
#include "modelFactoryMesh.h"

Cylinder::CreatedFaces
Cylinder::createMesh(ModelFactoryMesh & mesh, const Mutation::Matrix & mutation) const
{
	const glm::vec2 scale {std::accumulate(&mutation[0][0], &mutation[0][3], 0.f),
			std::accumulate(&mutation[1][0], &mutation[1][3], 0.f)};
	const unsigned int P = static_cast<unsigned int>(std::round(15.F * std::sqrt(glm::length(scale))));
	std::vector<OpenMesh::VertexHandle> bottom(P), top(P);
	std::generate_n(bottom.begin(), P, [a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
		const auto xy = sincosf(a += step) * .5F;
		const auto xyz = (xy ^ 0) % mutation;
		return mesh.add_vertex({xyz.x, xyz.y, xyz.z});
	});
	std::generate_n(top.begin(), P, [a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
		const auto xy = sincosf(a -= step) * .5F;
		const auto xyz = (xy ^ 1) % mutation;
		return mesh.add_vertex({xyz.x, xyz.y, xyz.z});
	});
	CreatedFaces surface;
	std::generate_n(std::inserter(surface, surface.end()), P,
			[a = 0.f, step = two_pi / static_cast<float>(P), &mesh, &mutation]() mutable {
				const auto xy1 = sincosf(a) * .5F;
				const auto xy2 = sincosf(a -= step) * .5F;
				const auto xyz1b = (xy1 ^ 0) % mutation;
				const auto xyz2b = (xy2 ^ 0) % mutation;
				const auto xyz1t = (xy1 ^ 1) % mutation;
				const auto xyz2t = (xy2 ^ 1) % mutation;
				return mesh.add_namedFace("edge",
						{
								mesh.add_vertex({xyz1b.x, xyz1b.y, xyz1b.z}),
								mesh.add_vertex({xyz2b.x, xyz2b.y, xyz2b.z}),
								mesh.add_vertex({xyz2t.x, xyz2t.y, xyz2t.z}),
								mesh.add_vertex({xyz1t.x, xyz1t.y, xyz1t.z}),
						});
			});
	for (const auto & [name, face] : surface) {
		mesh.property(mesh.smoothFaceProperty, face) = true;
	}
	surface.insert(mesh.add_namedFace("bottom", bottom));
	surface.insert(mesh.add_namedFace("top", top));

	return surface;
}