CARLA
 
载入中...
搜索中...
未找到
Mesh.cpp
浏览该文件的文档.
1// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include <carla/geom/Mesh.h>
8
9#include <string>
10#include <sstream>
11#include <ios>
12#include <iostream>
13#include <fstream>
14
15#include <carla/geom/Math.h>
16
17namespace carla {
18namespace geom {
19
20 bool Mesh::IsValid() const {
21 // should be at least some one vertex
22 if (_vertices.empty()) {
23 std::cout << "Mesh validation error: there are no vertices in the mesh." << std::endl;
24 return false;
25 }
26
27 // if there are indices, the amount must be multiple of 3
28 if (!_indexes.empty() && _indexes.size() % 3 != 0) {
29 std::cout << "Mesh validation error: the index amount must be multiple of 3." << std::endl;
30 return false;
31 }
32
33 if (!_materials.empty() && _materials.back().index_end == 0) {
34 std::cout << "Mesh validation error: last material was not closed." << std::endl;
35 return false;
36 }
37
38 return true;
39 }
40
41 // e.g:
42 // 1 3 5 7
43 // #---#---#---#
44 // | / | / | / |
45 // #---#---#---#
46 // 2 4 6 8
47 void Mesh::AddTriangleStrip(const std::vector<Mesh::vertex_type> &vertices) {
48 if (vertices.size() == 0) {
49 return;
50 }
51 DEBUG_ASSERT(vertices.size() >= 3);
52 size_t i = GetVerticesNum() + 2;
53 AddVertices(vertices);
54 bool index_clockwise = true;
55 while (i < GetVerticesNum()) {
56 index_clockwise = !index_clockwise;
57 if (index_clockwise) {
58 AddIndex(i + 1);
59 AddIndex(i);
60 AddIndex(i - 1);
61 } else {
62 AddIndex(i - 1);
63 AddIndex(i);
64 AddIndex(i + 1);
65 }
66 ++i;
67 }
68 }
69
70 // e.g:
71 // 2 1 6
72 // #---#---#
73 // | / | \ |
74 // #---#---#
75 // 3 4 5
76 void Mesh::AddTriangleFan(const std::vector<Mesh::vertex_type> &vertices) {
77 DEBUG_ASSERT(vertices.size() >= 3);
78 const size_t initial_index = GetVerticesNum() + 1;
79 size_t i = GetVerticesNum() + 2;
80 AddVertices(vertices);
81 while (i < GetVerticesNum()) {
82 AddIndex(initial_index);
83 AddIndex(i);
84 AddIndex(i + 1);
85 ++i;
86 }
87 }
88
90 _vertices.push_back(vertex);
91 }
92
93 void Mesh::AddVertices(const std::vector<Mesh::vertex_type> &vertices) {
94 std::copy(vertices.begin(), vertices.end(), std::back_inserter(_vertices));
95 }
96
98 _normals.push_back(normal);
99 }
100
102 _indexes.push_back(index);
103 }
104
106 _uvs.push_back(uv);
107 }
108
109 void Mesh::AddUVs(const std::vector<uv_type> & uv) {
110 std::copy(uv.begin(), uv.end(), std::back_inserter(_uvs));
111 }
112
113 void Mesh::AddMaterial(const std::string &material_name) {
114 const size_t open_index = _indexes.size();
115 if (!_materials.empty()) {
116 if (_materials.back().index_end == 0) {
117 // @todo: change this comment to a debug warning
118 // std::cout << "last material was not closed, closing it..." << std::endl;
119 EndMaterial();
120 }
121 }
122 if (open_index % 3 != 0) {
123 std::cout << "open_index % 3 != 0" << std::endl;
124 return;
125 }
126 _materials.emplace_back(material_name, open_index, 0);
127 }
128
130 const size_t close_index = _indexes.size();
131 if (_materials.empty() ||
132 _materials.back().index_start == close_index ||
133 _materials.back().index_end != 0) {
134 // @todo: change this comment to a debug warning
135 // std::cout << "WARNING: Bad end of material. Material not started." << std::endl;
136 return;
137 }
138 if (_indexes.empty() || close_index % 3 != 0) {
139 // @todo: change this comment to a debug warning
140 // std::cout << "WARNING: Bad end of material. Face not started/ended." << std::endl;
141 return;
142 }
143 _materials.back().index_end = close_index;
144 }
145
146 std::string Mesh::GenerateOBJ() const {
147 if (!IsValid()) {
148 return "";
149 }
150 std::stringstream out;
151 out << std::fixed; // Avoid using scientific notation
152
153 out << "# List of geometric vertices, with (x, y, z) coordinates." << std::endl;
154 for (auto &v : _vertices) {
155 out << "v " << v.x << " " << v.y << " " << v.z << std::endl;
156 }
157
158 if (!_uvs.empty()) {
159 out << std::endl << "# List of texture coordinates, in (u, v) coordinates, these will vary between 0 and 1." << std::endl;
160 for (auto &vt : _uvs) {
161 out << "vt " << vt.x << " " << vt.y << std::endl;
162 }
163 }
164
165 if (!_normals.empty()) {
166 out << std::endl << "# List of vertex normals in (x, y, z) form; normals might not be unit vectors." << std::endl;
167 for (auto &vn : _normals) {
168 out << "vn " << vn.x << " " << vn.y << " " << vn.z << std::endl;
169 }
170 }
171
172 if (!_indexes.empty()) {
173 out << std::endl << "# Polygonal face element." << std::endl;
174 auto it_m = _materials.begin();
175 auto it = _indexes.begin();
176 size_t index_counter = 0u;
177 while (it != _indexes.end()) {
178 // While exist materials
179 if (it_m != _materials.end()) {
180 // If the current material ends at this index
181 if (it_m->index_end == index_counter) {
182 ++it_m;
183 }
184 // If the current material start at this index
185 if (it_m->index_start == index_counter) {
186 out << "\nusemtl " << it_m->name << std::endl;
187 }
188 }
189
190 // Add the actual face using the 3 consecutive indices
191 out << "f " << *it; ++it;
192 out << " " << *it; ++it;
193 out << " " << *it << std::endl; ++it;
194
195 index_counter += 3;
196 }
197 }
198
199 return out.str();
200 }
201
202 std::string Mesh::GenerateOBJForRecast() const {
203 if (!IsValid()) {
204 return "";
205 }
206 std::stringstream out;
207 out << std::fixed; // Avoid using scientific notation
208
209 out << "# List of geometric vertices, with (x, y, z) coordinates." << std::endl;
210 for (auto &v : _vertices) {
211 // Switched "y" and "z" for Recast library
212 out << "v " << v.x << " " << v.z << " " << v.y << std::endl;
213 }
214
215 if (!_indexes.empty()) {
216 out << std::endl << "# Polygonal face element." << std::endl;
217 auto it_m = _materials.begin();
218 auto it = _indexes.begin();
219 size_t index_counter = 0u;
220 while (it != _indexes.end()) {
221 // While exist materials
222 if (it_m != _materials.end()) {
223 // If the current material ends at this index
224 if (it_m->index_end == index_counter) {
225 ++it_m;
226 }
227 // If the current material start at this index
228 if (it_m->index_start == index_counter) {
229 out << "\nusemtl " << it_m->name << std::endl;
230 }
231 }
232 // Add the actual face using the 3 consecutive indices
233 // Changes the face build direction to clockwise since
234 // the space has changed.
235 out << "f " << *it; ++it;
236 const auto i_2 = *it; ++it;
237 const auto i_3 = *it; ++it;
238 out << " " << i_3 << " " << i_2 << std::endl;
239 index_counter += 3;
240 }
241 }
242
243 return out.str();
244 }
245
246 std::string Mesh::GeneratePLY() const {
247 if (!IsValid()) {
248 return "Invalid Mesh";
249 }
250 // Generate header
251 std::stringstream out;
252 return out.str();
253 }
254
255 const std::vector<Mesh::vertex_type> &Mesh::GetVertices() const {
256 return _vertices;
257 }
258
259 std::vector<Mesh::vertex_type> &Mesh::GetVertices() {
260 return _vertices;
261 }
262
263 size_t Mesh::GetVerticesNum() const {
264 return _vertices.size();
265 }
266
267 const std::vector<Mesh::normal_type> &Mesh::GetNormals() const {
268 return _normals;
269 }
270
271 const std::vector<Mesh::index_type> &Mesh::GetIndexes() const {
272 return _indexes;
273 }
274
275 std::vector<Mesh::index_type>& Mesh::GetIndexes() {
276 return _indexes;
277 }
278 size_t Mesh::GetIndexesNum() const {
279 return _indexes.size();
280 }
281
282 const std::vector<Mesh::uv_type> &Mesh::GetUVs() const {
283 return _uvs;
284 }
285
286 const std::vector<Mesh::material_type> &Mesh::GetMaterials() const {
287 return _materials;
288 }
289
291 return _vertices.size();
292 }
293
294 Mesh& Mesh::ConcatMesh(const Mesh& rhs, int num_vertices_to_link) {
295
296 if (!rhs.IsValid()){
297 return *this += rhs;
298 }
299 const size_t v_num = GetVerticesNum();
300 const size_t i_num = GetIndexesNum();
301
302 _vertices.insert(
303 _vertices.end(),
304 rhs.GetVertices().begin(),
305 rhs.GetVertices().end());
306
307 _normals.insert(
308 _normals.end(),
309 rhs.GetNormals().begin(),
310 rhs.GetNormals().end());
311
312 const size_t vertex_to_start_concating = v_num - num_vertices_to_link;
313 for( size_t i = 1; i < num_vertices_to_link; ++i ) {
314 _indexes.push_back( vertex_to_start_concating + i );
315 _indexes.push_back( vertex_to_start_concating + i + 1 );
316 _indexes.push_back( v_num + i );
317
318 _indexes.push_back( vertex_to_start_concating + i + 1);
319 _indexes.push_back( v_num + i + 1);
320 _indexes.push_back( v_num + i);
321 }
322
323 std::transform(
324 rhs.GetIndexes().begin(),
325 rhs.GetIndexes().end(),
326 std::back_inserter(_indexes),
327 [=](size_t index) {return index + v_num; });
328
329 _uvs.insert(
330 _uvs.end(),
331 rhs.GetUVs().begin(),
332 rhs.GetUVs().end());
333
334 std::transform(
335 rhs.GetMaterials().begin(),
336 rhs.GetMaterials().end(),
337 std::back_inserter(_materials),
338 [=](MeshMaterial mat) {
339 mat.index_start += i_num;
340 mat.index_end += i_num;
341 return mat;
342 });
343
344 return *this;
345 }
346
348 const size_t v_num = GetVerticesNum();
349 const size_t i_num = GetIndexesNum();
350
351 _vertices.insert(
352 _vertices.end(),
353 rhs.GetVertices().begin(),
354 rhs.GetVertices().end());
355
356 _normals.insert(
357 _normals.end(),
358 rhs.GetNormals().begin(),
359 rhs.GetNormals().end());
360
361 std::transform(
362 rhs.GetIndexes().begin(),
363 rhs.GetIndexes().end(),
364 std::back_inserter(_indexes),
365 [=](size_t index) {return index + v_num;});
366
367 _uvs.insert(
368 _uvs.end(),
369 rhs.GetUVs().begin(),
370 rhs.GetUVs().end());
371
372 std::transform(
373 rhs.GetMaterials().begin(),
374 rhs.GetMaterials().end(),
375 std::back_inserter(_materials),
376 [=](MeshMaterial mat) {
377 mat.index_start += i_num;
378 mat.index_end += i_num;
379 return mat;
380 });
381
382 return *this;
383 }
384
385 Mesh operator+(const Mesh &lhs, const Mesh &rhs) {
386 Mesh m = lhs;
387 return m += rhs;
388 }
389
390} // namespace geom
391} // namespace carla
#define DEBUG_ASSERT(predicate)
Definition Debug.h:66
Mesh data container, validator and exporter.
Definition Mesh.h:44
void AddIndex(index_type index)
Appends a index to the indexes list.
Definition Mesh.cpp:101
void AddVertex(vertex_type vertex)
Appends a vertex to the vertices list.
Definition Mesh.cpp:89
std::vector< vertex_type > _vertices
Definition Mesh.h:235
void AddVertices(const std::vector< vertex_type > &vertices)
Appends a vertex to the vertices list.
Definition Mesh.cpp:93
std::string GenerateOBJ() const
Returns a string containing the mesh encoded in OBJ.
Definition Mesh.cpp:146
void AddUV(uv_type uv)
Appends a vertex to the vertices list, they will be read 3 in 3.
Definition Mesh.cpp:105
Mesh & ConcatMesh(const Mesh &rhs, int num_vertices_to_link)
Merges two meshes into a single mesh
Definition Mesh.cpp:294
std::vector< index_type > _indexes
Definition Mesh.h:239
const std::vector< uv_type > & GetUVs() const
Definition Mesh.cpp:282
const std::vector< index_type > & GetIndexes() const
Definition Mesh.cpp:271
std::string GeneratePLY() const
Returns a string containing the mesh encoded in PLY.
Definition Mesh.cpp:246
bool IsValid() const
Check if the mesh can be valid or not.
Definition Mesh.cpp:20
void AddUVs(const std::vector< uv_type > &uv)
Appends uvs.
Definition Mesh.cpp:109
std::string GenerateOBJForRecast() const
Returns a string containing the mesh encoded in OBJ.
Definition Mesh.cpp:202
size_t GetVerticesNum() const
Definition Mesh.cpp:263
void AddNormal(normal_type normal)
Appends a normal to the normal list.
Definition Mesh.cpp:97
std::vector< normal_type > _normals
Definition Mesh.h:237
std::vector< material_type > _materials
Definition Mesh.h:243
void AddMaterial(const std::string &material_name)
Starts applying a new material to the new added triangles.
Definition Mesh.cpp:113
void EndMaterial()
Stops applying the material to the new added triangles.
Definition Mesh.cpp:129
size_t index_type
Definition Mesh.h:49
Mesh & operator+=(const Mesh &rhs)
Merges two meshes into a single mesh
Definition Mesh.cpp:347
const std::vector< material_type > & GetMaterials() const
Definition Mesh.cpp:286
const std::vector< normal_type > & GetNormals() const
Definition Mesh.cpp:267
size_t GetLastVertexIndex() const
Returns the index of the last added vertex (number of vertices).
Definition Mesh.cpp:290
void AddTriangleFan(const std::vector< vertex_type > &vertices)
Adds a triangle fan to the mesh, vertex order is counterclockwise.
Definition Mesh.cpp:76
std::vector< uv_type > _uvs
Definition Mesh.h:241
size_t GetIndexesNum() const
Definition Mesh.cpp:278
void AddTriangleStrip(const std::vector< vertex_type > &vertices)
Adds a triangle strip to the mesh, vertex order is counterclockwise.
Definition Mesh.cpp:47
const std::vector< vertex_type > & GetVertices() const
Definition Mesh.cpp:255
Mesh operator+(const Mesh &lhs, const Mesh &rhs)
Definition Mesh.cpp:385
This file contains definitions of common data structures used in traffic manager.
Definition Carla.cpp:133
Material that references the vertex index start and end of a mesh where it is affecting.
Definition Mesh.h:25