bodies.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 
38 #include <LinearMath/btConvexHull.h>
39 // #include <BulletCollision/CollisionShapes/btTriangleShape.h>
40 #include <algorithm>
41 #include <iostream>
42 #include <cmath>
43 
44 namespace robot_self_filter
45 {
47 {
48  Body *body = NULL;
49 
50  if (shape)
51  switch (shape->type)
52  {
53  case shapes::BOX:
54  body = new bodies::Box(shape);
55  break;
56  case shapes::SPHERE:
57  body = new bodies::Sphere(shape);
58  break;
59  case shapes::CYLINDER:
60  body = new bodies::Cylinder(shape);
61  break;
62  case shapes::MESH:
63  body = new bodies::ConvexMesh(shape);
64  break;
65  default:
66  std::cerr << "Creating body from shape: Unknown shape type" << shape->type << std::endl;
67  break;
68  }
69 
70  return body;
71 }
72 
73 void bodies::mergeBoundingSpheres(const std::vector<BoundingSphere> &spheres, BoundingSphere &mergedSphere)
74 {
75  if (spheres.empty())
76  {
77  mergedSphere.center.setValue(tfScalar(0), tfScalar(0), tfScalar(0));
78  mergedSphere.radius = 0.0;
79  }
80  else
81  {
82  mergedSphere = spheres[0];
83  for (unsigned int i = 1 ; i < spheres.size() ; ++i)
84  {
85  if (spheres[i].radius <= 0.0)
86  continue;
87  double d = spheres[i].center.distance(mergedSphere.center);
88  if (d + mergedSphere.radius <= spheres[i].radius)
89  {
90  mergedSphere.center = spheres[i].center;
91  mergedSphere.radius = spheres[i].radius;
92  }
93  else
94  if (d + spheres[i].radius > mergedSphere.radius)
95  {
96  tf::Vector3 delta = mergedSphere.center - spheres[i].center;
97  mergedSphere.radius = (delta.length() + spheres[i].radius + mergedSphere.radius)/2.0;
98  mergedSphere.center = delta.normalized() * (mergedSphere.radius - spheres[i].radius) + spheres[i].center;
99  }
100  }
101  }
102 }
103 
104 namespace bodies
105 {
106  static const double ZERO = 1e-9;
107 
110  static inline double distanceSQR(const tf::Vector3& p, const tf::Vector3& origin, const tf::Vector3& dir)
111  {
112  tf::Vector3 a = p - origin;
113  double d = dir.dot(a);
114  return a.length2() - d * d;
115  }
116 
117  namespace detail
118  {
119 
120  // temp structure for intersection points (used for ordering them)
121  struct intersc
122  {
123  intersc(const tf::Vector3 &_pt, const double _tm) : pt(_pt), time(_tm) {}
124 
126  double time;
127  };
128 
129  // define order on intersection points
131  {
132  bool operator()(const intersc &a, const intersc &b) const
133  {
134  return a.time < b.time;
135  }
136  };
137  }
138 }
139 
140 bool bodies::Sphere::containsPoint(const tf::Vector3 &p, bool verbose) const
141 {
142  return (m_center - p).length2() < m_radius2;
143 }
144 
145 void bodies::Sphere::useDimensions(const shapes::Shape *shape) // radius
146 {
147  m_radius = static_cast<const shapes::Sphere*>(shape)->radius;
148 }
149 
151 {
152  m_radiusU = m_radius * m_scale + m_padding;
153  m_radius2 = m_radiusU * m_radiusU;
154  m_center = m_pose.getOrigin();
155 }
156 
158 {
159  return 4.0 * M_PI * m_radiusU * m_radiusU * m_radiusU / 3.0;
160 }
161 
163 {
164  sphere.center = m_center;
165  sphere.radius = m_radiusU;
166 }
167 
168 bool bodies::Sphere::intersectsRay(const tf::Vector3& origin, const tf::Vector3& dir, std::vector<tf::Vector3> *intersections, unsigned int count) const
169 {
170  if (distanceSQR(m_center, origin, dir) > m_radius2) return false;
171 
172  bool result = false;
173 
174  tf::Vector3 cp = origin - m_center;
175  double dpcpv = cp.dot(dir);
176 
177  tf::Vector3 w = cp - dpcpv * dir;
178  tf::Vector3 Q = m_center + w;
179  double x = m_radius2 - w.length2();
180 
181  if (fabs(x) < ZERO)
182  {
183  w = Q - origin;
184  double dpQv = w.dot(dir);
185  if (dpQv > ZERO)
186  {
187  if (intersections)
188  intersections->push_back(Q);
189  result = true;
190  }
191  } else
192  if (x > 0.0)
193  {
194  x = sqrt(x);
195  w = dir * x;
196  tf::Vector3 A = Q - w;
197  tf::Vector3 B = Q + w;
198  w = A - origin;
199  double dpAv = w.dot(dir);
200  w = B - origin;
201  double dpBv = w.dot(dir);
202 
203  if (dpAv > ZERO)
204  {
205  result = true;
206  if (intersections)
207  {
208  intersections->push_back(A);
209  if (count == 1)
210  return result;
211  }
212  }
213 
214  if (dpBv > ZERO)
215  {
216  result = true;
217  if (intersections)
218  intersections->push_back(B);
219  }
220  }
221  return result;
222 }
223 
224 bool bodies::Cylinder::containsPoint(const tf::Vector3 &p, bool verbose) const
225 {
226  tf::Vector3 v = p - m_center;
227  double pH = v.dot(m_normalH);
228 
229  if (fabs(pH) > m_length2)
230  return false;
231 
232  double pB1 = v.dot(m_normalB1);
233  double remaining = m_radius2 - pB1 * pB1;
234 
235  if (remaining < 0.0)
236  return false;
237  else
238  {
239  double pB2 = v.dot(m_normalB2);
240  return pB2 * pB2 < remaining;
241  }
242 }
243 
244 void bodies::Cylinder::useDimensions(const shapes::Shape *shape) // (length, radius)
245 {
246  m_length = static_cast<const shapes::Cylinder*>(shape)->length;
247  m_radius = static_cast<const shapes::Cylinder*>(shape)->radius;
248 }
249 
251 {
252  m_radiusU = m_radius * m_scale + m_padding;
253  m_radius2 = m_radiusU * m_radiusU;
254  m_length2 = m_scale * m_length / 2.0 + m_padding;
255  m_center = m_pose.getOrigin();
256  m_radiusBSqr = m_length2 * m_length2 + m_radius2;
257  m_radiusB = sqrt(m_radiusBSqr);
258 
259  const tf::Matrix3x3& basis = m_pose.getBasis();
260  m_normalB1 = basis.getColumn(0);
261  m_normalB2 = basis.getColumn(1);
262  m_normalH = basis.getColumn(2);
263 
264  double tmp = -m_normalH.dot(m_center);
265  m_d1 = tmp + m_length2;
266  m_d2 = tmp - m_length2;
267 }
268 
270 {
271  return 2.0 * M_PI * m_radius2 * m_length2;
272 }
273 
275 {
276  sphere.center = m_center;
277  sphere.radius = m_radiusB;
278 }
279 
280 bool bodies::Cylinder::intersectsRay(const tf::Vector3& origin, const tf::Vector3& dir, std::vector<tf::Vector3> *intersections, unsigned int count) const
281 {
282  if (distanceSQR(m_center, origin, dir) > m_radiusBSqr) return false;
283 
284  std::vector<detail::intersc> ipts;
285 
286  // intersect bases
287  double tmp = m_normalH.dot(dir);
288  if (fabs(tmp) > ZERO)
289  {
290  double tmp2 = -m_normalH.dot(origin);
291  double t1 = (tmp2 - m_d1) / tmp;
292 
293  if (t1 > 0.0)
294  {
295  tf::Vector3 p1(origin + dir * t1);
296  tf::Vector3 v1(p1 - m_center);
297  v1 = v1 - m_normalH.dot(v1) * m_normalH;
298  if (v1.length2() < m_radius2 + ZERO)
299  {
300  if (intersections == NULL)
301  return true;
302 
303  detail::intersc ip(p1, t1);
304  ipts.push_back(ip);
305  }
306  }
307 
308  double t2 = (tmp2 - m_d2) / tmp;
309  if (t2 > 0.0)
310  {
311  tf::Vector3 p2(origin + dir * t2);
312  tf::Vector3 v2(p2 - m_center);
313  v2 = v2 - m_normalH.dot(v2) * m_normalH;
314  if (v2.length2() < m_radius2 + ZERO)
315  {
316  if (intersections == NULL)
317  return true;
318 
319  detail::intersc ip(p2, t2);
320  ipts.push_back(ip);
321  }
322  }
323  }
324 
325  if (ipts.size() < 2)
326  {
327  // intersect with infinite cylinder
328  tf::Vector3 VD(m_normalH.cross(dir));
329  tf::Vector3 ROD(m_normalH.cross(origin - m_center));
330  double a = VD.length2();
331  double b = 2.0 * ROD.dot(VD);
332  double c = ROD.length2() - m_radius2;
333  double d = b * b - 4.0 * a * c;
334  if (d > 0.0 && fabs(a) > ZERO)
335  {
336  d = sqrt(d);
337  double e = -a * 2.0;
338  double t1 = (b + d) / e;
339  double t2 = (b - d) / e;
340 
341  if (t1 > 0.0)
342  {
343  tf::Vector3 p1(origin + dir * t1);
344  tf::Vector3 v1(m_center - p1);
345 
346  if (fabs(m_normalH.dot(v1)) < m_length2 + ZERO)
347  {
348  if (intersections == NULL)
349  return true;
350 
351  detail::intersc ip(p1, t1);
352  ipts.push_back(ip);
353  }
354  }
355 
356  if (t2 > 0.0)
357  {
358  tf::Vector3 p2(origin + dir * t2);
359  tf::Vector3 v2(m_center - p2);
360 
361  if (fabs(m_normalH.dot(v2)) < m_length2 + ZERO)
362  {
363  if (intersections == NULL)
364  return true;
365  detail::intersc ip(p2, t2);
366  ipts.push_back(ip);
367  }
368  }
369  }
370  }
371 
372  if (ipts.empty())
373  return false;
374 
375  std::sort(ipts.begin(), ipts.end(), detail::interscOrder());
376  const unsigned int n = count > 0 ? std::min<unsigned int>(count, ipts.size()) : ipts.size();
377  for (unsigned int i = 0 ; i < n ; ++i)
378  intersections->push_back(ipts[i].pt);
379 
380  return true;
381 }
382 
383 bool bodies::Box::containsPoint(const tf::Vector3 &p, bool verbose) const
384 {
385  /* if(verbose)
386  fprintf(stderr,"Actual: %f,%f,%f \nDesired: %f,%f,%f \nTolerance:%f,%f,%f\n",p.x(),p.y(),p.z(),m_center.x(),m_center.y(),m_center.z(),m_length2,m_width2,m_height2);*/
387  tf::Vector3 v = p - m_center;
388  double pL = v.dot(m_normalL);
389 
390  if (fabs(pL) > m_length2)
391  return false;
392 
393  double pW = v.dot(m_normalW);
394 
395  if (fabs(pW) > m_width2)
396  return false;
397 
398  double pH = v.dot(m_normalH);
399 
400  if (fabs(pH) > m_height2)
401  return false;
402 
403  return true;
404 }
405 
406 void bodies::Box::useDimensions(const shapes::Shape *shape) // (x, y, z) = (length, width, height)
407 {
408  const double *size = static_cast<const shapes::Box*>(shape)->size;
409  m_length = size[0];
410  m_width = size[1];
411  m_height = size[2];
412 }
413 
415 {
416  double s2 = m_scale / 2.0;
417  m_length2 = m_length * s2 + m_padding;
418  m_width2 = m_width * s2 + m_padding;
419  m_height2 = m_height * s2 + m_padding;
420 
421  m_center = m_pose.getOrigin();
422 
423  m_radius2 = m_length2 * m_length2 + m_width2 * m_width2 + m_height2 * m_height2;
424  m_radiusB = sqrt(m_radius2);
425 
426  const tf::Matrix3x3& basis = m_pose.getBasis();
427  m_normalL = basis.getColumn(0);
428  m_normalW = basis.getColumn(1);
429  m_normalH = basis.getColumn(2);
430 
431  const tf::Vector3 tmp(m_normalL * m_length2 + m_normalW * m_width2 + m_normalH * m_height2);
432  m_corner1 = m_center - tmp;
433  m_corner2 = m_center + tmp;
434 }
435 
436 double bodies::Box::computeVolume(void) const
437 {
438  return 8.0 * m_length2 * m_width2 * m_height2;
439 }
440 
442 {
443  sphere.center = m_center;
444  sphere.radius = m_radiusB;
445 }
446 
447 bool bodies::Box::intersectsRay(const tf::Vector3& origin, const tf::Vector3& dir, std::vector<tf::Vector3> *intersections, unsigned int count) const
448 {
449  if (distanceSQR(m_center, origin, dir) > m_radius2) return false;
450 
451  double t_near = -INFINITY;
452  double t_far = INFINITY;
453 
454  for (int i = 0; i < 3; i++)
455  {
456  const tf::Vector3 &vN = i == 0 ? m_normalL : (i == 1 ? m_normalW : m_normalH);
457  double dp = vN.dot(dir);
458 
459  if (fabs(dp) > ZERO)
460  {
461  double t1 = vN.dot(m_corner1 - origin) / dp;
462  double t2 = vN.dot(m_corner2 - origin) / dp;
463 
464  if (t1 > t2)
465  std::swap(t1, t2);
466 
467  if (t1 > t_near)
468  t_near = t1;
469 
470  if (t2 < t_far)
471  t_far = t2;
472 
473  if (t_near > t_far)
474  return false;
475 
476  if (t_far < 0.0)
477  return false;
478  }
479  else
480  {
481  if (i == 0)
482  {
483  if ((std::min(m_corner1.y(), m_corner2.y()) > origin.y() ||
484  std::max(m_corner1.y(), m_corner2.y()) < origin.y()) &&
485  (std::min(m_corner1.z(), m_corner2.z()) > origin.z() ||
486  std::max(m_corner1.z(), m_corner2.z()) < origin.z()))
487  return false;
488  }
489  else
490  {
491  if (i == 1)
492  {
493  if ((std::min(m_corner1.x(), m_corner2.x()) > origin.x() ||
494  std::max(m_corner1.x(), m_corner2.x()) < origin.x()) &&
495  (std::min(m_corner1.z(), m_corner2.z()) > origin.z() ||
496  std::max(m_corner1.z(), m_corner2.z()) < origin.z()))
497  return false;
498  }
499  else
500  if ((std::min(m_corner1.x(), m_corner2.x()) > origin.x() ||
501  std::max(m_corner1.x(), m_corner2.x()) < origin.x()) &&
502  (std::min(m_corner1.y(), m_corner2.y()) > origin.y() ||
503  std::max(m_corner1.y(), m_corner2.y()) < origin.y()))
504  return false;
505  }
506  }
507  }
508 
509  if (intersections)
510  {
511  if (t_far - t_near > ZERO)
512  {
513  intersections->push_back(t_near * dir + origin);
514  if (count > 1)
515  intersections->push_back(t_far * dir + origin);
516  }
517  else
518  intersections->push_back(t_far * dir + origin);
519  }
520 
521  return true;
522 }
523 /*
524 bool bodies::Mesh::containsPoint(const tf::Vector3 &p) const
525 {
526  // compute all intersections
527  std::vector<tf::Vector3> pts;
528  intersectsRay(p, tf::Vector3(0, 0, 1), &pts);
529 
530  // if we have an odd number of intersections, we are inside
531  return pts.size() % 2 == 1;
532 }
533 
534 namespace bodies
535 {
536  namespace detail
537  {
538  // callback for bullet
539  class myTriangleCallback : public btTriangleCallback
540  {
541  public:
542 
543  myTriangleCallback(bool keep_triangles) : keep_triangles_(keep_triangles)
544  {
545  found_intersections = false;
546  }
547 
548  virtual void processTriangle(tf::Vector3 *triangle, int partId, int triangleIndex)
549  {
550  found_intersections = true;
551  if (keep_triangles_)
552  triangles.push_back(btTriangleShape(triangle[0], triangle[1], triangle[2]));
554  }
555 
556  bool found_intersections;
557  std::vector<btTriangleShape> triangles;
558 
559  private:
560 
561  bool keep_triangles_;
562  };
563 
564  }
565 }
566 
567 bool bodies::Mesh::intersectsRay(const tf::Vector3& origin, const tf::Vector3& dir, std::vector<tf::Vector3> *intersections, unsigned int count) const
568 {
569  if (m_btMeshShape)
570  {
571 
572  if (distanceSQR(m_center, origin, dir) > m_radiusBSqr) return false;
573 
574  // transform the ray into the coordinate frame of the mesh
575  tf::Vector3 orig(m_iPose * origin);
576  tf::Vector3 dr(m_iPose.getBasis() * dir);
577 
578  // find intersection with AABB
579  tfScalar maxT = 0.0;
580 
581  if (fabs(dr.x()) > ZERO)
582  {
583  tfScalar t = (m_aabbMax.x() - orig.x()) / dr.x();
584  if (t < 0.0)
585  t = (m_aabbMin.x() - orig.x()) / dr.x();
586  if (t > maxT)
587  maxT = t;
588  }
589  if (fabs(dr.y()) > ZERO)
590  {
591  tfScalar t = (m_aabbMax.y() - orig.y()) / dr.y();
592  if (t < 0.0)
593  t = (m_aabbMin.y() - orig.y()) / dr.y();
594  if (t > maxT)
595  maxT = t;
596  }
597  if (fabs(dr.z()) > ZERO)
598  {
599  tfScalar t = (m_aabbMax.z() - orig.z()) / dr.z();
600  if (t < 0.0)
601  t = (m_aabbMin.z() - orig.z()) / dr.z();
602  if (t > maxT)
603  maxT = t;
604  }
605 
606  // the farthest point where we could have an intersection id orig + dr * maxT
607 
608  detail::myTriangleCallback cb(intersections != NULL);
609  m_btMeshShape->performRaycast(&cb, orig, orig + dr * maxT);
610  if (cb.found_intersections)
611  {
612  if (intersections)
613  {
614  std::vector<detail::intersc> intpt;
615  for (unsigned int i = 0 ; i < cb.triangles.size() ; ++i)
616  {
617  tf::Vector3 normal;
618  cb.triangles[i].calcNormal(normal);
619  tfScalar dv = normal.dot(dr);
620  if (fabs(dv) > 1e-3)
621  {
622  double t = (normal.dot(cb.triangles[i].getVertexPtr(0)) - normal.dot(orig)) / dv;
623  // here we use the input origin & direction, since the transform is linear
624  detail::intersc ip(origin + dir * t, t);
625  intpt.push_back(ip);
626  }
627  }
628  std::sort(intpt.begin(), intpt.end(), detail::interscOrder());
629  const unsigned int n = count > 0 ? std::min<unsigned int>(count, intpt.size()) : intpt.size();
630  for (unsigned int i = 0 ; i < n ; ++i)
631  intersections->push_back(intpt[i].pt);
632  }
633  return true;
634  }
635  else
636  return false;
637  }
638  else
639  return false;
640 }
641 
642 void bodies::Mesh::useDimensions(const shapes::Shape *shape)
643 {
644  const shapes::Mesh *mesh = static_cast<const shapes::Mesh*>(shape);
645  if (m_btMeshShape)
646  delete m_btMeshShape;
647  if (m_btMesh)
648  delete m_btMesh;
649 
650  m_btMesh = new btTriangleMesh();
651  const unsigned int nt = mesh->triangleCount / 3;
652  for (unsigned int i = 0 ; i < nt ; ++i)
653  {
654  const unsigned int i3 = i *3;
655  const unsigned int v1 = 3 * mesh->triangles[i3];
656  const unsigned int v2 = 3 * mesh->triangles[i3 + 1];
657  const unsigned int v3 = 3 * mesh->triangles[i3 + 2];
658  m_btMesh->addTriangle(tf::Vector3(mesh->vertices[v1], mesh->vertices[v1 + 1], mesh->vertices[v1 + 2]),
659  tf::Vector3(mesh->vertices[v2], mesh->vertices[v2 + 1], mesh->vertices[v2 + 2]),
660  tf::Vector3(mesh->vertices[v3], mesh->vertices[v3 + 1], mesh->vertices[v3 + 2]), true);
661  }
662 
663  m_btMeshShape = new btBvhTriangleMeshShape(m_btMesh, true);
664 }
665 
666 void bodies::Mesh::updateInternalData(void)
667 {
668  if (m_btMeshShape)
669  {
670  m_btMeshShape->setLocalScaling(tf::Vector3(m_scale, m_scale, m_scale));
671  m_btMeshShape->setMargin(m_padding);
672  }
673  m_iPose = m_pose.inverse();
674 
675  tf::Transform id;
676  id.setIdentity();
677  m_btMeshShape->getAabb(id, m_aabbMin, m_aabbMax);
678 
679  tf::Vector3 d = (m_aabbMax - m_aabbMin) / 2.0;
680 
681  m_center = m_pose.getOrigin() + d;
682  m_radiusBSqr = d.length2();
683  m_radiusB = sqrt(m_radiusBSqr);
684 
686 }
687 
688 double bodies::Mesh::computeVolume(void) const
689 {
690  if (m_btMeshShape)
691  {
692  // approximation; volume of AABB at identity transform
693  tf::Vector3 d = m_aabbMax - m_aabbMin;
694  return d.x() * d.y() * d.z();
695  }
696  else
697  return 0.0;
698 }
699 
700 void bodies::Mesh::computeBoundingSphere(BoundingSphere &sphere) const
701 {
702  sphere.center = m_center;
703  sphere.radius = m_radiusB;
704 }
705 
706 */
707 
708 bool bodies::ConvexMesh::containsPoint(const tf::Vector3 &p, bool verbose) const
709 {
710  if (m_boundingBox.containsPoint(p))
711  {
712  tf::Vector3 ip(m_iPose * p);
713  ip = m_meshCenter + (ip - m_meshCenter) * m_scale;
714  return isPointInsidePlanes(ip);
715  }
716  else
717  return false;
718 }
719 
721 {
722  const shapes::Mesh *mesh = static_cast<const shapes::Mesh*>(shape);
723 
724  double maxX = -INFINITY, maxY = -INFINITY, maxZ = -INFINITY;
725  double minX = INFINITY, minY = INFINITY, minZ = INFINITY;
726 
727  for(unsigned int i = 0; i < mesh->vertexCount ; ++i)
728  {
729  double vx = mesh->vertices[3 * i ];
730  double vy = mesh->vertices[3 * i + 1];
731  double vz = mesh->vertices[3 * i + 2];
732 
733  if (maxX < vx) maxX = vx;
734  if (maxY < vy) maxY = vy;
735  if (maxZ < vz) maxZ = vz;
736 
737  if (minX > vx) minX = vx;
738  if (minY > vy) minY = vy;
739  if (minZ > vz) minZ = vz;
740  }
741 
742  if (maxX < minX) maxX = minX = 0.0;
743  if (maxY < minY) maxY = minY = 0.0;
744  if (maxZ < minZ) maxZ = minZ = 0.0;
745 
746  shapes::Box *box_shape = new shapes::Box(maxX - minX, maxY - minY, maxZ - minZ);
747  m_boundingBox.setDimensions(box_shape);
748  delete box_shape;
749 
750  m_boxOffset.setValue((minX + maxX) / 2.0, (minY + maxY) / 2.0, (minZ + maxZ) / 2.0);
751 
752  m_planes.clear();
753  m_triangles.clear();
754  m_vertices.clear();
755  m_meshRadiusB = 0.0;
756  m_meshCenter.setValue(tfScalar(0), tfScalar(0), tfScalar(0));
757 
758  btVector3 *vertices = new btVector3[mesh->vertexCount];
759  for(unsigned int i = 0; i < mesh->vertexCount ; ++i)
760  {
761  vertices[i].setX(mesh->vertices[3 * i ]);
762  vertices[i].setY(mesh->vertices[3 * i + 1]);
763  vertices[i].setZ(mesh->vertices[3 * i + 2]);
764  }
765 
766  HullDesc hd(QF_TRIANGLES, mesh->vertexCount, vertices);
767  HullResult hr;
768  HullLibrary hl;
769  if (hl.CreateConvexHull(hd, hr) == QE_OK)
770  {
771  // std::cout << "Convex hull has " << hr.m_OutputVertices.size() << " vertices (down from " << mesh->vertexCount << "), " << hr.mNumFaces << " faces" << std::endl;
772 
773  m_vertices.reserve(hr.m_OutputVertices.size());
774  tf::Vector3 sum(0, 0, 0);
775 
776  for (int j = 0 ; j < hr.m_OutputVertices.size() ; ++j)
777  {
778  tf::Vector3 vector3_tmp(tf::Vector3(hr.m_OutputVertices[j][0],hr.m_OutputVertices[j][1],hr.m_OutputVertices[j][2]));
779  m_vertices.push_back(vector3_tmp);
780  sum = sum + vector3_tmp;
781  }
782 
783  m_meshCenter = sum / (double)(hr.m_OutputVertices.size());
784  for (unsigned int j = 0 ; j < m_vertices.size() ; ++j)
785  {
786  double dist = m_vertices[j].distance2(m_meshCenter);
787  if (dist > m_meshRadiusB)
788  m_meshRadiusB = dist;
789  }
790  m_meshRadiusB = sqrt(m_meshRadiusB);
791 
792  m_triangles.reserve(hr.m_Indices.size());
793  for (unsigned int j = 0 ; j < hr.mNumFaces ; ++j)
794  {
795  const tf::Vector3 p1(hr.m_OutputVertices[hr.m_Indices[j * 3 ]][0],hr.m_OutputVertices[hr.m_Indices[j * 3 ]][1],hr.m_OutputVertices[hr.m_Indices[j * 3 ]][2]);
796  const tf::Vector3 p2(hr.m_OutputVertices[hr.m_Indices[j * 3 + 1]][0],hr.m_OutputVertices[hr.m_Indices[j * 3 + 1]][1],hr.m_OutputVertices[hr.m_Indices[j * 3 + 1]][2]);
797  const tf::Vector3 p3(hr.m_OutputVertices[hr.m_Indices[j * 3 + 2]][0],hr.m_OutputVertices[hr.m_Indices[j * 3 + 2]][1],hr.m_OutputVertices[hr.m_Indices[j * 3 + 2]][2]);
798 
799  tf::Vector3 edge1 = (p2 - p1);
800  tf::Vector3 edge2 = (p3 - p1);
801 
802  edge1.normalize();
803  edge2.normalize();
804 
805  tf::Vector3 planeNormal = edge1.cross(edge2);
806 
807  if (planeNormal.length2() > tfScalar(1e-6))
808  {
809  planeNormal.normalize();
810  tf::tfVector4 planeEquation(planeNormal.getX(), planeNormal.getY(), planeNormal.getZ(), -planeNormal.dot(p1));
811 
812  unsigned int behindPlane = countVerticesBehindPlane(planeEquation);
813  if (behindPlane > 0)
814  {
815  tf::tfVector4 planeEquation2(-planeEquation.getX(), -planeEquation.getY(), -planeEquation.getZ(), -planeEquation.getW());
816  unsigned int behindPlane2 = countVerticesBehindPlane(planeEquation2);
817  if (behindPlane2 < behindPlane)
818  {
819  planeEquation.setValue(planeEquation2.getX(), planeEquation2.getY(), planeEquation2.getZ(), planeEquation2.getW());
820  behindPlane = behindPlane2;
821  }
822  }
823 
824  // if (behindPlane > 0)
825  // std::cerr << "Approximate plane: " << behindPlane << " of " << m_vertices.size() << " points are behind the plane" << std::endl;
826 
827  m_planes.push_back(planeEquation);
828 
829  m_triangles.push_back(hr.m_Indices[j * 3 + 0]);
830  m_triangles.push_back(hr.m_Indices[j * 3 + 1]);
831  m_triangles.push_back(hr.m_Indices[j * 3 + 2]);
832  }
833  }
834  }
835  else
836  std::cerr << "Unable to compute convex hull.";
837 
838  hl.ReleaseResult(hr);
839  delete[] vertices;
840 
841 }
842 
844 {
845  tf::Transform pose = m_pose;
846  pose.setOrigin(m_pose * m_boxOffset);
847  m_boundingBox.setPose(pose);
848  m_boundingBox.setPadding(m_padding);
849  m_boundingBox.setScale(m_scale);
850 
851  m_iPose = m_pose.inverse();
852  m_center = m_pose * m_meshCenter;
853  m_radiusB = m_meshRadiusB * m_scale + m_padding;
854  m_radiusBSqr = m_radiusB * m_radiusB;
855 
856  m_scaledVertices.resize(m_vertices.size());
857  for (unsigned int i = 0 ; i < m_vertices.size() ; ++i)
858  {
859  tf::Vector3 v(m_vertices[i] - m_meshCenter);
860  tfScalar l = v.length();
861  m_scaledVertices[i] = m_meshCenter + v * (m_scale + (l > ZERO ? m_padding / l : 0.0));
862  }
863 }
864 
866 {
867  sphere.center = m_center;
868  sphere.radius = m_radiusB;
869 }
870 
872 {
873  unsigned int numplanes = m_planes.size();
874  for (unsigned int i = 0 ; i < numplanes ; ++i)
875  {
876  const tf::tfVector4& plane = m_planes[i];
877  tfScalar dist = plane.dot(point) + plane.getW() - m_padding - tfScalar(1e-6);
878  if (dist > tfScalar(0))
879  return false;
880  }
881  return true;
882 }
883 
884 unsigned int bodies::ConvexMesh::countVerticesBehindPlane(const tf::tfVector4& planeNormal) const
885 {
886  unsigned int numvertices = m_vertices.size();
887  unsigned int result = 0;
888  for (unsigned int i = 0 ; i < numvertices ; ++i)
889  {
890  tfScalar dist = planeNormal.dot(m_vertices[i]) + planeNormal.getW() - tfScalar(1e-6);
891  if (dist > tfScalar(0))
892  result++;
893  }
894  return result;
895 }
896 
898 {
899  double volume = 0.0;
900  for (unsigned int i = 0 ; i < m_triangles.size() / 3 ; ++i)
901  {
902  const tf::Vector3 &v1 = m_vertices[m_triangles[3*i + 0]];
903  const tf::Vector3 &v2 = m_vertices[m_triangles[3*i + 1]];
904  const tf::Vector3 &v3 = m_vertices[m_triangles[3*i + 2]];
905  volume += v1.x()*v2.y()*v3.z() + v2.x()*v3.y()*v1.z() + v3.x()*v1.y()*v2.z() - v1.x()*v3.y()*v2.z() - v2.x()*v1.y()*v3.z() - v3.x()*v2.y()*v1.z();
906  }
907  return fabs(volume)/6.0;
908 }
909 
910 bool bodies::ConvexMesh::intersectsRay(const tf::Vector3& origin, const tf::Vector3& dir, std::vector<tf::Vector3> *intersections, unsigned int count) const
911 {
912  if (distanceSQR(m_center, origin, dir) > m_radiusBSqr) return false;
913  if (!m_boundingBox.intersectsRay(origin, dir)) return false;
914 
915  // transform the ray into the coordinate frame of the mesh
916  tf::Vector3 orig(m_iPose * origin);
917  tf::Vector3 dr(m_iPose.getBasis() * dir);
918 
919  std::vector<detail::intersc> ipts;
920 
921  bool result = false;
922 
923  // for each triangle
924  const unsigned int nt = m_triangles.size() / 3;
925  for (unsigned int i = 0 ; i < nt ; ++i)
926  {
927  tfScalar tmp = m_planes[i].dot(dr);
928  if (fabs(tmp) > ZERO)
929  {
930  double t = -(m_planes[i].dot(orig) + m_planes[i].getW()) / tmp;
931  if (t > 0.0)
932  {
933  const int i3 = 3 * i;
934  const int v1 = m_triangles[i3 + 0];
935  const int v2 = m_triangles[i3 + 1];
936  const int v3 = m_triangles[i3 + 2];
937 
938  const tf::Vector3 &a = m_scaledVertices[v1];
939  const tf::Vector3 &b = m_scaledVertices[v2];
940  const tf::Vector3 &c = m_scaledVertices[v3];
941 
942  tf::Vector3 cb(c - b);
943  tf::Vector3 ab(a - b);
944 
945  // intersection of the plane defined by the triangle and the ray
946  tf::Vector3 P(orig + dr * t);
947 
948  // check if it is inside the triangle
949  tf::Vector3 pb(P - b);
950  tf::Vector3 c1(cb.cross(pb));
951  tf::Vector3 c2(cb.cross(ab));
952  if (c1.dot(c2) < 0.0)
953  continue;
954 
955  tf::Vector3 ca(c - a);
956  tf::Vector3 pa(P - a);
957  tf::Vector3 ba(-ab);
958 
959  c1 = ca.cross(pa);
960  c2 = ca.cross(ba);
961  if (c1.dot(c2) < 0.0)
962  continue;
963 
964  c1 = ba.cross(pa);
965  c2 = ba.cross(ca);
966 
967  if (c1.dot(c2) < 0.0)
968  continue;
969 
970  result = true;
971  if (intersections)
972  {
973  detail::intersc ip(origin + dir * t, t);
974  ipts.push_back(ip);
975  }
976  else
977  break;
978  }
979  }
980  }
981 
982  if (intersections)
983  {
984  std::sort(ipts.begin(), ipts.end(), detail::interscOrder());
985  const unsigned int n = count > 0 ? std::min<unsigned int>(count, ipts.size()) : ipts.size();
986  for (unsigned int i = 0 ; i < n ; ++i)
987  intersections->push_back(ipts[i].pt);
988  }
989 
990  return result;
991 }
992 
993 }
d
virtual double computeVolume(void) const
Compute the volume of the body. This method includes changes induced by scaling and padding...
Definition: bodies.cpp:157
virtual bool intersectsRay(const tf::Vector3 &origin, const tf::Vector3 &dir, std::vector< tf::Vector3 > *intersections=NULL, unsigned int count=0) const
Check is a ray intersects the body, and find the set of intersections, in order, along the ray...
Definition: bodies.cpp:280
bool isPointInsidePlanes(const tf::Vector3 &point) const
Definition: bodies.cpp:871
virtual void computeBoundingSphere(BoundingSphere &sphere) const
Compute the bounding radius for the body, in its current pose. Scaling and padding are accounted for...
Definition: bodies.cpp:274
Definition of a box.
Definition: shapes.h:130
double tfScalar
virtual void computeBoundingSphere(BoundingSphere &sphere) const
Compute the bounding radius for the body, in its current pose. Scaling and padding are accounted for...
Definition: bodies.cpp:865
Definition of a cylinder.
Definition: shapes.h:110
virtual void useDimensions(const shapes::Shape *shape)
Definition: bodies.cpp:244
virtual bool intersectsRay(const tf::Vector3 &origin, const tf::Vector3 &dir, std::vector< tf::Vector3 > *intersections=NULL, unsigned int count=0) const
Check is a ray intersects the body, and find the set of intersections, in order, along the ray...
Definition: bodies.cpp:447
virtual void computeBoundingSphere(BoundingSphere &sphere) const
Compute the bounding radius for the body, in its current pose. Scaling and padding are accounted for...
Definition: bodies.cpp:162
tfScalar getW() const
virtual bool containsPoint(const tf::Vector3 &p, bool verbose=false) const
Check is a point is inside the body.
Definition: bodies.cpp:140
TFSIMD_FORCE_INLINE const tfScalar & getY() const
Definition of a cylinder.
Definition: bodies.h:210
Definition of a mesh.
Definition: shapes.h:152
virtual bool containsPoint(const tf::Vector3 &p, bool verbose=false) const
Check is a point is inside the body.
Definition: bodies.cpp:708
intersc(const tf::Vector3 &_pt, const double _tm)
Definition: bodies.cpp:123
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
static const double ZERO
Definition: bodies.cpp:106
TFSIMD_FORCE_INLINE void setValue(const tfScalar &x, const tfScalar &y, const tfScalar &z)
TFSIMD_FORCE_INLINE Vector3 cross(const Vector3 &v) const
double * vertices
the position for each vertex vertex k has values at index (3k, 3k+1, 3k+2) = (x,y,z)
Definition: shapes.h:190
Definition of a sphere that bounds another object.
Definition: bodies.h:61
TFSIMD_FORCE_INLINE const tfScalar & x() const
Definition of a convex mesh. Convex hull is computed for a given shape::Mesh.
Definition: bodies.h:355
TFSIMD_FORCE_INLINE tfScalar dot(const Vector3 &v) const
Body * createBodyFromShape(const shapes::Shape *shape)
Create a body from a given shape.
Definition: bodies.cpp:46
TFSIMD_FORCE_INLINE tfScalar distance2(const Vector3 &v) const
virtual double computeVolume(void) const
Compute the volume of the body. This method includes changes induced by scaling and padding...
Definition: bodies.cpp:436
void mergeBoundingSpheres(const std::vector< BoundingSphere > &spheres, BoundingSphere &mergedSphere)
Compute a bounding sphere to enclose a set of bounding spheres.
Definition: bodies.cpp:73
TFSIMD_FORCE_INLINE const tfScalar & z() const
virtual bool containsPoint(const tf::Vector3 &p, bool verbose=false) const
Check is a point is inside the body.
Definition: bodies.cpp:383
TFSIMD_FORCE_INLINE Vector3 normalized() const
TFSIMD_FORCE_INLINE const tfScalar & y() const
static double distanceSQR(const tf::Vector3 &p, const tf::Vector3 &origin, const tf::Vector3 &dir)
Compute the square of the distance between a ray and a point Note: this requires &#39;dir&#39; to be normaliz...
Definition: bodies.cpp:110
virtual void updateInternalData(void)
Definition: bodies.cpp:414
A body is a shape + its pose. Point inclusion, ray intersection can be tested, volumes and bounding s...
Definition: bodies.h:70
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool operator()(const intersc &a, const intersc &b) const
Definition: bodies.cpp:132
virtual void updateInternalData(void)
Definition: bodies.cpp:150
virtual double computeVolume(void) const
Compute the volume of the body. This method includes changes induced by scaling and padding...
Definition: bodies.cpp:897
virtual bool intersectsRay(const tf::Vector3 &origin, const tf::Vector3 &dir, std::vector< tf::Vector3 > *intersections=NULL, unsigned int count=0) const
Check is a ray intersects the body, and find the set of intersections, in order, along the ray...
Definition: bodies.cpp:168
TFSIMD_FORCE_INLINE Vector3 & normalize()
TFSIMD_FORCE_INLINE const tfScalar & w() const
virtual void computeBoundingSphere(BoundingSphere &sphere) const
Compute the bounding radius for the body, in its current pose. Scaling and padding are accounted for...
Definition: bodies.cpp:441
Definition of a sphere.
Definition: shapes.h:91
Definition of a box.
Definition: bodies.h:255
A basic definition of a shape. Shapes are considered centered at origin.
Definition: shapes.h:59
virtual void useDimensions(const shapes::Shape *shape)
Definition: bodies.cpp:145
TFSIMD_FORCE_INLINE const tfScalar & getX() const
virtual double computeVolume(void) const
Compute the volume of the body. This method includes changes induced by scaling and padding...
Definition: bodies.cpp:269
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
virtual void updateInternalData(void)
Definition: bodies.cpp:250
Definition of a sphere.
Definition: bodies.h:175
unsigned int vertexCount
the number of available vertices
Definition: shapes.h:186
virtual bool intersectsRay(const tf::Vector3 &origin, const tf::Vector3 &dir, std::vector< tf::Vector3 > *intersections=NULL, unsigned int count=0) const
Check is a ray intersects the body, and find the set of intersections, in order, along the ray...
Definition: bodies.cpp:910
virtual bool containsPoint(const tf::Vector3 &p, bool verbose=false) const
Check is a point is inside the body.
Definition: bodies.cpp:224
virtual void useDimensions(const shapes::Shape *shape)
Definition: bodies.cpp:720
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
TFSIMD_FORCE_INLINE tfScalar length2() const
virtual void useDimensions(const shapes::Shape *shape)
Definition: bodies.cpp:406
TFSIMD_FORCE_INLINE tfScalar length() const
TFSIMD_FORCE_INLINE Vector3 getColumn(int i) const
virtual void updateInternalData(void)
Definition: bodies.cpp:843
unsigned int countVerticesBehindPlane(const tf::tfVector4 &planeNormal) const
Definition: bodies.cpp:884


robot_self_filter
Author(s): Eitan Marder-Eppstein
autogenerated on Thu Jun 6 2019 19:59:05