FCL  0.6.0
Flexible Collision Library
mesh_shape_collision_traversal_node-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_TRAVERSAL_MESHSHAPECOLLISIONTRAVERSALNODE_INL_H
39 #define FCL_TRAVERSAL_MESHSHAPECOLLISIONTRAVERSALNODE_INL_H
40 
41 #include "fcl/narrowphase/detail/traversal/collision/mesh_shape_collision_traversal_node.h"
42 
43 namespace fcl
44 {
45 
46 namespace detail
47 {
48 
49 //==============================================================================
50 template <typename BV, typename Shape, typename NarrowPhaseSolver>
51 MeshShapeCollisionTraversalNode<BV, Shape, NarrowPhaseSolver>::MeshShapeCollisionTraversalNode()
52  : BVHShapeCollisionTraversalNode<BV, Shape>()
53 {
54  vertices = nullptr;
55  tri_indices = nullptr;
56 
57  nsolver = nullptr;
58 }
59 
60 //==============================================================================
61 template <typename BV, typename Shape, typename NarrowPhaseSolver>
63 {
64  if(this->enable_statistics) this->num_leaf_tests++;
65  const BVNode<BV>& node = this->model1->getBV(b1);
66 
67  int primitive_id = node.primitiveId();
68 
69  const Triangle& tri_id = tri_indices[primitive_id];
70 
71  const Vector3<S>& p1 = vertices[tri_id[0]];
72  const Vector3<S>& p2 = vertices[tri_id[1]];
73  const Vector3<S>& p3 = vertices[tri_id[2]];
74 
75  if(this->model1->isOccupied() && this->model2->isOccupied())
76  {
77  bool is_intersect = false;
78 
79  if(!this->request.enable_contact)
80  {
81  if(nsolver->shapeTriangleIntersect(*(this->model2), this->tf2, p1, p2, p3, nullptr, nullptr, nullptr))
82  {
83  is_intersect = true;
84  if(this->request.num_max_contacts > this->result->numContacts())
85  this->result->addContact(Contact<S>(this->model1, this->model2, primitive_id, Contact<S>::NONE));
86  }
87  }
88  else
89  {
90  S penetration;
91  Vector3<S> normal;
92  Vector3<S> contactp;
93 
94  if(nsolver->shapeTriangleIntersect(*(this->model2), this->tf2, p1, p2, p3, &contactp, &penetration, &normal))
95  {
96  is_intersect = true;
97  if(this->request.num_max_contacts > this->result->numContacts())
98  this->result->addContact(Contact<S>(this->model1, this->model2, primitive_id, Contact<S>::NONE, contactp, -normal, penetration));
99  }
100  }
101 
102  if(is_intersect && this->request.enable_cost)
103  {
104  AABB<S> overlap_part;
105  AABB<S> shape_aabb;
106  computeBV(*(this->model2), this->tf2, shape_aabb);
107  AABB<S>(p1, p2, p3).overlap(shape_aabb, overlap_part);
108  this->result->addCostSource(CostSource<S>(overlap_part, cost_density), this->request.num_max_cost_sources);
109  }
110  }
111  if((!this->model1->isFree() && !this->model2->isFree()) && this->request.enable_cost)
112  {
113  if(nsolver->shapeTriangleIntersect(*(this->model2), this->tf2, p1, p2, p3, nullptr, nullptr, nullptr))
114  {
115  AABB<S> overlap_part;
116  AABB<S> shape_aabb;
117  computeBV(*(this->model2), this->tf2, shape_aabb);
118  AABB<S>(p1, p2, p3).overlap(shape_aabb, overlap_part);
119  this->result->addCostSource(CostSource<S>(overlap_part, cost_density), this->request.num_max_cost_sources);
120  }
121  }
122 }
123 
124 //==============================================================================
125 template <typename BV, typename Shape, typename NarrowPhaseSolver>
127 {
128  return this->request.isSatisfied(*(this->result));
129 }
130 
131 //==============================================================================
132 template <typename BV, typename Shape, typename NarrowPhaseSolver>
133 bool initialize(
136  Transform3<typename BV::S>& tf1,
137  const Shape& model2,
138  const Transform3<typename BV::S>& tf2,
139  const NarrowPhaseSolver* nsolver,
142  bool use_refit,
143  bool refit_bottomup)
144 {
145  using S = typename BV::S;
146 
147  if(model1.getModelType() != BVH_MODEL_TRIANGLES)
148  return false;
149 
150  if(!tf1.matrix().isIdentity())
151  {
152  std::vector<Vector3<S>> vertices_transformed(model1.num_vertices);
153  for(int i = 0; i < model1.num_vertices; ++i)
154  {
155  Vector3<S>& p = model1.vertices[i];
156  Vector3<S> new_v = tf1 * p;
157  vertices_transformed[i] = new_v;
158  }
159 
160  model1.beginReplaceModel();
161  model1.replaceSubModel(vertices_transformed);
162  model1.endReplaceModel(use_refit, refit_bottomup);
163 
164  tf1.setIdentity();
165  }
166 
167  node.model1 = &model1;
168  node.tf1 = tf1;
169  node.model2 = &model2;
170  node.tf2 = tf2;
171  node.nsolver = nsolver;
172 
173  computeBV(model2, tf2, node.model2_bv);
174 
175  node.vertices = model1.vertices;
176  node.tri_indices = model1.tri_indices;
177 
178  node.request = request;
179  node.result = &result;
180 
181  node.cost_density = model1.cost_density * model2.cost_density;
182 
183  return true;
184 }
185 
186 //==============================================================================
187 template <typename BV, typename Shape, typename NarrowPhaseSolver>
188 void meshShapeCollisionOrientedNodeLeafTesting(
189  int b1, int b2,
190  const BVHModel<BV>* model1, const Shape& model2,
191  Vector3<typename BV::S>* vertices, Triangle* tri_indices,
192  const Transform3<typename BV::S>& tf1,
193  const Transform3<typename BV::S>& tf2,
194  const NarrowPhaseSolver* nsolver,
195  bool enable_statistics,
196  typename BV::S cost_density,
197  int& num_leaf_tests,
198  const CollisionRequest<typename BV::S>& request,
200 {
201  using S = typename BV::S;
202 
203  if(enable_statistics) num_leaf_tests++;
204  const BVNode<BV>& node = model1->getBV(b1);
205 
206  int primitive_id = node.primitiveId();
207 
208  const Triangle& tri_id = tri_indices[primitive_id];
209 
210  const Vector3<S>& p1 = vertices[tri_id[0]];
211  const Vector3<S>& p2 = vertices[tri_id[1]];
212  const Vector3<S>& p3 = vertices[tri_id[2]];
213 
214  if(model1->isOccupied() && model2.isOccupied())
215  {
216  bool is_intersect = false;
217 
218  if(!request.enable_contact) // only interested in collision or not
219  {
220  if(nsolver->shapeTriangleIntersect(model2, tf2, p1, p2, p3, tf1, nullptr, nullptr, nullptr))
221  {
222  is_intersect = true;
223  if(request.num_max_contacts > result.numContacts())
224  result.addContact(Contact<S>(model1, &model2, primitive_id, Contact<S>::NONE));
225  }
226  }
227  else
228  {
229  S penetration;
230  Vector3<S> normal;
231  Vector3<S> contactp;
232 
233  if(nsolver->shapeTriangleIntersect(model2, tf2, p1, p2, p3, tf1, &contactp, &penetration, &normal))
234  {
235  is_intersect = true;
236  if(request.num_max_contacts > result.numContacts())
237  result.addContact(Contact<S>(model1, &model2, primitive_id, Contact<S>::NONE, contactp, -normal, penetration));
238  }
239  }
240 
241  if(is_intersect && request.enable_cost)
242  {
243  AABB<S> overlap_part;
244  AABB<S> shape_aabb;
245  computeBV(model2, tf2, shape_aabb);
246  /* bool res = */ AABB<S>(tf1 * p1, tf1 * p2, tf1 * p3).overlap(shape_aabb, overlap_part);
247  result.addCostSource(CostSource<S>(overlap_part, cost_density), request.num_max_cost_sources);
248  }
249  }
250  else if((!model1->isFree() || model2.isFree()) && request.enable_cost)
251  {
252  if(nsolver->shapeTriangleIntersect(model2, tf2, p1, p2, p3, tf1, nullptr, nullptr, nullptr))
253  {
254  AABB<S> overlap_part;
255  AABB<S> shape_aabb;
256  computeBV(model2, tf2, shape_aabb);
257  /* bool res = */ AABB<S>(tf1 * p1, tf1 * p2, tf1 * p3).overlap(shape_aabb, overlap_part);
258  result.addCostSource(CostSource<S>(overlap_part, cost_density), request.num_max_cost_sources);
259  }
260  }
261 }
262 
263 //==============================================================================
264 template <typename Shape, typename NarrowPhaseSolver>
267  : MeshShapeCollisionTraversalNode<OBB<typename Shape::S>, Shape, NarrowPhaseSolver>()
268 {
269 }
270 
271 //==============================================================================
272 template <typename Shape, typename NarrowPhaseSolver>
274 {
275  if(this->enable_statistics) this->num_bv_tests++;
276 
277  return !overlap(this->tf1.linear(), this->tf1.translation(), this->model2_bv, this->model1->getBV(b1).bv);
278 }
279 
280 //==============================================================================
281 template <typename Shape, typename NarrowPhaseSolver>
283 {
284  detail::meshShapeCollisionOrientedNodeLeafTesting(b1, b2, this->model1, *(this->model2), this->vertices, this->tri_indices,
285  this->tf1, this->tf2, this->nsolver, this->enable_statistics, this->cost_density, this->num_leaf_tests, this->request, *(this->result));
286 }
287 
288 //==============================================================================
289 template <typename Shape, typename NarrowPhaseSolver>
291  : MeshShapeCollisionTraversalNode<RSS<typename Shape::S>, Shape, NarrowPhaseSolver>()
292 {
293 }
294 
295 //==============================================================================
296 template <typename Shape, typename NarrowPhaseSolver>
298 {
299  if(this->enable_statistics) this->num_bv_tests++;
300 
301  return !overlap(this->tf1.linear(), this->tf1.translation(), this->model2_bv, this->model1->getBV(b1).bv);
302 }
303 
304 //==============================================================================
305 template <typename Shape, typename NarrowPhaseSolver>
307 {
308  detail::meshShapeCollisionOrientedNodeLeafTesting(b1, b2, this->model1, *(this->model2), this->vertices, this->tri_indices,
309  this->tf1, this->tf2, this->nsolver, this->enable_statistics, this->cost_density, this->num_leaf_tests, this->request, *(this->result));
310 }
311 
312 //==============================================================================
313 template <typename Shape, typename NarrowPhaseSolver>
316  : MeshShapeCollisionTraversalNode<kIOS<typename Shape::S>, Shape, NarrowPhaseSolver>()
317 {
318 }
319 
320 //==============================================================================
321 template <typename Shape, typename NarrowPhaseSolver>
323 {
324  if(this->enable_statistics) this->num_bv_tests++;
325 
326  return !overlap(this->tf1.linear(), this->tf1.translation(), this->model2_bv, this->model1->getBV(b1).bv);
327 }
328 
329 //==============================================================================
330 template <typename Shape, typename NarrowPhaseSolver>
332 {
333  detail::meshShapeCollisionOrientedNodeLeafTesting(b1, b2, this->model1, *(this->model2), this->vertices, this->tri_indices,
334  this->tf1, this->tf2, this->nsolver, this->enable_statistics, this->cost_density, this->num_leaf_tests, this->request, *(this->result));
335 }
336 
337 //==============================================================================
338 template <typename Shape, typename NarrowPhaseSolver>
341  : MeshShapeCollisionTraversalNode<OBBRSS<typename Shape::S>, Shape, NarrowPhaseSolver>()
342 {
343 }
344 
345 //==============================================================================
346 template <typename Shape, typename NarrowPhaseSolver>
348 {
349  if(this->enable_statistics) this->num_bv_tests++;
350  return !overlap(this->tf1.linear(), this->tf1.translation(), this->model2_bv, this->model1->getBV(b1).bv);
351 }
352 
353 //==============================================================================
354 template <typename Shape, typename NarrowPhaseSolver>
356 {
357  detail::meshShapeCollisionOrientedNodeLeafTesting(b1, b2, this->model1, *(this->model2), this->vertices, this->tri_indices,
358  this->tf1, this->tf2, this->nsolver, this->enable_statistics, this->cost_density, this->num_leaf_tests, this->request, *(this->result));
359 }
360 
361 template <typename BV, typename Shape, typename NarrowPhaseSolver,
362  template <typename, typename> class OrientedNode>
363 bool setupMeshShapeCollisionOrientedNode(
364  OrientedNode<Shape, NarrowPhaseSolver>& node,
365  const BVHModel<BV>& model1,
366  const Transform3<typename BV::S>& tf1,
367  const Shape& model2, const Transform3<typename BV::S>& tf2,
368  const NarrowPhaseSolver* nsolver,
369  const CollisionRequest<typename BV::S>& request,
371 {
372  if(model1.getModelType() != BVH_MODEL_TRIANGLES)
373  return false;
374 
375  node.model1 = &model1;
376  node.tf1 = tf1;
377  node.model2 = &model2;
378  node.tf2 = tf2;
379  node.nsolver = nsolver;
380 
381  computeBV(model2, tf2, node.model2_bv);
382 
383  node.vertices = model1.vertices;
384  node.tri_indices = model1.tri_indices;
385 
386  node.request = request;
387  node.result = &result;
388 
389  node.cost_density = model1.cost_density * model2.cost_density;
390 
391  return true;
392 }
393 
394 //==============================================================================
395 template <typename Shape, typename NarrowPhaseSolver>
396 bool initialize(
398  const BVHModel<OBB<typename Shape::S>>& model1,
399  const Transform3<typename Shape::S>& tf1,
400  const Shape& model2,
401  const Transform3<typename Shape::S>& tf2,
402  const NarrowPhaseSolver* nsolver,
405 {
406  return detail::setupMeshShapeCollisionOrientedNode(
407  node, model1, tf1, model2, tf2, nsolver, request, result);
408 }
409 
410 //==============================================================================
411 template <typename Shape, typename NarrowPhaseSolver>
412 bool initialize(
414  const BVHModel<RSS<typename Shape::S>>& model1,
415  const Transform3<typename Shape::S>& tf1,
416  const Shape& model2,
417  const Transform3<typename Shape::S>& tf2,
418  const NarrowPhaseSolver* nsolver,
421 {
422  return detail::setupMeshShapeCollisionOrientedNode(
423  node, model1, tf1, model2, tf2, nsolver, request, result);
424 }
425 
426 //==============================================================================
427 template <typename Shape, typename NarrowPhaseSolver>
428 bool initialize(
430  const BVHModel<kIOS<typename Shape::S>>& model1,
431  const Transform3<typename Shape::S>& tf1,
432  const Shape& model2,
433  const Transform3<typename Shape::S>& tf2,
434  const NarrowPhaseSolver* nsolver,
437 {
438  return detail::setupMeshShapeCollisionOrientedNode(
439  node, model1, tf1, model2, tf2, nsolver, request, result);
440 }
441 
442 //==============================================================================
443 template <typename Shape, typename NarrowPhaseSolver>
444 bool initialize(
446  const BVHModel<OBBRSS<typename Shape::S>>& model1,
447  const Transform3<typename Shape::S>& tf1,
448  const Shape& model2,
449  const Transform3<typename Shape::S>& tf2,
450  const NarrowPhaseSolver* nsolver,
453 {
454  return detail::setupMeshShapeCollisionOrientedNode(
455  node, model1, tf1, model2, tf2, nsolver, request, result);
456 }
457 
458 } // namespace detail
459 } // namespace fcl
460 
461 #endif
bool BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: mesh_shape_collision_traversal_node-inl.h:347
void leafTesting(int b1, int b2) const
Leaf test between node b1 and b2, if they are both leafs.
Definition: mesh_shape_collision_traversal_node-inl.h:282
Traversal node for collision between mesh and shape.
Definition: mesh_shape_collision_traversal_node.h:52
void leafTesting(int b1, int b2) const
Leaf test between node b1 and b2, if they are both leafs.
Definition: mesh_shape_collision_traversal_node-inl.h:331
bool enable_cost
whether the cost sources will be computed
Definition: collision_request.h:64
bool enable_statistics
Whether stores statistics.
Definition: collision_traversal_node_base.h:78
void addCostSource(const CostSource< S > &c, std::size_t num_max_cost_sources)
add one cost source into result structure
Definition: collision_result-inl.h:66
size_t num_max_contacts
The maximum number of contacts will return.
Definition: collision_request.h:55
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
int replaceSubModel(const std::vector< Vector3< S >> &ps)
Replace a set of points in the old BVH model.
Definition: BVH_model-inl.h:559
collision result
Definition: collision_request.h:48
A class for rectangle sphere-swept bounding volume.
Definition: RSS.h:49
int beginReplaceModel()
Replace the geometry information of current frame (i.e. should have the same mesh topology with the p...
Definition: BVH_model-inl.h:508
BVHModelType getModelType() const
Model type described by the instance.
Definition: BVH_model-inl.h:48
bool overlap(const Eigen::MatrixBase< DerivedA > &R0, const Eigen::MatrixBase< DerivedB > &T0, const kIOS< S > &b1, const kIOS< S > &b2)
Check collision between two kIOSs, b1 is in configuration (R0, T0) and b2 is in identity.
Definition: kIOS-inl.h:249
const BVNode< BV > & getBV(int id) const
We provide getBV() and getNumBVs() because BVH may be compressed (in future), so we must provide some...
Definition: BVH_model-inl.h:160
void leafTesting(int b1, int b2) const
Intersection testing between leaves (one triangle and one shape)
Definition: mesh_shape_collision_traversal_node-inl.h:62
Transform3< BV::S > tf2
configuration of second object
Definition: traversal_node_base.h:88
Contact information returned by collision.
Definition: contact.h:48
size_t numContacts() const
number of contacts found
Definition: collision_result-inl.h:83
Vector3< S > * vertices
Geometry point data.
Definition: BVH_model.h:162
bool BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: mesh_shape_collision_traversal_node-inl.h:273
int num_vertices
Number of points.
Definition: BVH_model.h:174
CollisionRequest< BV::S > request
request setting for collision
Definition: collision_traversal_node_base.h:72
const BVHModel< BV > * model1
The first BVH model.
Definition: bvh_collision_traversal_node.h:86
bool isFree() const
whether the object is completely free
int primitiveId() const
Return the primitive index. The index is referred to the original data (i.e. vertices or tri_indices)...
Definition: BV_node_base.cpp:50
Triangle * tri_indices
Geometry triangle index data, will be nullptr for point clouds.
Definition: BVH_model.h:165
Triangle with 3 indices for points.
Definition: triangle.h:47
bool BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: mesh_shape_collision_traversal_node-inl.h:297
Definition: mesh_shape_collision_traversal_node.h:189
bool canStop() const
Whether the traversal process can stop early.
Definition: mesh_shape_collision_traversal_node-inl.h:126
unknown model type
Definition: BVH_internal.h:78
void leafTesting(int b1, int b2) const
Leaf test between node b1 and b2, if they are both leafs.
Definition: mesh_shape_collision_traversal_node-inl.h:306
bool enable_contact
whether the contact information (normal, penetration depth and contact position) will return ...
Definition: collision_request.h:58
Traversal node for mesh and shape, when mesh BVH is one of the oriented node (OBB, RSS, OBBRSS, kIOS)
Definition: mesh_shape_collision_traversal_node.h:108
request to the collision algorithm
Definition: collision_request.h:52
size_t num_max_cost_sources
The maximum number of cost sources will return.
Definition: collision_request.h:61
void computeBV(const Shape &s, const Transform3< typename BV::S > &tf, BV &bv)
calculate a bounding volume for a shape in a specific configuration
Definition: utility-inl.h:1049
A class describing the bounding hierarchy of a mesh model or a point cloud model (which is viewed as ...
Definition: BVH_model.h:57
BV::S cost_density
collision cost for unit volume
Definition: collision_geometry.h:103
CollisionResult< BV::S > * result
collision result kept during the traversal iteration
Definition: collision_traversal_node_base.h:75
A class describing a bounding volume node. It includes the tree structure providing in BVNodeBase and...
Definition: BV_node.h:52
Transform3< BV::S > tf1
configuation of first object
Definition: traversal_node_base.h:85
Cost source describes an area with a cost. The area is described by an AABB<S> region.
Definition: cost_source.h:49
int num_bv_tests
statistical information
Definition: bvh_collision_traversal_node.h:92
void leafTesting(int b1, int b2) const
Leaf test between node b1 and b2, if they are both leafs.
Definition: mesh_shape_collision_traversal_node-inl.h:355
bool BVTesting(int b1, int b2) const
BV test between b1 and b2.
Definition: mesh_shape_collision_traversal_node-inl.h:322
Class merging the OBB and RSS, can handle collision and distance simultaneously.
Definition: OBBRSS.h:50
Definition: mesh_shape_collision_traversal_node.h:162
bool isOccupied() const
whether the object is completely occupied
const BVHModel< BV > * model2
The second BVH model.
Definition: bvh_collision_traversal_node.h:89
int endReplaceModel(bool refit=true, bool bottomup=true)
End BVH model replacement, will also refit or rebuild the bounding volume hierarchy.
Definition: BVH_model-inl.h:577
A class describing the kIOS collision structure, which is a set of spheres.
Definition: kIOS.h:48
Definition: mesh_shape_collision_traversal_node.h:135
Oriented bounding box class.
Definition: OBB.h:51
void addContact(const Contact< S > &c)
add one contact into result structure
Definition: collision_result-inl.h:59