Unravel Engine C++ Reference
Loading...
Searching...
No Matches
subdivide_mesh.hpp
Go to the documentation of this file.
1#ifndef GENERATOR_SUBDIVIDEMESH_HPP
2#define GENERATOR_SUBDIVIDEMESH_HPP
3
4#include <map>
5#include <vector>
6
7#include "edge.hpp"
8#include "mesh_vertex.hpp"
9#include "triangle.hpp"
10#include "utils.hpp"
11
12namespace generator
13{
14
15template<typename mesh_t, int Iterations>
17{
18 static_assert(Iterations > 0, "Iterations must be greater than zero!");
19
20private:
21 using impl_t = subdivide_mesh_t<subdivide_mesh_t<mesh_t, Iterations - 1>, 1>;
22 impl_t subdivide_mesh_;
23
24public:
25 subdivide_mesh_t(mesh_t mesh) : subdivide_mesh_{subdivide_mesh_t<mesh_t, Iterations - 1>{std::move(mesh)}}
26 {
27 }
28
30
31 triangles_t triangles() const noexcept
32 {
33 return subdivide_mesh_.triangles();
34 }
35
37
38 vertices_t vertices() const noexcept
39 {
40 return subdivide_mesh_.vertices();
41 }
42};
43
44template<typename mesh_t>
45class subdivide_mesh_t<mesh_t, 0>
46{
47private:
48 using impl_t = mesh_t;
49 impl_t mesh_;
50
51public:
52 subdivide_mesh_t(mesh_t mesh) : mesh_{std::move(mesh)}
53 {
54 }
55
56 using triangles_t = typename impl_t::triangles_t;
57
58 triangles_t triangles() const noexcept
59 {
60 return mesh_.triangles();
61 }
62
63 using vertices_t = typename impl_t::vertices_t;
64
65 vertices_t vertices() const noexcept
66 {
67 return mesh_.vertices();
68 }
69};
70
72template<typename mesh_t>
73class subdivide_mesh_t<mesh_t, 1>
74{
75public:
77 {
78 public:
79 bool done() const noexcept
80 {
81 return triangles_.done();
82 }
83
85 {
86 if(i_ == 0)
87 triangle_ = triangles_.generate();
88
89 if(i_ == 3)
90 {
91 return triangle_t{{vertexFromEdge(triangle_.vertices[0], triangle_.vertices[1]),
92 vertexFromEdge(triangle_.vertices[1], triangle_.vertices[2]),
93 vertexFromEdge(triangle_.vertices[2], triangle_.vertices[0])}};
94 }
95
96 int j = (i_ + 1) % 3;
97 int k = (i_ + 2) % 3;
98 return triangle_t{{triangle_.vertices[i_],
99 vertexFromEdge(triangle_.vertices[i_], triangle_.vertices[j]),
100 vertexFromEdge(triangle_.vertices[k], triangle_.vertices[i_])}};
101 }
102
103 void next()
104 {
105 ++i_;
106 if(i_ == 4)
107 {
108 i_ = 0;
109 triangles_.next();
110 }
111 }
112
113 private:
114 const subdivide_mesh_t* mesh_;
115
116 int i_;
117
118 typename triangle_generator_type<mesh_t>::type triangles_;
119
120 mutable triangle_t triangle_;
121
122 explicit triangles_t(const subdivide_mesh_t& mesh)
123 : mesh_{&mesh}
124 , i_{0}
125 , triangles_{mesh.mesh_.triangles()}
126 , triangle_{}
127 {
128 }
129
130 int vertexFromEdge(int a, int b) const
131 {
132 if(a > b)
133 std::swap(a, b);
134 return static_cast<int>(mesh_->vertex_cache_.size()) + mesh_->edge_map_.at({a, b});
135 }
136
137 friend class subdivide_mesh_t;
138 };
139
141 {
142 public:
143 bool done() const noexcept
144 {
145 return vertex_index_ == mesh_->vertex_cache_.size() && edge_index_ == mesh_->edge_cache_.size();
146 }
147
149 {
150 if(vertex_index_ < mesh_->vertex_cache_.size())
151 return mesh_->vertex_cache_[vertex_index_];
152
153 const mesh_vertex_t& v1 = mesh_->vertex_cache_[mesh_->edge_cache_[edge_index_].vertices[0]];
154 const mesh_vertex_t& v2 = mesh_->vertex_cache_[mesh_->edge_cache_[edge_index_].vertices[1]];
155
156 mesh_vertex_t vertex;
157 vertex.position = gml::mix(v1.position, v2.position, 0.5);
158 vertex.tex_coord = gml::mix(v1.tex_coord, v2.tex_coord, 0.5);
159 vertex.normal = gml::normalize(gml::mix(v1.normal, v2.normal, 0.5));
160 return vertex;
161 }
162
163 void next()
164 {
165 if(vertex_index_ < mesh_->vertex_cache_.size())
166 ++vertex_index_;
167 else
168 ++edge_index_;
169 }
170
171 private:
172 const subdivide_mesh_t* mesh_;
173
174 int edge_index_;
175 int vertex_index_;
176
177 explicit vertices_t(const subdivide_mesh_t& mesh) : mesh_{&mesh}, edge_index_{0}, vertex_index_{0}
178 {
179 }
180
181 friend class subdivide_mesh_t;
182 };
183
184 subdivide_mesh_t(mesh_t mesh) : mesh_{std::move(mesh)}
185 {
186 for(const mesh_vertex_t& vertex : mesh_.vertices())
187 {
188 vertex_cache_.push_back(vertex);
189 }
190
191 for(const triangle_t& triangle : mesh_.triangles())
192 {
193 for(int i = 0; i < 3; ++i)
194 {
195 int j = (i + 1) % 3;
196
197 edge_t e{{triangle.vertices[i], triangle.vertices[j]}};
198 if(e.vertices[0] > e.vertices[1])
199 std::swap(e.vertices[0], e.vertices[1]);
200
201 if(edge_map_.find(e.vertices) == edge_map_.end())
202 {
203 edge_map_[e.vertices] = static_cast<int>(edge_cache_.size());
204 edge_cache_.push_back(e);
205 }
206 }
207 }
208 }
209
210 triangles_t triangles() const noexcept
211 {
212 return triangles_t{*this};
213 }
214
215 vertices_t vertices() const noexcept
216 {
217 return vertices_t{*this};
218 }
219
220private:
221 mesh_t mesh_;
222
223 std::vector<edge_t> edge_cache_;
224
225 std::map<gml::ivec2, int> edge_map_;
226
227 std::vector<mesh_vertex_t> vertex_cache_;
228};
229} // namespace generator
230
231#endif
entt::handle b
entt::handle a
gml::dvec2 tex_coord
UV texture coordinates.
gml::dvec3 normal
Unit vector perpendicular to the surface.
typename impl_t::triangles_t triangles_t
triangles_t triangles() const noexcept
typename impl_t::vertices_t vertices_t
triangles_t triangles() const noexcept
typename impl_t::vertices_t vertices_t
vertices_t vertices() const noexcept
typename impl_t::triangles_t triangles_t
triangles_t triangles() const noexcept