summaryrefslogtreecommitdiff
path: root/assetFactory/cylinder.cpp
blob: 0803369f7295655ca8acb92788c811f48e56e01d (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
47
48
49
50
51
52
53
#include "cylinder.h"
#include "maths.h"
#include "modelFactoryMesh.h"

Cylinder::CreatedFaces
Cylinder::createMesh(ModelFactoryMesh & mesh, float lodf) const
{
	const auto P = static_cast<unsigned int>(std::round(15.F * std::sqrt(lodf)));
	const auto step = two_pi / static_cast<float>(P);

	// Generate 2D circumference points
	std::vector<glm::vec2> circumference(P);
	std::generate(circumference.begin(), circumference.end(), [a = 0.f, step]() mutable {
		return sincosf(a += step) * .5F;
	});

	CreatedFaces surface;
	{
		// Generate bottom face vertices
		std::vector<OpenMesh::VertexHandle> bottom(P);
		std::transform(circumference.begin(), circumference.end(), bottom.begin(), [&mesh](const auto & xy) {
			return mesh.add_vertex({xy.x, xy.y, 0.f});
		});
		surface.insert(mesh.add_namedFace("bottom", bottom));
	}
	{
		// Generate top face vertices
		std::vector<OpenMesh::VertexHandle> top(P);
		std::transform(circumference.rbegin(), circumference.rend(), top.begin(), [&mesh](const auto & xy) {
			return mesh.add_vertex({xy.x, xy.y, 1.f});
		});
		surface.insert(mesh.add_namedFace("top", top));
	}
	{
		// Generate edge vertices
		std::vector<std::pair<OpenMesh::VertexHandle, OpenMesh::VertexHandle>> edge(P + 1);
		std::transform(circumference.begin(), circumference.end(), edge.begin(), [&mesh](const auto & xy) {
			return std::make_pair(mesh.add_vertex({xy.x, xy.y, 0.f}), mesh.add_vertex({xy.x, xy.y, 1.f}));
		});
		// Wrap around
		edge.back() = edge.front();
		// Transform adjacent pairs of top/bottom pairs to faces
		std::adjacent_find(edge.begin(), edge.end(), [&mesh, &surface](const auto & first, const auto & second) {
			const auto fh
					= surface.insert(mesh.add_namedFace("edge", first.first, first.second, second.second, second.first))
							  ->second;
			mesh.property(mesh.smoothFaceProperty, fh) = true;
			return false;
		});
	}

	return surface;
}