Unravel Engine C++ Reference
Loading...
Searching...
No Matches
convex_polygon_mesh.cpp
Go to the documentation of this file.
2
3#include "circle_shape.hpp"
4#include "iterator.hpp"
5
6using namespace generator;
7
8convex_polygon_mesh_t::triangles_t::triangles_t(const convex_polygon_mesh_t& mesh) noexcept
9 : mesh_{&mesh}
10 , odd_{false}
11 , segment_index_{0}
12 , side_index_{0}
13 , ring_index_{0}
14{
15}
16
17bool convex_polygon_mesh_t::triangles_t::done() const noexcept
18{
19 return mesh_->segments_ == 0 || mesh_->vertices_.size() < 3 || ring_index_ == mesh_->rings_;
20}
21
22triangle_t convex_polygon_mesh_t::triangles_t::generate() const
23{
24 if(done())
25 throw std::runtime_error("Done!");
26
27 triangle_t triangle{};
28
29 const int verticesPerRing = mesh_->segments_ * int(mesh_->vertices_.size());
30 const int delta = ring_index_ * verticesPerRing + 1;
31
32 const int n1 = side_index_ * mesh_->segments_ + segment_index_;
33 const int n2 = (n1 + 1) % verticesPerRing;
34
35 if(ring_index_ == mesh_->rings_ - 1)
36 {
37 triangle.vertices[0] = 0;
38 triangle.vertices[1] = n1 + delta;
39 triangle.vertices[2] = n2 + delta;
40 }
41 else
42 {
43 if(!odd_)
44 {
45 triangle.vertices[0] = n1 + delta;
46 triangle.vertices[1] = n2 + delta;
47 triangle.vertices[2] = n1 + verticesPerRing + delta;
48 }
49 else
50 {
51 triangle.vertices[0] = n2 + delta;
52 triangle.vertices[1] = n2 + verticesPerRing + delta;
53 triangle.vertices[2] = n1 + verticesPerRing + delta;
54 }
55 }
56
57 return triangle;
58}
59
60void convex_polygon_mesh_t::triangles_t::next()
61{
62 if(done())
63 throw std::runtime_error("Done!");
64
65 if(ring_index_ == mesh_->rings_ - 1)
66 {
67 ++segment_index_;
68
69 if(segment_index_ == mesh_->segments_)
70 {
71 segment_index_ = 0;
72
73 ++side_index_;
74
75 if(side_index_ == static_cast<int>(mesh_->vertices_.size()))
76 {
77 ++ring_index_;
78 }
79 }
80 }
81 else
82 {
83 odd_ = !odd_;
84
85 if(!odd_)
86 {
87 ++segment_index_;
88
89 if(segment_index_ == mesh_->segments_)
90 {
91 segment_index_ = 0;
92
93 ++side_index_;
94
95 if(side_index_ == static_cast<int>(mesh_->vertices_.size()))
96 {
97 side_index_ = 0;
98 odd_ = false;
99
100 ++ring_index_;
101 }
102 }
103 }
104 }
105}
106
107convex_polygon_mesh_t::vertices_t::vertices_t(const convex_polygon_mesh_t& mesh) noexcept
108 : mesh_{&mesh}
109 , center_done_{false}
110 , segment_index_{0}
111 , side_index_{0}
112 , ring_index_{0}
113{
114}
115
116bool convex_polygon_mesh_t::vertices_t::done() const noexcept
117{
118 return mesh_->segments_ == 0 || mesh_->rings_ == 0 || mesh_->vertices_.size() < 3 || ring_index_ == mesh_->rings_;
119}
120
121mesh_vertex_t convex_polygon_mesh_t::vertices_t::generate() const
122{
123 if(done())
124 throw std::runtime_error("Done!");
125
126 mesh_vertex_t vertex{};
127
128 if(center_done_)
129 {
130 const double ringDelta = static_cast<double>(ring_index_) / mesh_->rings_;
131 const double segmentDelta = static_cast<double>(segment_index_) / mesh_->segments_;
132
133 const int nextSide = (side_index_ + 1) % mesh_->vertices_.size();
134 const gml::dvec3 a = gml::mix(mesh_->vertices_.at(side_index_), mesh_->center_, ringDelta);
135 const gml::dvec3 b = gml::mix(mesh_->vertices_.at(nextSide), mesh_->center_, ringDelta);
136
137 vertex.position = gml::mix(a, b, segmentDelta);
138 }
139 else
140 {
141 vertex.position = mesh_->center_;
142 }
143
144 vertex.normal = mesh_->normal_;
145
146 const gml::dvec3 delta = vertex.position - mesh_->center_;
147
148 vertex.tex_coord[0] = gml::dot(mesh_->tangent_, delta);
149 vertex.tex_coord[1] = gml::dot(mesh_->bitangent_, delta);
150
151 vertex.tex_coord -= mesh_->tex_delta_;
152
153 return vertex;
154}
155
156void convex_polygon_mesh_t::vertices_t::next()
157{
158 if(done())
159 throw std::runtime_error("Done!");
160
161 if(!center_done_)
162 {
163 center_done_ = true;
164 }
165 else
166 {
167 ++segment_index_;
168
169 if(segment_index_ == mesh_->segments_)
170 {
171 segment_index_ = 0;
172
173 ++side_index_;
174
175 if(side_index_ == static_cast<int>(mesh_->vertices_.size()))
176 {
177 side_index_ = 0;
178
179 ++ring_index_;
180 }
181 }
182 }
183}
184
185namespace
186{
187
188std::vector<gml::dvec3> makevertices_t(double radius, int sides) noexcept
189{
190 std::vector<gml::dvec3> result{};
191
192 circle_shape_t circle{radius, sides};
193 for(const auto& v : circle.vertices())
194 {
195 result.push_back(gml::dvec3{v.position[0], v.position[1], 0.0});
196 }
197 result.pop_back(); // The last one is a dublicate with the first one
198
199 return result;
200}
201
202std::vector<gml::dvec3> convertvertices_t(const std::vector<gml::dvec2>& vertices) noexcept
203{
204 std::vector<gml::dvec3> result(vertices.size());
205
206 for(std::size_t i = 0; i < vertices.size(); ++i)
207 {
208 result.at(i) = gml::dvec3{vertices.at(i)[0], vertices.at(i)[1], 0.0};
209 }
210
211 return result;
212}
213
214gml::dvec3 calcCenter(const std::vector<gml::dvec3>& vertices) noexcept
215{
216 gml::dvec3 result{};
217 for(const auto& v : vertices)
218 {
219 result += v;
220 }
221 return result / static_cast<double>(vertices.size());
222}
223
224gml::dvec3 calcNormal(const gml::dvec3& center, const std::vector<gml::dvec3>& vertices)
225{
226 gml::dvec3 normal{};
227 for(int i = 0; i < static_cast<int>(vertices.size()); ++i)
228 {
229 normal += gml::normal(center, vertices[i], vertices[(i + 1) % vertices.size()]);
230 }
231 return gml::normalize(normal);
232}
233} // namespace
234
235convex_polygon_mesh_t::convex_polygon_mesh_t(double radius, int sides, int segments, int rings) noexcept
236 : convex_polygon_mesh_t{makevertices_t(radius, sides), segments, rings}
237{
238}
239
240convex_polygon_mesh_t::convex_polygon_mesh_t(const std::vector<gml::dvec2>& vertices, int segments, int rings) noexcept
241 : convex_polygon_mesh_t{convertvertices_t(vertices), segments, rings}
242{
243}
244
245convex_polygon_mesh_t::convex_polygon_mesh_t(std::vector<gml::dvec3> vertices, int segments, int rings) noexcept
246 : vertices_{std::move(vertices)}
247 , segments_{segments}
248 , rings_{rings}
249 , center_{calcCenter(vertices_)}
250 , normal_{calcNormal(center_, vertices_)}
251 , tangent_{}
252 , bitangent_{}
253 , tex_delta_{}
254{
255 if(vertices_.size() > 0)
256 {
257 tangent_ = gml::normalize(vertices_.at(0) - center_);
258 bitangent_ = gml::cross(normal_, tangent_);
259
260 gml::dvec2 texMax{};
261
262 for(const gml::dvec3& vertex : vertices_)
263 {
264 gml::dvec3 delta = vertex - center_;
265
266 gml::dvec2 uv{gml::dot(tangent_, delta), gml::dot(bitangent_, delta)};
267
268 tex_delta_ = gml::min(tex_delta_, uv);
269 texMax = gml::max(texMax, uv);
270 }
271
272 gml::dvec2 size = texMax - tex_delta_;
273
274 tangent_ /= size[0];
275 bitangent_ /= size[1];
276
277 tex_delta_ /= size;
278 }
279}
280
281convex_polygon_mesh_t::triangles_t convex_polygon_mesh_t::triangles() const noexcept
282{
283 return triangles_t{*this};
284}
285
286convex_polygon_mesh_t::vertices_t convex_polygon_mesh_t::vertices() const noexcept
287{
288 return vertices_t{*this};
289}
entt::handle b
btVector3 normal
entt::handle a
vertices_t vertices() const noexcept
convex_polygon_mesh_t(double radius=1.0, int sides=5, int segments=4, int rings=4) noexcept
triangles_t triangles() const noexcept
gml::dvec3 normal
Unit vector perpendicular to the surface.
glm::tvec3< T > normal(const glm::tvec3< T > &p1, const glm::tvec3< T > &p2, const glm::tvec3< T > &p3)
Definition math.hpp:131
glm::tvec2< T > cross(const glm::tvec2< T > &v)
Definition math.hpp:108
const segment_list * segments