mesh_operations.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Ioan Sucan */
36 
39 
40 #include <cstdio>
41 #include <cmath>
42 #include <algorithm>
43 #include <set>
44 #include <float.h>
45 
46 #include <console_bridge/console.h>
48 
49 #include <assimp/scene.h>
50 #include <assimp/Importer.hpp>
51 #include <assimp/postprocess.h>
52 
53 #include <Eigen/Geometry>
54 
55 #include <boost/math/constants/constants.hpp>
56 
57 namespace shapes
58 {
59 
60 namespace detail
61 {
62 
63 namespace
64 {
65 
67 struct LocalVertexType
68 {
69  LocalVertexType() : x(0.0), y(0.0), z(0.0)
70  {
71  }
72 
73  LocalVertexType(const Eigen::Vector3d &v) : x(v.x()), y(v.y()), z(v.z())
74  {
75  }
76 
77  double x,y,z;
78  unsigned int index;
79 };
80 
82 struct ltLocalVertexValue
83 {
84  bool operator()(const LocalVertexType &p1, const LocalVertexType &p2) const
85  {
86  if (p1.x < p2.x)
87  return true;
88  if (p1.x > p2.x)
89  return false;
90  if (p1.y < p2.y)
91  return true;
92  if (p1.y > p2.y)
93  return false;
94  if (p1.z < p2.z)
95  return true;
96  return false;
97  }
98 };
99 
101 struct ltLocalVertexIndex
102 {
103  bool operator()(const LocalVertexType &p1, const LocalVertexType &p2) const
104  {
105  return p1.index < p2.index;
106  }
107 };
108 
109 }
110 }
111 
112 Mesh* createMeshFromVertices(const EigenSTL::vector_Vector3d &vertices, const std::vector<unsigned int> &triangles)
113 {
114  unsigned int nt = triangles.size() / 3;
115  Mesh *mesh = new Mesh(vertices.size(), nt);
116  for (unsigned int i = 0 ; i < vertices.size() ; ++i)
117  {
118  mesh->vertices[3 * i ] = vertices[i].x();
119  mesh->vertices[3 * i + 1] = vertices[i].y();
120  mesh->vertices[3 * i + 2] = vertices[i].z();
121  }
122 
123  std::copy(triangles.begin(), triangles.end(), mesh->triangles);
124  mesh->computeTriangleNormals();
125  mesh->computeVertexNormals();
126 
127  return mesh;
128 }
129 
131 {
132  if (source.size() < 3)
133  return NULL;
134 
135  if (source.size() % 3 != 0)
136  CONSOLE_BRIDGE_logError("The number of vertices to construct a mesh from is not divisible by 3. Probably constructed triangles will not make sense.");
137 
138  std::set<detail::LocalVertexType, detail::ltLocalVertexValue> vertices;
139  std::vector<unsigned int> triangles;
140 
141  unsigned int n = source.size() / 3;
142  for (unsigned int i = 0 ; i < n ; ++i)
143  {
144  // check if we have new vertices
145  unsigned int i3 = i * 3;
146  detail::LocalVertexType vt1(source[i3]);
147  std::set<detail::LocalVertexType, detail::ltLocalVertexValue>::iterator p1 = vertices.find(vt1);
148  if (p1 == vertices.end())
149  {
150  vt1.index = vertices.size();
151  vertices.insert(vt1);
152  }
153  else
154  vt1.index = p1->index;
155  triangles.push_back(vt1.index);
156 
157  detail::LocalVertexType vt2(source[++i3]);
158  std::set<detail::LocalVertexType, detail::ltLocalVertexValue>::iterator p2 = vertices.find(vt2);
159  if (p2 == vertices.end())
160  {
161  vt2.index = vertices.size();
162  vertices.insert(vt2);
163  }
164  else
165  vt2.index = p2->index;
166  triangles.push_back(vt2.index);
167 
168  detail::LocalVertexType vt3(source[++i3]);
169  std::set<detail::LocalVertexType, detail::ltLocalVertexValue>::iterator p3 = vertices.find(vt3);
170  if (p3 == vertices.end())
171  {
172  vt3.index = vertices.size();
173  vertices.insert(vt3);
174  }
175  else
176  vt3.index = p3->index;
177 
178  triangles.push_back(vt3.index);
179  }
180 
181  // sort our vertices
182  std::vector<detail::LocalVertexType> vt;
183  vt.insert(vt.end(), vertices.begin(), vertices.end());
184  std::sort(vt.begin(), vt.end(), detail::ltLocalVertexIndex());
185 
186  // copy the data to a mesh structure
187  unsigned int nt = triangles.size() / 3;
188 
189  Mesh *mesh = new Mesh(vt.size(), nt);
190  for (unsigned int i = 0 ; i < vt.size() ; ++i)
191  {
192  unsigned int i3 = i * 3;
193  mesh->vertices[i3 ] = vt[i].x;
194  mesh->vertices[i3 + 1] = vt[i].y;
195  mesh->vertices[i3 + 2] = vt[i].z;
196  }
197 
198  std::copy(triangles.begin(), triangles.end(), mesh->triangles);
199  mesh->computeTriangleNormals();
200  mesh->computeVertexNormals();
201 
202  return mesh;
203 }
204 
205 Mesh* createMeshFromResource(const std::string& resource)
206 {
207  static const Eigen::Vector3d one(1.0, 1.0, 1.0);
208  return createMeshFromResource(resource, one);
209 }
210 
211 Mesh* createMeshFromBinary(const char* buffer, std::size_t size,
212  const std::string &assimp_hint)
213 {
214  static const Eigen::Vector3d one(1.0, 1.0, 1.0);
215  return createMeshFromBinary(buffer, size, one, assimp_hint);
216 }
217 
218 Mesh* createMeshFromBinary(const char *buffer, std::size_t size, const Eigen::Vector3d &scale,
219  const std::string &assimp_hint)
220 {
221  if (!buffer || size < 1)
222  {
223  CONSOLE_BRIDGE_logWarn("Cannot construct mesh from empty binary buffer");
224  return NULL;
225  }
226 
227  // try to get a file extension
228  std::string hint;
229  std::size_t pos = assimp_hint.find_last_of(".");
230  if (pos != std::string::npos)
231  {
232  hint = assimp_hint.substr(pos + 1);
233  std::transform(hint.begin(), hint.end(), hint.begin(), ::tolower);
234  }
235  if (hint.empty())
236  hint = assimp_hint; // send entire file name as hint if no extension was found
237 
238  // Create an instance of the Importer class
239  Assimp::Importer importer;
240 
241  // Issue #38 fix: as part of the post-processing, we remove all other components in file but
242  // the meshes, as anyway the resulting shapes:Mesh object just receives vertices and triangles.
243  importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,
244  aiComponent_NORMALS |
245  aiComponent_TANGENTS_AND_BITANGENTS |
246  aiComponent_COLORS |
247  aiComponent_TEXCOORDS |
248  aiComponent_BONEWEIGHTS |
249  aiComponent_ANIMATIONS |
250  aiComponent_TEXTURES |
251  aiComponent_LIGHTS |
252  aiComponent_CAMERAS |
253  aiComponent_MATERIALS);
254 
255  // And have it read the given file with some post-processing
256  const aiScene* scene = importer.ReadFileFromMemory(reinterpret_cast<const void*>(buffer), size,
257  aiProcess_Triangulate |
258  aiProcess_JoinIdenticalVertices |
259  aiProcess_SortByPType |
260  aiProcess_RemoveComponent, hint.c_str());
261  if (!scene)
262  return NULL;
263 
264  // Assimp enforces Y_UP convention by rotating models with different conventions.
265  // However, that behaviour is confusing and doesn't match the ROS convention
266  // where the Z axis is pointing up.
267  // Hopefully this doesn't undo legit use of the root node transformation...
268  // Note that this is also what RViz does internally.
269  scene->mRootNode->mTransformation = aiMatrix4x4();
270 
271  // These post processing steps flatten the root node transformation into child nodes,
272  // so they must be delayed until after clearing the root node transform above.
273  importer.ApplyPostProcessing(aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph);
274 
275  return createMeshFromAsset(scene, scale, hint);
276 }
277 
278 Mesh* createMeshFromResource(const std::string& resource, const Eigen::Vector3d &scale)
279 {
282  try
283  {
284  res = retriever.get(resource);
285  }
287  {
288  CONSOLE_BRIDGE_logError("%s", e.what());
289  return NULL;
290  }
291 
292  if (res.size == 0)
293  {
294  CONSOLE_BRIDGE_logWarn("Retrieved empty mesh for resource '%s'", resource.c_str());
295  return NULL;
296  }
297 
298  Mesh *m = createMeshFromBinary(reinterpret_cast<const char*>(res.data.get()), res.size, scale, resource);
299  if (!m)
300  {
301  CONSOLE_BRIDGE_logWarn("Assimp reports no scene in %s.", resource.c_str());
302  CONSOLE_BRIDGE_logWarn("This could be because of a resource filename that is too long for the Assimp library, a known bug. As a workaround shorten the filename/path.");
303  }
304  return m;
305 }
306 
307 namespace
308 {
309 void extractMeshData(const aiScene *scene, const aiNode *node, const aiMatrix4x4 &parent_transform, const Eigen::Vector3d &scale,
310  EigenSTL::vector_Vector3d &vertices, std::vector<unsigned int> &triangles)
311 {
312  aiMatrix4x4 transform = parent_transform;
313  transform *= node->mTransformation;
314  for (unsigned int j = 0 ; j < node->mNumMeshes; ++j)
315  {
316  const aiMesh* a = scene->mMeshes[node->mMeshes[j]];
317  unsigned int offset = vertices.size();
318  for (unsigned int i = 0 ; i < a->mNumVertices ; ++i)
319  {
320  aiVector3D v = transform * a->mVertices[i];
321  vertices.push_back(Eigen::Vector3d(v.x * scale.x(), v.y * scale.y(), v.z * scale.z()));
322  }
323  for (unsigned int i = 0 ; i < a->mNumFaces ; ++i)
324  if (a->mFaces[i].mNumIndices == 3)
325  {
326  triangles.push_back(offset + a->mFaces[i].mIndices[0]);
327  triangles.push_back(offset + a->mFaces[i].mIndices[1]);
328  triangles.push_back(offset + a->mFaces[i].mIndices[2]);
329  }
330  }
331 
332  for (unsigned int n = 0; n < node->mNumChildren; ++n)
333  extractMeshData(scene, node->mChildren[n], transform, scale, vertices, triangles);
334 }
335 }
336 
337 Mesh* createMeshFromAsset(const aiScene* scene, const std::string &resource_name)
338 {
339  static const Eigen::Vector3d one(1.0, 1.0, 1.0);
340  return createMeshFromAsset(scene, one, resource_name);
341 }
342 
343 Mesh* createMeshFromAsset(const aiScene* scene, const Eigen::Vector3d &scale, const std::string &resource_name)
344 {
345  if (!scene->HasMeshes())
346  {
347  CONSOLE_BRIDGE_logWarn("Assimp reports scene in %s has no meshes", resource_name.c_str());
348  return NULL;
349  }
350  EigenSTL::vector_Vector3d vertices;
351  std::vector<unsigned int> triangles;
352  extractMeshData(scene, scene->mRootNode, aiMatrix4x4(), scale, vertices, triangles);
353  if (vertices.empty())
354  {
355  CONSOLE_BRIDGE_logWarn("There are no vertices in the scene %s", resource_name.c_str());
356  return NULL;
357  }
358  if (triangles.empty())
359  {
360  CONSOLE_BRIDGE_logWarn("There are no triangles in the scene %s", resource_name.c_str());
361  return NULL;
362  }
363 
364  return createMeshFromVertices(vertices, triangles);
365 }
366 
368 {
369  if (shape->type == shapes::SPHERE)
370  return shapes::createMeshFromShape(static_cast<const shapes::Sphere&>(*shape));
371  else
372  if (shape->type == shapes::BOX)
373  return shapes::createMeshFromShape(static_cast<const shapes::Box&>(*shape));
374  else
375  if (shape->type == shapes::CYLINDER)
376  return shapes::createMeshFromShape(static_cast<const shapes::Cylinder&>(*shape));
377  else
378  if (shape->type == shapes::CONE)
379  return shapes::createMeshFromShape(static_cast<const shapes::Cone&>(*shape));
380  else
381  CONSOLE_BRIDGE_logError("Conversion of shape of type '%s' to a mesh is not known", shapeStringName(shape).c_str());
382  return NULL;
383 }
384 
386 {
387  double x = box.size[0] / 2.0;
388  double y = box.size[1] / 2.0;
389  double z = box.size[2] / 2.0;
390 
391  // define vertices of box mesh
392  Mesh *result = new Mesh(8, 12);
393  result->vertices[0] = -x;
394  result->vertices[1] = -y;
395  result->vertices[2] = -z;
396 
397  result->vertices[3] = x;
398  result->vertices[4] = -y;
399  result->vertices[5] = -z;
400 
401  result->vertices[6] = x;
402  result->vertices[7] = -y;
403  result->vertices[8] = z;
404 
405  result->vertices[9] = -x;
406  result->vertices[10] = -y;
407  result->vertices[11] = z;
408 
409  result->vertices[12] = -x;
410  result->vertices[13] = y;
411  result->vertices[14] = z;
412 
413  result->vertices[15] = -x;
414  result->vertices[16] = y;
415  result->vertices[17] = -z;
416 
417  result->vertices[18] = x;
418  result->vertices[19] = y;
419  result->vertices[20] = z;
420 
421  result->vertices[21] = x;
422  result->vertices[22] = y;
423  result->vertices[23] = -z;
424 
425  static const unsigned int tri[] = {0, 1, 2,
426  2, 3, 0,
427  4, 3, 2,
428  2, 6, 4,
429  7, 6, 2,
430  2, 1, 7,
431  3, 4, 5,
432  5, 0, 3,
433  0, 5, 7,
434  7, 1, 0,
435  7, 5, 4,
436  4, 6, 7};
437  memcpy(result->triangles, tri, sizeof(unsigned int) * 36);
438  result->computeTriangleNormals();
439  result->computeVertexNormals();
440  return result;
441 }
442 
444 {
445  // this code is adapted from FCL
446  EigenSTL::vector_Vector3d vertices;
447  std::vector<unsigned int> triangles;
448 
449  const double r = sphere.radius;
450  const double pi = boost::math::constants::pi<double>();
451  const unsigned int seg = std::max<unsigned int>(6, 0.5 + 2.0 * pi * r / 0.01); // split the sphere longitudinally up to a resolution of 1 cm at the ecuator, or a minimum of 6 segments
452  const unsigned int ring = std::max<unsigned int>(6, 2.0 * r / 0.01); // split the sphere into rings along latitude, up to a height of at most 1 cm, or a minimum of 6 rings
453 
454  double phi, phid;
455  phid = pi * 2.0 / seg;
456  phi = 0.0;
457 
458  double theta, thetad;
459  thetad = pi / (ring + 1);
460  theta = 0;
461 
462  for (unsigned int i = 0; i < ring; ++i)
463  {
464  double theta_ = theta + thetad * (i + 1);
465  for (unsigned int j = 0; j < seg; ++j)
466  vertices.push_back(Eigen::Vector3d(r * sin(theta_) * cos(phi + j * phid),
467  r * sin(theta_) * sin(phi + j * phid),
468  r * cos(theta_)));
469  }
470  vertices.push_back(Eigen::Vector3d(0.0, 0.0, r));
471  vertices.push_back(Eigen::Vector3d(0.0, 0.0, -r));
472 
473  for (unsigned int i = 0 ; i < ring - 1; ++i)
474  {
475  for (unsigned int j = 0 ; j < seg ; ++j)
476  {
477  unsigned int a, b, c, d;
478  a = i * seg + j;
479  b = (j == seg - 1) ? (i * seg) : (i * seg + j + 1);
480  c = (i + 1) * seg + j;
481  d = (j == seg - 1) ? ((i + 1) * seg) : ((i + 1) * seg + j + 1);
482  triangles.push_back(a);
483  triangles.push_back(c);
484  triangles.push_back(b);
485  triangles.push_back(b);
486  triangles.push_back(c);
487  triangles.push_back(d);
488  }
489  }
490 
491  for (unsigned int j = 0 ; j < seg ; ++j)
492  {
493  unsigned int a, b;
494  a = j;
495  b = (j == seg - 1) ? 0 : (j + 1);
496  triangles.push_back(ring * seg);
497  triangles.push_back(a);
498  triangles.push_back(b);
499 
500  a = (ring - 1) * seg + j;
501  b = (j == seg - 1) ? (ring - 1) * seg : ((ring - 1) * seg + j + 1);
502  triangles.push_back(a);
503  triangles.push_back(ring * seg + 1);
504  triangles.push_back(b);
505  }
506  return createMeshFromVertices(vertices, triangles);
507 }
508 
510 {
511  // this code is adapted from FCL
512  EigenSTL::vector_Vector3d vertices;
513  std::vector<unsigned int> triangles;
514 
515  // magic number defining how many triangles to construct for the unit cylinder; perhaps this should be a param
516  static unsigned int tot_for_unit_cylinder = 100;
517 
518  double r = cylinder.radius;
519  double h = cylinder.length;
520 
521  const double pi = boost::math::constants::pi<double>();
522  unsigned int tot = ceil(tot_for_unit_cylinder * r);
523  double phid = pi * 2 / tot;
524 
525  double circle_edge = phid * r;
526  unsigned int h_num = ceil(h / circle_edge);
527 
528  double phi = 0;
529  double hd = h / h_num;
530 
531  for (unsigned int i = 0 ; i < tot ; ++i)
532  vertices.push_back(Eigen::Vector3d(r * cos(phi + phid * i), r * sin(phi + phid * i), h / 2));
533 
534  for (unsigned int i = 0; i < h_num - 1 ; ++i)
535  for(unsigned int j = 0; j < tot; ++j)
536  vertices.push_back(Eigen::Vector3d(r * cos(phi + phid * j), r * sin(phi + phid * j), h / 2 - (i + 1) * hd));
537 
538  for (unsigned int i = 0; i < tot; ++i)
539  vertices.push_back(Eigen::Vector3d(r * cos(phi + phid * i), r * sin(phi + phid * i), - h / 2));
540 
541  vertices.push_back(Eigen::Vector3d(0, 0, h / 2));
542  vertices.push_back(Eigen::Vector3d(0, 0, -h / 2));
543 
544  for (unsigned int i = 0; i < tot ; ++i)
545  {
546  triangles.push_back((h_num + 1) * tot);
547  triangles.push_back(i);
548  triangles.push_back((i == tot - 1) ? 0 : (i + 1));
549  }
550 
551  for (unsigned int i = 0; i < tot; ++i)
552  {
553  triangles.push_back((h_num + 1) * tot + 1);
554  triangles.push_back(h_num * tot + ((i == tot - 1) ? 0 : (i + 1)));
555  triangles.push_back(h_num * tot + i);
556  }
557 
558  for (unsigned int i = 0; i < h_num; ++i)
559  {
560  for (unsigned int j = 0; j < tot; ++j)
561  {
562  int a, b, c, d;
563  a = j;
564  b = (j == tot - 1) ? 0 : (j + 1);
565  c = j + tot;
566  d = (j == tot - 1) ? tot : (j + 1 + tot);
567 
568  int start = i * tot;
569  triangles.push_back(start + b);
570  triangles.push_back(start + a);
571  triangles.push_back(start + c);
572  triangles.push_back(start + b);
573  triangles.push_back(start + c);
574  triangles.push_back(start + d);
575  }
576  }
577  return createMeshFromVertices(vertices, triangles);
578 }
579 
581 {
582  // this code is adapted from FCL
583  EigenSTL::vector_Vector3d vertices;
584  std::vector<unsigned int> triangles;
585 
586  // magic number defining how many triangles to construct for the unit cylinder; perhaps this should be a param
587  static unsigned int tot_for_unit_cone = 100;
588 
589  double r = cone.radius;
590  double h = cone.length;
591 
592  const double pi = boost::math::constants::pi<double>();
593  unsigned int tot = tot_for_unit_cone * r;
594  double phid = pi * 2 / tot;
595 
596  double circle_edge = phid * r;
597  unsigned int h_num = ceil(h / circle_edge);
598 
599  double phi = 0;
600  double hd = h / h_num;
601 
602  for (unsigned int i = 0; i < h_num - 1; ++i)
603  {
604  double h_i = h / 2 - (i + 1) * hd;
605  double rh = r * (0.5 - h_i / h);
606  for(unsigned int j = 0; j < tot; ++j)
607  vertices.push_back(Eigen::Vector3d(rh * cos(phi + phid * j), rh * sin(phi + phid * j), h_i));
608  }
609 
610  for (unsigned int i = 0; i < tot; ++i)
611  vertices.push_back(Eigen::Vector3d(r * cos(phi + phid * i), r * sin(phi + phid * i), - h / 2));
612 
613  vertices.push_back(Eigen::Vector3d(0, 0, h / 2));
614  vertices.push_back(Eigen::Vector3d(0, 0, -h / 2));
615 
616  for (unsigned int i = 0; i < tot; ++i)
617  {
618  triangles.push_back(h_num * tot);
619  triangles.push_back(i);
620  triangles.push_back((i == tot - 1) ? 0 : (i + 1));
621  }
622 
623  for (unsigned int i = 0; i < tot; ++i)
624  {
625  triangles.push_back(h_num * tot + 1);
626  triangles.push_back((h_num - 1) * tot + ((i == tot - 1) ? 0 : (i + 1)));
627  triangles.push_back((h_num - 1) * tot + i);
628  }
629 
630  for (unsigned int i = 0; i < h_num - 1; ++i)
631  for (unsigned int j = 0; j < tot; ++j)
632  {
633  int a, b, c, d;
634  a = j;
635  b = (j == tot - 1) ? 0 : (j + 1);
636  c = j + tot;
637  d = (j == tot - 1) ? tot : (j + 1 + tot);
638 
639  int start = i * tot;
640  triangles.push_back(start + b);
641  triangles.push_back(start + a);
642  triangles.push_back(start + c);
643  triangles.push_back(start + b);
644  triangles.push_back(start + c);
645  triangles.push_back(start + d);
646  }
647  return createMeshFromVertices(vertices, triangles);
648 }
649 
650 namespace
651 {
652  inline void writeFloatToSTL(char *&ptr , float data)
653  {
654  memcpy(ptr, &data, sizeof(float));
655  ptr += sizeof(float);
656  }
657  inline void writeFloatToSTL(char *&ptr , double datad)
658  {
659  float data = datad;
660  memcpy(ptr, &data, sizeof(float));
661  ptr += sizeof(float);
662  }
663 }
664 
665 void writeSTLBinary(const Mesh* mesh, std::vector<char> &buffer)
666 {
667  buffer.resize(84 + mesh->triangle_count * 50);
668  memset(&buffer[0], 0, 80);
669  char *ptr = &buffer[80];
670  uint32_t nt = mesh->triangle_count;
671  memcpy(ptr, &nt, sizeof(uint32_t));
672  ptr += sizeof(uint32_t);
673  for (unsigned int i = 0 ; i < mesh->triangle_count ; ++i)
674  {
675  unsigned int i3 = i * 3;
676 
677  if (mesh->triangle_normals)
678  {
679  writeFloatToSTL(ptr, mesh->triangle_normals[i3]);
680  writeFloatToSTL(ptr, mesh->triangle_normals[i3 + 1]);
681  writeFloatToSTL(ptr, mesh->triangle_normals[i3 + 2]);
682  }
683  else
684  {
685  memset(ptr, 0, sizeof(float) * 3);
686  ptr += sizeof(float) * 3;
687  }
688 
689  unsigned int index = mesh->triangles[i3] * 3;
690  writeFloatToSTL(ptr, mesh->vertices[index]);
691  writeFloatToSTL(ptr, mesh->vertices[index + 1]);
692  writeFloatToSTL(ptr, mesh->vertices[index + 2]);
693  index = mesh->triangles[i3 + 1] * 3;
694  writeFloatToSTL(ptr, mesh->vertices[index]);
695  writeFloatToSTL(ptr, mesh->vertices[index + 1]);
696  writeFloatToSTL(ptr, mesh->vertices[index + 2]);
697  index = mesh->triangles[i3 + 2] * 3;
698  writeFloatToSTL(ptr, mesh->vertices[index]);
699  writeFloatToSTL(ptr, mesh->vertices[index + 1]);
700  writeFloatToSTL(ptr, mesh->vertices[index + 2]);
701  memset(ptr, 0, 2);
702  ptr += 2;
703  }
704 }
705 
706 }
d
Definition of various shapes. No properties such as position are included. These are simply the descr...
double radius
The radius of the cylinder.
Definition: shapes.h:135
Definition of a cylinder Length is along z axis. Origin is at center of mass.
Definition: shapes.h:116
std::vector< Eigen::Vector3d, Eigen::aligned_allocator< Eigen::Vector3d > > vector_Vector3d
double length
The length (height) of the cone.
Definition: shapes.h:155
double size[3]
x, y, z dimensions of the box (axis-aligned)
Definition: shapes.h:177
ShapeType type
The type of the shape.
Definition: shapes.h:91
double radius
The radius of the cone.
Definition: shapes.h:158
double length
The length of the cylinder.
Definition: shapes.h:132
unsigned int * triangles
The vertex indices for each triangle triangle k has vertices at index (3k, 3k+1, 3k+2) = (v1...
Definition: shapes.h:221
double y
Definition of a cone Tip is on positive z axis. Center of base is on negative z axis. Origin is halway between tip and center of base.
Definition: shapes.h:141
Mesh * createMeshFromVertices(const EigenSTL::vector_Vector3d &vertices, const std::vector< unsigned int > &triangles)
Load a mesh from a set of vertices. Triangles are constructed using index values from the triangles v...
unsigned int index
A basic definition of a shape. Shapes are considered centered at origin.
Definition: shapes.h:66
boost::shared_array< uint8_t > data
unsigned int triangle_count
The number of triangles formed with the vertices.
Definition: shapes.h:217
double z
double * vertices
The position for each vertex vertex k has values at index (3k, 3k+1, 3k+2) = (x,y,z)
Definition: shapes.h:214
double * triangle_normals
The normal to each triangle; unit vector represented as (x,y,z); If missing from the mesh...
Definition: shapes.h:225
void computeVertexNormals()
The normals to each vertex, averaged from the triangle normals. computeTriangleNormals() is automatic...
Definition: shapes.cpp:404
Definition of a sphere.
Definition: shapes.h:95
const std::string & shapeStringName(const Shape *shape)
Get the string name of the shape.
MemoryResource get(const std::string &url)
void computeTriangleNormals()
The normals to each triangle can be computed from the vertices using cross products. This function performs this computation and allocates memory for normals if needed.
Definition: shapes.cpp:381
Mesh * createMeshFromResource(const std::string &resource)
Load a mesh from a resource that contains a mesh that can be loaded by assimp.
void writeSTLBinary(const Mesh *mesh, std::vector< char > &buffer)
Write the mesh to a buffer in STL format.
Definition of a triangle mesh By convention the "center" of the shape is at the origin. For a mesh this implies that the AABB of the mesh is centered at the origin. Some methods may not work with arbitrary meshes whose AABB is not centered at the origin.
Definition: shapes.h:185
Definition of a box Aligned with the XYZ axes.
Definition: shapes.h:163
Mesh * createMeshFromBinary(const char *buffer, std::size_t size, const std::string &assimp_hint=std::string())
Load a mesh from a binary stream that contains a mesh that can be loaded by assimp.
Mesh * createMeshFromAsset(const aiScene *scene, const Eigen::Vector3d &scale, const std::string &assimp_hint=std::string())
Load a mesh from an assimp datastructure.
#define CONSOLE_BRIDGE_logError(fmt,...)
double radius
The radius of the sphere.
Definition: shapes.h:111
Mesh * createMeshFromShape(const Shape *shape)
Construct a mesh from a primitive shape that is NOT already a mesh. This call allocates a new object...
double x
r


geometric_shapes
Author(s): Ioan Sucan , Gil Jones
autogenerated on Wed Jan 17 2018 03:52:51