Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gsaurel/hpp-fcl
  • coal-library/coal
2 results
Show changes
Showing
with 2470 additions and 702 deletions
......@@ -35,208 +35,232 @@
/** \author Jia Pan */
#ifndef FCL_AABB_H
#define FCL_AABB_H
#ifndef COAL_AABB_H
#define COAL_AABB_H
#include "coal/data_types.h"
#include "fcl/math/vec_3f.h"
namespace coal {
namespace fcl
{
struct CollisionRequest;
class Plane;
class Halfspace;
/// @brief A class describing the AABB collision structure, which is a box in 3D space determined by two diagonal points
class AABB
{
public:
/// @defgroup Bounding_Volume Bounding volumes
/// Classes of different types of bounding volume.
/// @{
/// @brief A class describing the AABB collision structure, which is a box in 3D
/// space determined by two diagonal points
class COAL_DLLAPI AABB {
public:
/// @brief The min point in the AABB
Vec3f min_;
Vec3s min_;
/// @brief The max point in the AABB
Vec3f max_;
Vec3s max_;
/// @brief Creating an AABB with zero size (low bound +inf, upper bound -inf)
AABB();
/// @brief Creating an AABB at position v with zero size
AABB(const Vec3f& v) : min_(v), max_(v)
{
}
AABB(const Vec3s& v) : min_(v), max_(v) {}
/// @brief Creating an AABB with two endpoints a and b
AABB(const Vec3f& a, const Vec3f&b) : min_(min(a, b)),
max_(max(a, b))
{
}
AABB(const Vec3s& a, const Vec3s& b)
: min_(a.cwiseMin(b)), max_(a.cwiseMax(b)) {}
/// @brief Creating an AABB centered as core and is of half-dimension delta
AABB(const AABB& core, const Vec3f& delta) : min_(core.min_ - delta),
max_(core.max_ + delta)
{
}
AABB(const AABB& core, const Vec3s& delta)
: min_(core.min_ - delta), max_(core.max_ + delta) {}
/// @brief Creating an AABB contains three points
AABB(const Vec3f& a, const Vec3f& b, const Vec3f& c) : min_(min(min(a, b), c)),
max_(max(max(a, b), c))
{
}
AABB(const Vec3s& a, const Vec3s& b, const Vec3s& c)
: min_(a.cwiseMin(b).cwiseMin(c)), max_(a.cwiseMax(b).cwiseMax(c)) {}
/// @brief Check whether two AABB are overlap
inline bool overlap(const AABB& other) const
{
if(min_[0] > other.max_[0]) return false;
if(min_[1] > other.max_[1]) return false;
if(min_[2] > other.max_[2]) return false;
AABB(const AABB& other) = default;
if(max_[0] < other.min_[0]) return false;
if(max_[1] < other.min_[1]) return false;
if(max_[2] < other.min_[2]) return false;
AABB& operator=(const AABB& other) = default;
return true;
}
AABB& update(const Vec3s& a, const Vec3s& b) {
min_ = a.cwiseMin(b);
max_ = a.cwiseMax(b);
return *this;
}
/// @brief Check whether the AABB contains another AABB
inline bool contain(const AABB& other) const
{
return (other.min_[0] >= min_[0]) && (other.max_[0] <= max_[0]) && (other.min_[1] >= min_[1]) && (other.max_[1] <= max_[1]) && (other.min_[2] >= min_[2]) && (other.max_[2] <= max_[2]);
/// @brief Comparison operator
bool operator==(const AABB& other) const {
return min_ == other.min_ && max_ == other.max_;
}
bool operator!=(const AABB& other) const { return !(*this == other); }
/// @brief Check whether two AABB are overlapped along specific axis
inline bool axisOverlap(const AABB& other, int axis_id) const
{
if(min_[axis_id] > other.max_[axis_id]) return false;
/// @name Bounding volume API
/// Common API to BVs.
/// @{
if(max_[axis_id] < other.min_[axis_id]) return false;
/// @brief Check whether the AABB contains a point
inline bool contain(const Vec3s& p) const {
if (p[0] < min_[0] || p[0] > max_[0]) return false;
if (p[1] < min_[1] || p[1] > max_[1]) return false;
if (p[2] < min_[2] || p[2] > max_[2]) return false;
return true;
}
/// @brief Check whether two AABB are overlap and return the overlap part
inline bool overlap(const AABB& other, AABB& overlap_part) const
{
if(!overlap(other))
{
return false;
}
overlap_part.min_ = max(min_, other.min_);
overlap_part.max_ = min(max_, other.max_);
/// @brief Check whether two AABB are overlap
inline bool overlap(const AABB& other) const {
if (min_[0] > other.max_[0]) return false;
if (min_[1] > other.max_[1]) return false;
if (min_[2] > other.max_[2]) return false;
if (max_[0] < other.min_[0]) return false;
if (max_[1] < other.min_[1]) return false;
if (max_[2] < other.min_[2]) return false;
return true;
}
/// @brief Check whether AABB overlaps a plane
bool overlap(const Plane& p) const;
/// @brief Check whether the AABB contains a point
inline bool contain(const Vec3f& p) const
{
if(p[0] < min_[0] || p[0] > max_[0]) return false;
if(p[1] < min_[1] || p[1] > max_[1]) return false;
if(p[2] < min_[2] || p[2] > max_[2]) return false;
/// @brief Check whether AABB overlaps a halfspace
bool overlap(const Halfspace& hs) const;
return true;
}
/// @brief Check whether two AABB are overlap
bool overlap(const AABB& other, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) const;
/// @brief Distance between two AABBs
CoalScalar distance(const AABB& other) const;
/// @brief Distance between two AABBs; P and Q, should not be NULL, return the
/// nearest points
CoalScalar distance(const AABB& other, Vec3s* P, Vec3s* Q) const;
/// @brief Merge the AABB and a point
inline AABB& operator += (const Vec3f& p)
{
min_.ubound(p);
max_.lbound(p);
inline AABB& operator+=(const Vec3s& p) {
min_ = min_.cwiseMin(p);
max_ = max_.cwiseMax(p);
return *this;
}
/// @brief Merge the AABB and another AABB
inline AABB& operator += (const AABB& other)
{
min_.ubound(other.min_);
max_.lbound(other.max_);
inline AABB& operator+=(const AABB& other) {
min_ = min_.cwiseMin(other.min_);
max_ = max_.cwiseMax(other.max_);
return *this;
}
/// @brief Return the merged AABB of current AABB and the other one
inline AABB operator + (const AABB& other) const
{
inline AABB operator+(const AABB& other) const {
AABB res(*this);
return res += other;
}
/// @brief Size of the AABB (used in BV_Splitter to order two AABBs)
inline CoalScalar size() const { return (max_ - min_).squaredNorm(); }
/// @brief Center of the AABB
inline Vec3s center() const { return (min_ + max_) * 0.5; }
/// @brief Width of the AABB
inline FCL_REAL width() const
{
return max_[0] - min_[0];
}
inline CoalScalar width() const { return max_[0] - min_[0]; }
/// @brief Height of the AABB
inline FCL_REAL height() const
{
return max_[1] - min_[1];
}
inline CoalScalar height() const { return max_[1] - min_[1]; }
/// @brief Depth of the AABB
inline FCL_REAL depth() const
{
return max_[2] - min_[2];
}
inline CoalScalar depth() const { return max_[2] - min_[2]; }
/// @brief Volume of the AABB
inline FCL_REAL volume() const
{
return width() * height() * depth();
}
inline CoalScalar volume() const { return width() * height() * depth(); }
/// @brief Size of the AABB (used in BV_Splitter to order two AABBs)
inline FCL_REAL size() const
{
return (max_ - min_).sqrLength();
}
/// @}
/// @brief Radius of the AABB
inline FCL_REAL radius() const
{
return (max_ - min_).length() / 2;
/// @brief Check whether the AABB contains another AABB
inline bool contain(const AABB& other) const {
return (other.min_[0] >= min_[0]) && (other.max_[0] <= max_[0]) &&
(other.min_[1] >= min_[1]) && (other.max_[1] <= max_[1]) &&
(other.min_[2] >= min_[2]) && (other.max_[2] <= max_[2]);
}
/// @brief Center of the AABB
inline Vec3f center() const
{
return (min_ + max_) * 0.5;
}
/// @brief Check whether two AABB are overlap and return the overlap part
inline bool overlap(const AABB& other, AABB& overlap_part) const {
if (!overlap(other)) {
return false;
}
/// @brief Distance between two AABBs; P and Q, should not be NULL, return the nearest points
FCL_REAL distance(const AABB& other, Vec3f* P, Vec3f* Q) const;
overlap_part.min_ = min_.cwiseMax(other.min_);
overlap_part.max_ = max_.cwiseMin(other.max_);
return true;
}
/// @brief Distance between two AABBs
FCL_REAL distance(const AABB& other) const;
/// @brief Check whether two AABB are overlapped along specific axis
inline bool axisOverlap(const AABB& other, int axis_id) const {
if (min_[axis_id] > other.max_[axis_id]) return false;
if (max_[axis_id] < other.min_[axis_id]) return false;
/// @brief whether two AABB are equal
inline bool equal(const AABB& other) const
{
return min_.equal(other.min_) && max_.equal(other.max_);
return true;
}
/// @brief expand the half size of the AABB by delta, and keep the center unchanged.
inline AABB& expand(const Vec3f& delta)
{
/// @brief expand the half size of the AABB by delta, and keep the center
/// unchanged.
inline AABB& expand(const Vec3s& delta) {
min_ -= delta;
max_ += delta;
return *this;
}
/// @brief expand the half size of the AABB by a scalar delta, and keep the
/// center unchanged.
inline AABB& expand(const CoalScalar delta) {
min_.array() -= delta;
max_.array() += delta;
return *this;
}
/// @brief expand the aabb by increase the thickness of the plate by a ratio
inline AABB& expand(const AABB& core, FCL_REAL ratio)
{
inline AABB& expand(const AABB& core, CoalScalar ratio) {
min_ = min_ * ratio - core.min_;
max_ = max_ * ratio - core.max_;
return *this;
}
}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
/// @brief translate the center of AABB by t
static inline AABB translate(const AABB& aabb, const Vec3f& t)
{
static inline AABB translate(const AABB& aabb, const Vec3s& t) {
AABB res(aabb);
res.min_ += t;
res.max_ += t;
return res;
}
static inline AABB rotate(const AABB& aabb, const Matrix3s& R) {
AABB res(R * aabb.min_);
Vec3s corner(aabb.min_);
const Eigen::DenseIndex bit[3] = {1, 2, 4};
for (Eigen::DenseIndex ic = 1; ic < 8;
++ic) { // ic = 0 corresponds to aabb.min_. Skip it.
for (Eigen::DenseIndex i = 0; i < 3; ++i) {
corner[i] = (ic & bit[i]) ? aabb.max_[i] : aabb.min_[i];
}
res += R * corner;
}
return res;
}
/// @brief Check collision between two aabbs, b1 is in configuration (R0, T0)
/// and b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const AABB& b1,
const AABB& b2);
/// @brief Check collision between two aabbs, b1 is in configuration (R0, T0)
/// and b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const AABB& b1,
const AABB& b2, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound);
} // namespace coal
#endif
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Open Source Robotics Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** \author Jia Pan */
#ifndef COAL_BV_H
#define COAL_BV_H
#include "coal/BV/kDOP.h"
#include "coal/BV/AABB.h"
#include "coal/BV/OBB.h"
#include "coal/BV/RSS.h"
#include "coal/BV/OBBRSS.h"
#include "coal/BV/kIOS.h"
#include "coal/math/transform.h"
/** @brief Main namespace */
namespace coal {
/// @cond IGNORE
namespace details {
/// @brief Convert a bounding volume of type BV1 in configuration tf1 to a
/// bounding volume of type BV2 in I configuration.
template <typename BV1, typename BV2>
struct Converter {
static void convert(const BV1& bv1, const Transform3s& tf1, BV2& bv2);
static void convert(const BV1& bv1, BV2& bv2);
};
/// @brief Convert from AABB to AABB, not very tight but is fast.
template <>
struct Converter<AABB, AABB> {
static void convert(const AABB& bv1, const Transform3s& tf1, AABB& bv2) {
const Vec3s& center = bv1.center();
CoalScalar r = (bv1.max_ - bv1.min_).norm() * 0.5;
const Vec3s center2 = tf1.transform(center);
bv2.min_ = center2 - Vec3s::Constant(r);
bv2.max_ = center2 + Vec3s::Constant(r);
}
static void convert(const AABB& bv1, AABB& bv2) { bv2 = bv1; }
};
template <>
struct Converter<AABB, OBB> {
static void convert(const AABB& bv1, const Transform3s& tf1, OBB& bv2) {
bv2.To = tf1.transform(bv1.center());
bv2.extent.noalias() = (bv1.max_ - bv1.min_) * 0.5;
bv2.axes = tf1.getRotation();
}
static void convert(const AABB& bv1, OBB& bv2) {
bv2.To = bv1.center();
bv2.extent.noalias() = (bv1.max_ - bv1.min_) * 0.5;
bv2.axes.setIdentity();
}
};
template <>
struct Converter<OBB, OBB> {
static void convert(const OBB& bv1, const Transform3s& tf1, OBB& bv2) {
bv2.extent = bv1.extent;
bv2.To = tf1.transform(bv1.To);
bv2.axes.noalias() = tf1.getRotation() * bv1.axes;
}
static void convert(const OBB& bv1, OBB& bv2) { bv2 = bv1; }
};
template <>
struct Converter<OBBRSS, OBB> {
static void convert(const OBBRSS& bv1, const Transform3s& tf1, OBB& bv2) {
Converter<OBB, OBB>::convert(bv1.obb, tf1, bv2);
}
static void convert(const OBBRSS& bv1, OBB& bv2) {
Converter<OBB, OBB>::convert(bv1.obb, bv2);
}
};
template <>
struct Converter<RSS, OBB> {
static void convert(const RSS& bv1, const Transform3s& tf1, OBB& bv2) {
bv2.extent = Vec3s(bv1.length[0] * 0.5 + bv1.radius,
bv1.length[1] * 0.5 + bv1.radius, bv1.radius);
bv2.To = tf1.transform(bv1.Tr);
bv2.axes.noalias() = tf1.getRotation() * bv1.axes;
}
static void convert(const RSS& bv1, OBB& bv2) {
bv2.extent = Vec3s(bv1.length[0] * 0.5 + bv1.radius,
bv1.length[1] * 0.5 + bv1.radius, bv1.radius);
bv2.To = bv1.Tr;
bv2.axes = bv1.axes;
}
};
template <typename BV1>
struct Converter<BV1, AABB> {
static void convert(const BV1& bv1, const Transform3s& tf1, AABB& bv2) {
const Vec3s& center = bv1.center();
CoalScalar r = Vec3s(bv1.width(), bv1.height(), bv1.depth()).norm() * 0.5;
const Vec3s center2 = tf1.transform(center);
bv2.min_ = center2 - Vec3s::Constant(r);
bv2.max_ = center2 + Vec3s::Constant(r);
}
static void convert(const BV1& bv1, AABB& bv2) {
const Vec3s& center = bv1.center();
CoalScalar r = Vec3s(bv1.width(), bv1.height(), bv1.depth()).norm() * 0.5;
bv2.min_ = center - Vec3s::Constant(r);
bv2.max_ = center + Vec3s::Constant(r);
}
};
template <typename BV1>
struct Converter<BV1, OBB> {
static void convert(const BV1& bv1, const Transform3s& tf1, OBB& bv2) {
AABB bv;
Converter<BV1, AABB>::convert(bv1, bv);
Converter<AABB, OBB>::convert(bv, tf1, bv2);
}
static void convert(const BV1& bv1, OBB& bv2) {
AABB bv;
Converter<BV1, AABB>::convert(bv1, bv);
Converter<AABB, OBB>::convert(bv, bv2);
}
};
template <>
struct Converter<OBB, RSS> {
static void convert(const OBB& bv1, const Transform3s& tf1, RSS& bv2) {
bv2.Tr = tf1.transform(bv1.To);
bv2.axes.noalias() = tf1.getRotation() * bv1.axes;
bv2.radius = bv1.extent[2];
bv2.length[0] = 2 * (bv1.extent[0] - bv2.radius);
bv2.length[1] = 2 * (bv1.extent[1] - bv2.radius);
}
static void convert(const OBB& bv1, RSS& bv2) {
bv2.Tr = bv1.To;
bv2.axes = bv1.axes;
bv2.radius = bv1.extent[2];
bv2.length[0] = 2 * (bv1.extent[0] - bv2.radius);
bv2.length[1] = 2 * (bv1.extent[1] - bv2.radius);
}
};
template <>
struct Converter<RSS, RSS> {
static void convert(const RSS& bv1, const Transform3s& tf1, RSS& bv2) {
bv2.Tr = tf1.transform(bv1.Tr);
bv2.axes.noalias() = tf1.getRotation() * bv1.axes;
bv2.radius = bv1.radius;
bv2.length[0] = bv1.length[0];
bv2.length[1] = bv1.length[1];
}
static void convert(const RSS& bv1, RSS& bv2) { bv2 = bv1; }
};
template <>
struct Converter<OBBRSS, RSS> {
static void convert(const OBBRSS& bv1, const Transform3s& tf1, RSS& bv2) {
Converter<RSS, RSS>::convert(bv1.rss, tf1, bv2);
}
static void convert(const OBBRSS& bv1, RSS& bv2) {
Converter<RSS, RSS>::convert(bv1.rss, bv2);
}
};
template <>
struct Converter<AABB, RSS> {
static void convert(const AABB& bv1, const Transform3s& tf1, RSS& bv2) {
bv2.Tr = tf1.transform(bv1.center());
/// Sort the AABB edges so that AABB extents are ordered.
CoalScalar d[3] = {bv1.width(), bv1.height(), bv1.depth()};
Eigen::DenseIndex id[3] = {0, 1, 2};
for (Eigen::DenseIndex i = 1; i < 3; ++i) {
for (Eigen::DenseIndex j = i; j > 0; --j) {
if (d[j] > d[j - 1]) {
{
CoalScalar tmp = d[j];
d[j] = d[j - 1];
d[j - 1] = tmp;
}
{
Eigen::DenseIndex tmp = id[j];
id[j] = id[j - 1];
id[j - 1] = tmp;
}
}
}
}
const Vec3s extent = (bv1.max_ - bv1.min_) * 0.5;
bv2.radius = extent[id[2]];
bv2.length[0] = (extent[id[0]] - bv2.radius) * 2;
bv2.length[1] = (extent[id[1]] - bv2.radius) * 2;
const Matrix3s& R = tf1.getRotation();
const bool left_hand = (id[0] == (id[1] + 1) % 3);
if (left_hand)
bv2.axes.col(0) = -R.col(id[0]);
else
bv2.axes.col(0) = R.col(id[0]);
bv2.axes.col(1) = R.col(id[1]);
bv2.axes.col(2) = R.col(id[2]);
}
static void convert(const AABB& bv1, RSS& bv2) {
convert(bv1, Transform3s(), bv2);
}
};
template <>
struct Converter<AABB, OBBRSS> {
static void convert(const AABB& bv1, const Transform3s& tf1, OBBRSS& bv2) {
Converter<AABB, OBB>::convert(bv1, tf1, bv2.obb);
Converter<AABB, RSS>::convert(bv1, tf1, bv2.rss);
}
static void convert(const AABB& bv1, OBBRSS& bv2) {
Converter<AABB, OBB>::convert(bv1, bv2.obb);
Converter<AABB, RSS>::convert(bv1, bv2.rss);
}
};
} // namespace details
/// @endcond
/// @brief Convert a bounding volume of type BV1 in configuration tf1 to
/// bounding volume of type BV2 in identity configuration.
template <typename BV1, typename BV2>
static inline void convertBV(const BV1& bv1, const Transform3s& tf1, BV2& bv2) {
details::Converter<BV1, BV2>::convert(bv1, tf1, bv2);
}
/// @brief Convert a bounding volume of type BV1 to bounding volume of type BV2
/// in identity configuration.
template <typename BV1, typename BV2>
static inline void convertBV(const BV1& bv1, BV2& bv2) {
details::Converter<BV1, BV2>::convert(bv1, bv2);
}
} // namespace coal
#endif
......@@ -35,99 +35,132 @@
/** \author Jia Pan */
#ifndef COAL_BV_NODE_H
#define COAL_BV_NODE_H
#ifndef FCL_BV_NODE_H
#define FCL_BV_NODE_H
#include "coal/data_types.h"
#include "coal/BV/BV.h"
#include "fcl/math/vec_3f.h"
#include "fcl/math/matrix_3f.h"
namespace coal {
#include "fcl/BV/BV.h"
#include <iostream>
namespace fcl
{
/// @defgroup Construction_Of_BVH Construction of BVHModel
/// Classes which are used to build a BVHModel (Bounding Volume Hierarchy)
/// @{
/// @brief BVNodeBase encodes the tree structure for BVH
struct BVNodeBase
{
struct COAL_DLLAPI BVNodeBase {
/// @brief An index for first child node or primitive
/// If the value is positive, it is the index of the first child bv node
/// If the value is negative, it is -(primitive index + 1)
/// Zero is not used.
int first_child;
/// @brief The start id the primitive belonging to the current node. The index is referred to the primitive_indices in BVHModel and from that
/// we can obtain the primitive's index in original data indirectly.
int first_primitive;
/// @brief The start id the primitive belonging to the current node. The index
/// is referred to the primitive_indices in BVHModel and from that we can
/// obtain the primitive's index in original data indirectly.
unsigned int first_primitive;
/// @brief The number of primitives belonging to the current node
unsigned int num_primitives;
/// @brief Default constructor
BVNodeBase()
: first_child(0),
first_primitive(
(std::numeric_limits<unsigned int>::max)()) // value we should help
// to raise an issue
,
num_primitives(0) {}
/// @brief Equality operator
bool operator==(const BVNodeBase& other) const {
return first_child == other.first_child &&
first_primitive == other.first_primitive &&
num_primitives == other.num_primitives;
}
/// @brief The number of primitives belonging to the current node
int num_primitives;
/// @brief Difference operator
bool operator!=(const BVNodeBase& other) const { return !(*this == other); }
/// @brief Whether current node is a leaf node (i.e. contains a primitive index
/// @brief Whether current node is a leaf node (i.e. contains a primitive
/// index
inline bool isLeaf() const { return first_child < 0; }
/// @brief Return the primitive index. The index is referred to the original data (i.e. vertices or tri_indices) in BVHModel
/// @brief Return the primitive index. The index is referred to the original
/// data (i.e. vertices or tri_indices) in BVHModel
inline int primitiveId() const { return -(first_child + 1); }
/// @brief Return the index of the first child. The index is referred to the bounding volume array (i.e. bvs) in BVHModel
/// @brief Return the index of the first child. The index is referred to the
/// bounding volume array (i.e. bvs) in BVHModel
inline int leftChild() const { return first_child; }
/// @brief Return the index of the second child. The index is referred to the bounding volume array (i.e. bvs) in BVHModel
/// @brief Return the index of the second child. The index is referred to the
/// bounding volume array (i.e. bvs) in BVHModel
inline int rightChild() const { return first_child + 1; }
};
/// @brief A class describing a bounding volume node. It includes the tree structure providing in BVNodeBase and also the geometry data provided in BV template parameter.
template<typename BV>
struct BVNode : public BVNodeBase
{
/// @brief A class describing a bounding volume node. It includes the tree
/// structure providing in BVNodeBase and also the geometry data provided in BV
/// template parameter.
template <typename BV>
struct COAL_DLLAPI BVNode : public BVNodeBase {
typedef BVNodeBase Base;
/// @brief bounding volume storing the geometry
BV bv;
/// @brief Equality operator
bool operator==(const BVNode& other) const {
return Base::operator==(other) && bv == other.bv;
}
/// @brief Difference operator
bool operator!=(const BVNode& other) const { return !(*this == other); }
/// @brief Check whether two BVNode collide
bool overlap(const BVNode& other) const
{
return bv.overlap(other.bv);
bool overlap(const BVNode& other) const { return bv.overlap(other.bv); }
/// @brief Check whether two BVNode collide
bool overlap(const BVNode& other, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) const {
return bv.overlap(other.bv, request, sqrDistLowerBound);
}
/// @brief Compute the distance between two BVNode. P1 and P2, if not NULL and the underlying BV supports distance, return the nearest points.
FCL_REAL distance(const BVNode& other, Vec3f* P1 = NULL, Vec3f* P2 = NULL) const
{
/// @brief Compute the distance between two BVNode. P1 and P2, if not NULL and
/// the underlying BV supports distance, return the nearest points.
CoalScalar distance(const BVNode& other, Vec3s* P1 = NULL,
Vec3s* P2 = NULL) const {
return bv.distance(other.bv, P1, P2);
}
/// @brief Access the center of the BV
Vec3f getCenter() const { return bv.center(); }
/// @brief Access to the center of the BV
Vec3s getCenter() const { return bv.center(); }
/// @brief Access to the orientation of the BV
const Matrix3s& getOrientation() const {
static const Matrix3s id3 = Matrix3s::Identity();
return id3;
}
/// @brief Access the orientation of the BV
Matrix3f getOrientation() const { return Matrix3f::getIdentity(); }
/// \cond
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// \endcond
};
template<>
inline Matrix3f BVNode<OBB>::getOrientation() const
{
return Matrix3f(bv.axis[0][0], bv.axis[1][0], bv.axis[2][0],
bv.axis[0][1], bv.axis[1][1], bv.axis[2][1],
bv.axis[0][2], bv.axis[1][2], bv.axis[2][2]);
template <>
inline const Matrix3s& BVNode<OBB>::getOrientation() const {
return bv.axes;
}
template<>
inline Matrix3f BVNode<RSS>::getOrientation() const
{
return Matrix3f(bv.axis[0][0], bv.axis[1][0], bv.axis[2][0],
bv.axis[0][1], bv.axis[1][1], bv.axis[2][1],
bv.axis[0][2], bv.axis[1][2], bv.axis[2][2]);
template <>
inline const Matrix3s& BVNode<RSS>::getOrientation() const {
return bv.axes;
}
template<>
inline Matrix3f BVNode<OBBRSS>::getOrientation() const
{
return Matrix3f(bv.obb.axis[0][0], bv.obb.axis[1][0], bv.obb.axis[2][0],
bv.obb.axis[0][1], bv.obb.axis[1][1], bv.obb.axis[2][1],
bv.obb.axis[0][2], bv.obb.axis[1][2], bv.obb.axis[2][2]);
template <>
inline const Matrix3s& BVNode<OBBRSS>::getOrientation() const {
return bv.obb.axes;
}
}
} // namespace coal
#endif
......@@ -35,108 +35,116 @@
/** \author Jia Pan */
#ifndef FCL_OBB_H
#define FCL_OBB_H
#ifndef COAL_OBB_H
#define COAL_OBB_H
#include "coal/data_types.h"
#include "fcl/math/vec_3f.h"
#include "fcl/math/matrix_3f.h"
namespace coal {
namespace fcl
{
struct CollisionRequest;
/// @addtogroup Bounding_Volume
/// @{
/// @brief Oriented bounding box class
class OBB
{
public:
/// @brief Orientation of OBB. axis[i] is the ith column of the orientation matrix for the box; it is also the i-th principle direction of the box.
/// We assume that axis[0] corresponds to the axis with the longest box edge, axis[1] corresponds to the shorter one and axis[2] corresponds to the shortest one.
Vec3f axis[3];
struct COAL_DLLAPI OBB {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// @brief Orientation of OBB. axis[i] is the ith column of the orientation
/// matrix for the box; it is also the i-th principle direction of the box. We
/// assume that axis[0] corresponds to the axis with the longest box edge,
/// axis[1] corresponds to the shorter one and axis[2] corresponds to the
/// shortest one.
Matrix3s axes;
/// @brief Center of OBB
Vec3f To;
Vec3s To;
/// @brief Half dimensions of OBB
Vec3f extent;
Vec3s extent;
/// @brief Check collision between two OBB, return true if collision happens.
bool overlap(const OBB& other) const;
OBB() : axes(Matrix3s::Zero()), To(Vec3s::Zero()), extent(Vec3s::Zero()) {}
/// @brief Check collision between two OBB and return the overlap part. For OBB, the overlap_part return value is NOT used as the overlap part of two obbs usually is not an obb.
bool overlap(const OBB& other, OBB& overlap_part) const
{
return overlap(other);
/// @brief Equality operator
bool operator==(const OBB& other) const {
return axes == other.axes && To == other.To && extent == other.extent;
}
/// @brief Difference operator
bool operator!=(const OBB& other) const { return !(*this == other); }
/// @brief Check whether the OBB contains a point.
bool contain(const Vec3f& p) const;
bool contain(const Vec3s& p) const;
/// @brief A simple way to merge the OBB and a point (the result is not compact).
OBB& operator += (const Vec3f& p);
/// Check collision between two OBB
/// @return true if collision happens.
bool overlap(const OBB& other) const;
/// @brief Merge the OBB and another OBB (the result is not compact).
OBB& operator += (const OBB& other)
{
*this = *this + other;
return *this;
}
/// Check collision between two OBB
/// @return true if collision happens.
/// @retval sqrDistLowerBound squared lower bound on distance between boxes if
/// they do not overlap.
bool overlap(const OBB& other, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) const;
/// @brief Return the merged OBB of current OBB and the other one (the result is not compact).
OBB operator + (const OBB& other) const;
/// @brief Distance between two OBBs, not implemented.
CoalScalar distance(const OBB& other, Vec3s* P = NULL, Vec3s* Q = NULL) const;
/// @brief Width of the OBB.
inline FCL_REAL width() const
{
return 2 * extent[0];
}
/// @brief A simple way to merge the OBB and a point (the result is not
/// compact).
OBB& operator+=(const Vec3s& p);
/// @brief Height of the OBB.
inline FCL_REAL height() const
{
return 2 * extent[1];
/// @brief Merge the OBB and another OBB (the result is not compact).
OBB& operator+=(const OBB& other) {
*this = *this + other;
return *this;
}
/// @brief Depth of the OBB
inline FCL_REAL depth() const
{
return 2 * extent[2];
}
/// @brief Volume of the OBB
inline FCL_REAL volume() const
{
return width() * height() * depth();
}
/// @brief Return the merged OBB of current OBB and the other one (the result
/// is not compact).
OBB operator+(const OBB& other) const;
/// @brief Size of the OBB (used in BV_Splitter to order two OBBs)
inline FCL_REAL size() const
{
return extent.sqrLength();
}
inline CoalScalar size() const { return extent.squaredNorm(); }
/// @brief Center of the OBB
inline const Vec3f& center() const
{
return To;
}
/// @brief Distance between two OBBs, not implemented.
FCL_REAL distance(const OBB& other, Vec3f* P = NULL, Vec3f* Q = NULL) const;
};
inline const Vec3s& center() const { return To; }
/// @brief Width of the OBB.
inline CoalScalar width() const { return 2 * extent[0]; }
/// @brief Translate the OBB bv
OBB translate(const OBB& bv, const Vec3f& t);
/// @brief Height of the OBB.
inline CoalScalar height() const { return 2 * extent[1]; }
/// @brief Check collision between two obbs, b1 is in configuration (R0, T0) and b2 is in identity.
bool overlap(const Matrix3f& R0, const Vec3f& T0, const OBB& b1, const OBB& b2);
/// @brief Depth of the OBB
inline CoalScalar depth() const { return 2 * extent[2]; }
/// @brief Volume of the OBB
inline CoalScalar volume() const { return width() * height() * depth(); }
};
/// @brief Check collision between two boxes: the first box is in configuration (R, T) and its half dimension is set by a;
/// the second box is in identity configuration and its half dimension is set by b.
bool obbDisjoint(const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f& b);
}
/// @brief Translate the OBB bv
COAL_DLLAPI OBB translate(const OBB& bv, const Vec3s& t);
/// @brief Check collision between two obbs, b1 is in configuration (R0, T0) and
/// b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const OBB& b1,
const OBB& b2);
/// @brief Check collision between two obbs, b1 is in configuration (R0, T0) and
/// b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const OBB& b1,
const OBB& b2, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound);
/// Check collision between two boxes
/// @param B, T orientation and position of first box,
/// @param a half dimensions of first box,
/// @param b half dimensions of second box.
/// The second box is in identity configuration.
COAL_DLLAPI bool obbDisjoint(const Matrix3s& B, const Vec3s& T, const Vec3s& a,
const Vec3s& b);
} // namespace coal
#endif
......@@ -35,21 +35,23 @@
/** \author Jia Pan */
#ifndef FCL_OBBRSS_H
#define FCL_OBBRSS_H
#ifndef COAL_OBBRSS_H
#define COAL_OBBRSS_H
#include "coal/BV/OBB.h"
#include "coal/BV/RSS.h"
#include "fcl/BV/OBB.h"
#include "fcl/BV/RSS.h"
namespace coal {
namespace fcl
{
struct CollisionRequest;
/// @addtogroup Bounding_Volume
/// @{
/// @brief Class merging the OBB and RSS, can handle collision and distance simultaneously
class OBBRSS
{
public:
/// @brief Class merging the OBB and RSS, can handle collision and distance
/// simultaneously
struct COAL_DLLAPI OBBRSS {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// @brief OBB member, for rotation
OBB obb;
......@@ -57,101 +59,102 @@ public:
/// @brief RSS member, for distance
RSS rss;
/// @brief Check collision between two OBBRSS
bool overlap(const OBBRSS& other) const
{
return obb.overlap(other.obb);
/// @brief Equality operator
bool operator==(const OBBRSS& other) const {
return obb == other.obb && rss == other.rss;
}
/// @brief Check collision between two OBBRSS and return the overlap part.
bool overlap(const OBBRSS& other, OBBRSS& overlap_part) const
{
return overlap(other);
}
/// @brief Difference operator
bool operator!=(const OBBRSS& other) const { return !(*this == other); }
/// @brief Check whether the OBBRSS contains a point
inline bool contain(const Vec3f& p) const
{
return obb.contain(p);
inline bool contain(const Vec3s& p) const { return obb.contain(p); }
/// @brief Check collision between two OBBRSS
bool overlap(const OBBRSS& other) const { return obb.overlap(other.obb); }
/// Check collision between two OBBRSS
/// @retval sqrDistLowerBound squared lower bound on distance between
/// objects if they do not overlap.
bool overlap(const OBBRSS& other, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) const {
return obb.overlap(other.obb, request, sqrDistLowerBound);
}
/// @brief Distance between two OBBRSS; P and Q , is not NULL, returns the
/// nearest points
CoalScalar distance(const OBBRSS& other, Vec3s* P = NULL,
Vec3s* Q = NULL) const {
return rss.distance(other.rss, P, Q);
}
/// @brief Merge the OBBRSS and a point
OBBRSS& operator += (const Vec3f& p)
{
OBBRSS& operator+=(const Vec3s& p) {
obb += p;
rss += p;
return *this;
}
/// @brief Merge two OBBRSS
OBBRSS& operator += (const OBBRSS& other)
{
OBBRSS& operator+=(const OBBRSS& other) {
*this = *this + other;
return *this;
}
/// @brief Merge two OBBRSS
OBBRSS operator + (const OBBRSS& other) const
{
OBBRSS operator+(const OBBRSS& other) const {
OBBRSS result;
result.obb = obb + other.obb;
result.rss = rss + other.rss;
return result;
}
/// @brief Size of the OBBRSS (used in BV_Splitter to order two OBBRSS)
inline CoalScalar size() const { return obb.size(); }
/// @brief Center of the OBBRSS
inline const Vec3s& center() const { return obb.center(); }
/// @brief Width of the OBRSS
inline FCL_REAL width() const
{
return obb.width();
}
inline CoalScalar width() const { return obb.width(); }
/// @brief Height of the OBBRSS
inline FCL_REAL height() const
{
return obb.height();
}
inline CoalScalar height() const { return obb.height(); }
/// @brief Depth of the OBBRSS
inline FCL_REAL depth() const
{
return obb.depth();
}
inline CoalScalar depth() const { return obb.depth(); }
/// @brief Volume of the OBBRSS
inline FCL_REAL volume() const
{
return obb.volume();
}
/// @brief Size of the OBBRSS (used in BV_Splitter to order two OBBRSS)
inline FCL_REAL size() const
{
return obb.size();
}
/// @brief Center of the OBBRSS
inline const Vec3f& center() const
{
return obb.center();
}
/// @brief Distance between two OBBRSS; P and Q , is not NULL, returns the nearest points
FCL_REAL distance(const OBBRSS& other, Vec3f* P = NULL, Vec3f* Q = NULL) const
{
return rss.distance(other.rss, P, Q);
}
inline CoalScalar volume() const { return obb.volume(); }
};
/// @brief Translate the OBBRSS bv
OBBRSS translate(const OBBRSS& bv, const Vec3f& t);
/// @brief Check collision between two OBBRSS, b1 is in configuration (R0, T0) and b2 is in indentity
bool overlap(const Matrix3f& R0, const Vec3f& T0, const OBBRSS& b1, const OBBRSS& b2);
/// @brief Check collision between two OBBRSS, b1 is in configuration (R0, T0)
/// and b2 is in indentity
inline bool overlap(const Matrix3s& R0, const Vec3s& T0, const OBBRSS& b1,
const OBBRSS& b2) {
return overlap(R0, T0, b1.obb, b2.obb);
}
/// @brief Computate distance between two OBBRSS, b1 is in configuation (R0, T0) and b2 is in indentity; P and Q, is not NULL, returns the nearest points
FCL_REAL distance(const Matrix3f& R0, const Vec3f& T0, const OBBRSS& b1, const OBBRSS& b2, Vec3f* P = NULL, Vec3f* Q = NULL);
/// Check collision between two OBBRSS
/// @param R0, T0 configuration of b1
/// @param b1 first OBBRSS in configuration (R0, T0)
/// @param b2 second OBBRSS in identity position
/// @retval sqrDistLowerBound squared lower bound on the distance if OBBRSS do
/// not overlap.
inline bool overlap(const Matrix3s& R0, const Vec3s& T0, const OBBRSS& b1,
const OBBRSS& b2, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) {
return overlap(R0, T0, b1.obb, b2.obb, request, sqrDistLowerBound);
}
/// @brief Computate distance between two OBBRSS, b1 is in configuation (R0, T0)
/// and b2 is in indentity; P and Q, is not NULL, returns the nearest points
inline CoalScalar distance(const Matrix3s& R0, const Vec3s& T0,
const OBBRSS& b1, const OBBRSS& b2, Vec3s* P = NULL,
Vec3s* Q = NULL) {
return distance(R0, T0, b1.rss, b2.rss, P, Q);
}
} // namespace coal
#endif
......@@ -35,117 +35,139 @@
/** \author Jia Pan */
#ifndef FCL_RSS_H
#define FCL_RSS_H
#ifndef COAL_RSS_H
#define COAL_RSS_H
#include "coal/data_types.h"
#include "fcl/math/vec_3f.h"
#include "fcl/math/matrix_3f.h"
#include <boost/math/constants/constants.hpp>
namespace fcl
{
namespace coal {
struct CollisionRequest;
/// @addtogroup Bounding_Volume
/// @{
/// @brief A class for rectangle sphere-swept bounding volume
class RSS
{
public:
/// @brief Orientation of RSS. axis[i] is the ith column of the orientation matrix for the RSS; it is also the i-th principle direction of the RSS.
/// We assume that axis[0] corresponds to the axis with the longest length, axis[1] corresponds to the shorter one and axis[2] corresponds to the shortest one.
Vec3f axis[3];
struct COAL_DLLAPI RSS {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// @brief Orientation of RSS. axis[i] is the ith column of the orientation
/// matrix for the RSS; it is also the i-th principle direction of the RSS. We
/// assume that axis[0] corresponds to the axis with the longest length,
/// axis[1] corresponds to the shorter one and axis[2] corresponds to the
/// shortest one.
Matrix3s axes;
/// @brief Origin of the rectangle in RSS
Vec3f Tr;
Vec3s Tr;
/// @brief Side lengths of rectangle
FCL_REAL l[2];
CoalScalar length[2];
/// @brief Radius of sphere summed with rectangle to form RSS
FCL_REAL r;
CoalScalar radius;
/// @brief Default constructor with default values
RSS() : axes(Matrix3s::Zero()), Tr(Vec3s::Zero()), radius(-1) {
length[0] = 0;
length[1] = 0;
}
/// @brief Equality operator
bool operator==(const RSS& other) const {
return axes == other.axes && Tr == other.Tr &&
length[0] == other.length[0] && length[1] == other.length[1] &&
radius == other.radius;
}
/// @brief Difference operator
bool operator!=(const RSS& other) const { return !(*this == other); }
/// @brief Check whether the RSS contains a point
bool contain(const Vec3s& p) const;
/// @brief Check collision between two RSS
bool overlap(const RSS& other) const;
/// @brief Check collision between two RSS and return the overlap part.
/// For RSS, we return nothing, as the overlap part of two RSSs usually is not a RSS.
bool overlap(const RSS& other, RSS& overlap_part) const
{
/// Not implemented
bool overlap(const RSS& other, const CollisionRequest&,
CoalScalar& sqrDistLowerBound) const {
sqrDistLowerBound = sqrt(-1);
return overlap(other);
}
/// @brief Check whether the RSS contains a point
inline bool contain(const Vec3f& p) const;
/// @brief the distance between two RSS; P and Q, if not NULL, return the
/// nearest points
CoalScalar distance(const RSS& other, Vec3s* P = NULL, Vec3s* Q = NULL) const;
/// @brief A simple way to merge the RSS and a point, not compact.
/// @todo This function may have some bug.
RSS& operator += (const Vec3f& p);
RSS& operator+=(const Vec3s& p);
/// @brief Merge the RSS and another RSS
inline RSS& operator += (const RSS& other)
{
inline RSS& operator+=(const RSS& other) {
*this = *this + other;
return *this;
}
/// @brief Return the merged RSS of current RSS and the other one
RSS operator + (const RSS& other) const;
RSS operator+(const RSS& other) const;
/// @brief Width of the RSS
inline FCL_REAL width() const
{
return l[0] + 2 * r;
/// @brief Size of the RSS (used in BV_Splitter to order two RSSs)
inline CoalScalar size() const {
return (std::sqrt(length[0] * length[0] + length[1] * length[1]) +
2 * radius);
}
/// @brief The RSS center
inline const Vec3s& center() const { return Tr; }
/// @brief Width of the RSS
inline CoalScalar width() const { return length[0] + 2 * radius; }
/// @brief Height of the RSS
inline FCL_REAL height() const
{
return l[1] + 2 * r;
}
inline CoalScalar height() const { return length[1] + 2 * radius; }
/// @brief Depth of the RSS
inline FCL_REAL depth() const
{
return 2 * r;
}
inline CoalScalar depth() const { return 2 * radius; }
/// @brief Volume of the RSS
inline FCL_REAL volume() const
{
return (l[0] * l[1] * 2 * r + 4 * boost::math::constants::pi<FCL_REAL>() * r * r * r);
}
/// @brief Size of the RSS (used in BV_Splitter to order two RSSs)
inline FCL_REAL size() const
{
return (std::sqrt(l[0] * l[0] + l[1] * l[1]) + 2 * r);
inline CoalScalar volume() const {
return (length[0] * length[1] * 2 * radius +
4 * boost::math::constants::pi<CoalScalar>() * radius * radius *
radius);
}
/// @brief The RSS center
inline const Vec3f& center() const
{
return Tr;
/// @brief Check collision between two RSS and return the overlap part.
/// For RSS, we return nothing, as the overlap part of two RSSs usually is not
/// a RSS.
bool overlap(const RSS& other, RSS& /*overlap_part*/) const {
return overlap(other);
}
/// @brief the distance between two RSS; P and Q, if not NULL, return the nearest points
FCL_REAL distance(const RSS& other, Vec3f* P = NULL, Vec3f* Q = NULL) const;
};
/// @brief Translate the RSS bv
RSS translate(const RSS& bv, const Vec3f& t);
/// @brief distance between two RSS bounding volumes
/// P and Q (optional return values) are the closest points in the rectangles, not the RSS. But the direction P - Q is the correct direction for cloest points
/// Notice that P and Q are both in the local frame of the first RSS (not global frame and not even the local frame of object 1)
FCL_REAL distance(const Matrix3f& R0, const Vec3f& T0, const RSS& b1, const RSS& b2, Vec3f* P = NULL, Vec3f* Q = NULL);
/// @brief Check collision between two RSSs, b1 is in configuration (R0, T0) and b2 is in identity.
bool overlap(const Matrix3f& R0, const Vec3f& T0, const RSS& b1, const RSS& b2);
}
/// P and Q (optional return values) are the closest points in the rectangles,
/// not the RSS. But the direction P - Q is the correct direction for cloest
/// points Notice that P and Q are both in the local frame of the first RSS (not
/// global frame and not even the local frame of object 1)
COAL_DLLAPI CoalScalar distance(const Matrix3s& R0, const Vec3s& T0,
const RSS& b1, const RSS& b2, Vec3s* P = NULL,
Vec3s* Q = NULL);
/// @brief Check collision between two RSSs, b1 is in configuration (R0, T0) and
/// b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const RSS& b1,
const RSS& b2);
/// @brief Check collision between two RSSs, b1 is in configuration (R0, T0) and
/// b2 is in identity.
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const RSS& b1,
const RSS& b2, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound);
} // namespace coal
#endif
......@@ -35,19 +35,25 @@
/** \author Jia Pan */
#ifndef FCL_KDOP_H
#define FCL_KDOP_H
#ifndef COAL_KDOP_H
#define COAL_KDOP_H
#include "coal/fwd.hh"
#include "coal/data_types.h"
#include "fcl/math/vec_3f.h"
namespace coal {
namespace fcl
{
struct CollisionRequest;
/// @addtogroup Bounding_Volume
/// @{
/// @brief KDOP class describes the KDOP collision structures. K is set as the template parameter, which should be 16, 18, or 24
/// The KDOP structure is defined by some pairs of parallel planes defined by some axes.
/// For K = 16, the planes are 6 AABB planes and 10 diagonal planes that cut off some space of the edges:
/// @brief KDOP class describes the KDOP collision structures. K is set as the
/// template parameter, which should be 16, 18, or 24
/// The KDOP structure is defined by some pairs of parallel planes defined by
/// some axes.
/// For K = 16, the planes are 6 AABB planes and 10 diagonal planes that cut off
/// some space of the edges:
/// (-1,0,0) and (1,0,0) -> indices 0 and 8
/// (0,-1,0) and (0,1,0) -> indices 1 and 9
/// (0,0,-1) and (0,0,1) -> indices 2 and 10
......@@ -56,7 +62,8 @@ namespace fcl
/// (0,-1,-1) and (0,1,1) -> indices 5 and 13
/// (-1,1,0) and (1,-1,0) -> indices 6 and 14
/// (-1,0,1) and (1,0,-1) -> indices 7 and 15
/// For K = 18, the planes are 6 AABB planes and 12 diagonal planes that cut off some space of the edges:
/// For K = 18, the planes are 6 AABB planes and 12 diagonal planes that cut off
/// some space of the edges:
/// (-1,0,0) and (1,0,0) -> indices 0 and 9
/// (0,-1,0) and (0,1,0) -> indices 1 and 10
/// (0,0,-1) and (0,0,1) -> indices 2 and 11
......@@ -66,7 +73,8 @@ namespace fcl
/// (-1,1,0) and (1,-1,0) -> indices 6 and 15
/// (-1,0,1) and (1,0,-1) -> indices 7 and 16
/// (0,-1,1) and (0,1,-1) -> indices 8 and 17
/// For K = 18, the planes are 6 AABB planes and 18 diagonal planes that cut off some space of the edges:
/// For K = 18, the planes are 6 AABB planes and 18 diagonal planes that cut off
/// some space of the edges:
/// (-1,0,0) and (1,0,0) -> indices 0 and 12
/// (0,-1,0) and (0,1,0) -> indices 1 and 13
/// (0,0,-1) and (0,0,1) -> indices 2 and 14
......@@ -79,97 +87,104 @@ namespace fcl
/// (-1, -1, 1) and (1, 1, -1) --> indices 9 and 21
/// (-1, 1, -1) and (1, -1, 1) --> indices 10 and 22
/// (1, -1, -1) and (-1, 1, 1) --> indices 11 and 23
template<size_t N>
class KDOP
{
public:
template <short N>
class COAL_DLLAPI KDOP {
protected:
/// @brief Origin's distances to N KDOP planes
Eigen::Array<CoalScalar, N, 1> dist_;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// @brief Creating kDOP containing nothing
KDOP();
/// @brief Creating kDOP containing only one point
KDOP(const Vec3f& v);
KDOP(const Vec3s& v);
/// @brief Creating kDOP containing two points
KDOP(const Vec3f& a, const Vec3f& b);
/// @brief Check whether two KDOPs are overlapped
bool overlap(const KDOP<N>& other) const;
KDOP(const Vec3s& a, const Vec3s& b);
//// @brief Check whether one point is inside the KDOP
bool inside(const Vec3f& p) const;
/// @brief Equality operator
bool operator==(const KDOP& other) const {
return (dist_ == other.dist_).all();
}
/// @brief Merge the point and the KDOP
KDOP<N>& operator += (const Vec3f& p);
/// @brief Difference operator
bool operator!=(const KDOP& other) const {
return (dist_ != other.dist_).any();
}
/// @brief Merge two KDOPs
KDOP<N>& operator += (const KDOP<N>& other);
/// @brief Check whether two KDOPs overlap.
bool overlap(const KDOP<N>& other) const;
/// @brief Create a KDOP by mergin two KDOPs
KDOP<N> operator + (const KDOP<N>& other) const;
/// @brief Check whether two KDOPs overlap.
/// @return true if collision happens.
/// @retval sqrDistLowerBound squared lower bound on distance between boxes if
/// they do not overlap.
bool overlap(const KDOP<N>& other, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound) const;
/// @brief The (AABB) width
inline FCL_REAL width() const
{
return dist_[N / 2] - dist_[0];
}
/// @brief The distance between two KDOP<N>. Not implemented.
CoalScalar distance(const KDOP<N>& other, Vec3s* P = NULL,
Vec3s* Q = NULL) const;
/// @brief The (AABB) height
inline FCL_REAL height() const
{
return dist_[N / 2 + 1] - dist_[1];
}
/// @brief Merge the point and the KDOP
KDOP<N>& operator+=(const Vec3s& p);
/// @brief The (AABB) depth
inline FCL_REAL depth() const
{
return dist_[N / 2 + 2] - dist_[2];
}
/// @brief Merge two KDOPs
KDOP<N>& operator+=(const KDOP<N>& other);
/// @brief The (AABB) volume
inline FCL_REAL volume() const
{
return width() * height() * depth();
}
/// @brief Create a KDOP by mergin two KDOPs
KDOP<N> operator+(const KDOP<N>& other) const;
/// @brief Size of the kDOP (used in BV_Splitter to order two kDOPs)
inline FCL_REAL size() const
{
inline CoalScalar size() const {
return width() * width() + height() * height() + depth() * depth();
}
/// @brief The (AABB) center
inline Vec3f center() const
{
return Vec3f(dist_[0] + dist_[N / 2], dist_[1] + dist_[N / 2 + 1], dist_[2] + dist_[N / 2 + 2]) * 0.5;
inline Vec3s center() const {
return (dist_.template head<3>() + dist_.template segment<3>(N / 2)) / 2;
}
/// @brief The distance between two KDOP<N>. Not implemented.
FCL_REAL distance(const KDOP<N>& other, Vec3f* P = NULL, Vec3f* Q = NULL) const;
/// @brief The (AABB) width
inline CoalScalar width() const { return dist_[N / 2] - dist_[0]; }
private:
/// @brief Origin's distances to N KDOP planes
FCL_REAL dist_[N];
/// @brief The (AABB) height
inline CoalScalar height() const { return dist_[N / 2 + 1] - dist_[1]; }
public:
inline FCL_REAL dist(std::size_t i) const
{
return dist_[i];
}
/// @brief The (AABB) depth
inline CoalScalar depth() const { return dist_[N / 2 + 2] - dist_[2]; }
inline FCL_REAL& dist(std::size_t i)
{
return dist_[i];
}
/// @brief The (AABB) volume
inline CoalScalar volume() const { return width() * height() * depth(); }
inline CoalScalar dist(short i) const { return dist_[i]; }
inline CoalScalar& dist(short i) { return dist_[i]; }
//// @brief Check whether one point is inside the KDOP
bool inside(const Vec3s& p) const;
};
template <short N>
bool overlap(const Matrix3s& /*R0*/, const Vec3s& /*T0*/, const KDOP<N>& /*b1*/,
const KDOP<N>& /*b2*/) {
COAL_THROW_PRETTY("not implemented", std::logic_error);
}
template <short N>
bool overlap(const Matrix3s& /*R0*/, const Vec3s& /*T0*/, const KDOP<N>& /*b1*/,
const KDOP<N>& /*b2*/, const CollisionRequest& /*request*/,
CoalScalar& /*sqrDistLowerBound*/) {
COAL_THROW_PRETTY("not implemented", std::logic_error);
}
/// @brief translate the KDOP BV
template<size_t N>
KDOP<N> translate(const KDOP<N>& bv, const Vec3f& t);
template <short N>
COAL_DLLAPI KDOP<N> translate(const KDOP<N>& bv, const Vec3s& t);
}
} // namespace coal
#endif
......@@ -35,54 +35,85 @@
/** \author Jia Pan */
#ifndef FCL_KIOS_H
#define FCL_KIOS_H
#ifndef COAL_KIOS_H
#define COAL_KIOS_H
#include "fcl/BV/OBB.h"
#include "coal/BV/OBB.h"
namespace coal {
namespace fcl
{
/// @brief A class describing the kIOS collision structure, which is a set of spheres.
class kIOS
{
struct CollisionRequest;
/// @addtogroup Bounding_Volume
/// @{
/// @brief A class describing the kIOS collision structure, which is a set of
/// spheres.
class COAL_DLLAPI kIOS {
/// @brief One sphere in kIOS
struct kIOS_Sphere
{
Vec3f o;
FCL_REAL r;
struct COAL_DLLAPI kIOS_Sphere {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Vec3s o;
CoalScalar r;
bool operator==(const kIOS_Sphere& other) const {
return o == other.o && r == other.r;
}
bool operator!=(const kIOS_Sphere& other) const {
return !(*this == other);
}
};
/// @brief generate one sphere enclosing two spheres
static kIOS_Sphere encloseSphere(const kIOS_Sphere& s0, const kIOS_Sphere& s1)
{
Vec3f d = s1.o - s0.o;
FCL_REAL dist2 = d.sqrLength();
FCL_REAL diff_r = s1.r - s0.r;
static kIOS_Sphere encloseSphere(const kIOS_Sphere& s0,
const kIOS_Sphere& s1) {
Vec3s d = s1.o - s0.o;
CoalScalar dist2 = d.squaredNorm();
CoalScalar diff_r = s1.r - s0.r;
/** The sphere with the larger radius encloses the other */
if(diff_r * diff_r >= dist2)
{
if(s1.r > s0.r) return s1;
else return s0;
}
else /** spheres partially overlapping or disjoint */
if (diff_r * diff_r >= dist2) {
if (s1.r > s0.r)
return s1;
else
return s0;
} else /** spheres partially overlapping or disjoint */
{
float dist = std::sqrt(dist2);
float dist = (float)std::sqrt(dist2);
kIOS_Sphere s;
s.r = dist + s0.r + s1.r;
if(dist > 0)
if (dist > 0)
s.o = s0.o + d * ((s.r - s0.r) / dist);
else
s.o = s0.o;
return s;
}
}
public:
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
/// @brief Equality operator
bool operator==(const kIOS& other) const {
bool res = obb == other.obb && num_spheres == other.num_spheres;
if (!res) return false;
for (size_t k = 0; k < num_spheres; ++k) {
if (spheres[k] != other.spheres[k]) return false;
}
return true;
}
/// @brief Difference operator
bool operator!=(const kIOS& other) const { return !(*this == other); }
static constexpr size_t max_num_spheres = 5;
/// @brief The (at most) five spheres for intersection
kIOS_Sphere spheres[5];
kIOS_Sphere spheres[max_num_spheres];
/// @brief The number of spheres, no larger than 5
unsigned int num_spheres;
......@@ -90,70 +121,73 @@ public:
/// @ OBB related with kIOS
OBB obb;
/// @brief Check whether the kIOS contains a point
bool contain(const Vec3s& p) const;
/// @brief Check collision between two kIOS
bool overlap(const kIOS& other) const;
/// @brief Check collision between two kIOS and return the overlap part.
/// For kIOS, we return nothing, as the overlappart of two kIOS usually is not an kIOS
/// @todo Not efficient. It first checks the sphere collisions and then use OBB for further culling.
bool overlap(const kIOS& other, kIOS& overlap_part) const
{
return overlap(other);
}
/// @brief Check collision between two kIOS
bool overlap(const kIOS& other, const CollisionRequest&,
CoalScalar& sqrDistLowerBound) const;
/// @brief Check whether the kIOS contains a point
inline bool contain(const Vec3f& p) const;
/// @brief The distance between two kIOS
CoalScalar distance(const kIOS& other, Vec3s* P = NULL,
Vec3s* Q = NULL) const;
/// @brief A simple way to merge the kIOS and a point
kIOS& operator += (const Vec3f& p);
kIOS& operator+=(const Vec3s& p);
/// @brief Merge the kIOS and another kIOS
kIOS& operator += (const kIOS& other)
{
kIOS& operator+=(const kIOS& other) {
*this = *this + other;
return *this;
}
/// @brief Return the merged kIOS of current kIOS and the other one
kIOS operator + (const kIOS& other) const;
kIOS operator+(const kIOS& other) const;
/// @brief size of the kIOS (used in BV_Splitter to order two kIOSs)
CoalScalar size() const;
/// @brief Center of the kIOS
const Vec3f& center() const
{
return spheres[0].o;
}
const Vec3s& center() const { return spheres[0].o; }
/// @brief Width of the kIOS
FCL_REAL width() const;
CoalScalar width() const;
/// @brief Height of the kIOS
FCL_REAL height() const;
CoalScalar height() const;
/// @brief Depth of the kIOS
FCL_REAL depth() const;
CoalScalar depth() const;
/// @brief Volume of the kIOS
FCL_REAL volume() const;
/// @brief size of the kIOS (used in BV_Splitter to order two kIOSs)
FCL_REAL size() const;
/// @brief The distance between two kIOS
FCL_REAL distance(const kIOS& other, Vec3f* P = NULL, Vec3f* Q = NULL) const;
CoalScalar volume() const;
};
/// @brief Translate the kIOS BV
kIOS translate(const kIOS& bv, const Vec3f& t);
COAL_DLLAPI kIOS translate(const kIOS& bv, const Vec3s& t);
/// @brief Check collision between two kIOSs, b1 is in configuration (R0, T0)
/// and b2 is in identity.
/// @todo Not efficient
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const kIOS& b1,
const kIOS& b2);
/// @brief Check collision between two kIOSs, b1 is in configuration (R0, T0) and b2 is in identity.
/// @brief Check collision between two kIOSs, b1 is in configuration (R0, T0)
/// and b2 is in identity.
/// @todo Not efficient
bool overlap(const Matrix3f& R0, const Vec3f& T0, const kIOS& b1, const kIOS& b2);
COAL_DLLAPI bool overlap(const Matrix3s& R0, const Vec3s& T0, const kIOS& b1,
const kIOS& b2, const CollisionRequest& request,
CoalScalar& sqrDistLowerBound);
/// @brief Approximate distance between two kIOS bounding volumes
/// @todo P and Q is not returned, need implementation
FCL_REAL distance(const Matrix3f& R0, const Vec3f& T0, const kIOS& b1, const kIOS& b2, Vec3f* P = NULL, Vec3f* Q = NULL);
COAL_DLLAPI CoalScalar distance(const Matrix3s& R0, const Vec3s& T0,
const kIOS& b1, const kIOS& b2, Vec3s* P = NULL,
Vec3s* Q = NULL);
}
} // namespace coal
#endif
......@@ -35,44 +35,42 @@
/** \author Jia Pan */
#ifndef FCL_BVH_FRONT_H
#define FCL_BVH_FRONT_H
#ifndef COAL_BVH_FRONT_H
#define COAL_BVH_FRONT_H
#include <list>
namespace fcl
{
#include "coal/config.hh"
namespace coal {
/// @brief Front list acceleration for collision
/// Front list is a set of internal and leaf nodes in the BVTT hierarchy, where
/// the traversal terminates while performing a query during a given time instance. The front list reflects the subset of a
/// BVTT that is traversed for that particular proximity query.
struct BVHFrontNode
{
/// @brief The nodes to start in the future, i.e. the wave front of the traversal tree.
int left, right;
/// the traversal terminates while performing a query during a given time
/// instance. The front list reflects the subset of a BVTT that is traversed for
/// that particular proximity query.
struct COAL_DLLAPI BVHFrontNode {
/// @brief The nodes to start in the future, i.e. the wave front of the
/// traversal tree.
unsigned int left, right;
/// @brief The front node is not valid when collision is detected on the front node.
/// @brief The front node is not valid when collision is detected on the front
/// node.
bool valid;
BVHFrontNode(int left_, int right_) : left(left_),
right(right_),
valid(true)
{
}
BVHFrontNode(unsigned int left_, unsigned int right_)
: left(left_), right(right_), valid(true) {}
};
/// @brief BVH front list is a list of front nodes.
typedef std::list<BVHFrontNode> BVHFrontList;
/// @brief Add new front node into the front list
inline void updateFrontList(BVHFrontList* front_list, int b1, int b2)
{
if(front_list) front_list->push_back(BVHFrontNode(b1, b2));
inline void updateFrontList(BVHFrontList* front_list, unsigned int b1,
unsigned int b2) {
if (front_list) front_list->push_back(BVHFrontNode(b1, b2));
}
}
} // namespace coal
#endif
......@@ -35,51 +35,53 @@
/** \author Jia Pan */
#ifndef FCL_BVH_INTERNAL_H
#define FCL_BVH_INTERNAL_H
#ifndef COAL_BVH_INTERNAL_H
#define COAL_BVH_INTERNAL_H
#include "fcl/data_types.h"
#include "coal/data_types.h"
namespace fcl
{
namespace coal {
/// @brief States for BVH construction
/// empty->begun->processed ->replace_begun->processed -> ......
/// |
/// |-> update_begun -> updated -> .....
enum BVHBuildState
{
BVH_BUILD_STATE_EMPTY, /// empty state, immediately after constructor
BVH_BUILD_STATE_BEGUN, /// after beginModel(), state for adding geometry primitives
BVH_BUILD_STATE_PROCESSED, /// after tree has been build, ready for cd use
BVH_BUILD_STATE_UPDATE_BEGUN, /// after beginUpdateModel(), state for updating geometry primitives
BVH_BUILD_STATE_UPDATED, /// after tree has been build for updated geometry, ready for ccd use
BVH_BUILD_STATE_REPLACE_BEGUN, /// after beginReplaceModel(), state for replacing geometry primitives
};
enum BVHBuildState {
BVH_BUILD_STATE_EMPTY, /// empty state, immediately after constructor
BVH_BUILD_STATE_BEGUN, /// after beginModel(), state for adding geometry
/// primitives
BVH_BUILD_STATE_PROCESSED, /// after tree has been build, ready for cd use
BVH_BUILD_STATE_UPDATE_BEGUN, /// after beginUpdateModel(), state for
/// updating geometry primitives
BVH_BUILD_STATE_UPDATED, /// after tree has been build for updated geometry,
/// ready for ccd use
BVH_BUILD_STATE_REPLACE_BEGUN /// after beginReplaceModel(), state for
/// replacing geometry primitives
};
/// @brief Error code for BVH
enum BVHReturnCode
{
BVH_OK = 0, /// BVH is valid
BVH_ERR_MODEL_OUT_OF_MEMORY = -1, /// Cannot allocate memory for vertices and triangles
BVH_ERR_BUILD_OUT_OF_SEQUENCE = -2, /// BVH construction does not follow correct sequence
BVH_ERR_BUILD_EMPTY_MODEL = -3, /// BVH geometry is not prepared
BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME = -4, /// BVH geometry in previous frame is not prepared
BVH_ERR_UNSUPPORTED_FUNCTION = -5, /// BVH funtion is not supported
BVH_ERR_UNUPDATED_MODEL = -6, /// BVH model update failed
BVH_ERR_INCORRECT_DATA = -7, /// BVH data is not valid
BVH_ERR_UNKNOWN = -8 /// Unknown failure
};
/// @brief Error code for BVH
enum BVHReturnCode {
BVH_OK = 0, /// BVH is valid
BVH_ERR_MODEL_OUT_OF_MEMORY =
-1, /// Cannot allocate memory for vertices and triangles
BVH_ERR_BUILD_OUT_OF_SEQUENCE =
-2, /// BVH construction does not follow correct sequence
BVH_ERR_BUILD_EMPTY_MODEL = -3, /// BVH geometry is not prepared
BVH_ERR_BUILD_EMPTY_PREVIOUS_FRAME =
-4, /// BVH geometry in previous frame is not prepared
BVH_ERR_UNSUPPORTED_FUNCTION = -5, /// BVH funtion is not supported
BVH_ERR_UNUPDATED_MODEL = -6, /// BVH model update failed
BVH_ERR_INCORRECT_DATA = -7, /// BVH data is not valid
BVH_ERR_UNKNOWN = -8 /// Unknown failure
};
/// @brief BVH model type
enum BVHModelType
{
BVH_MODEL_UNKNOWN, /// @brief unknown model type
BVH_MODEL_TRIANGLES, /// @brief triangle model
BVH_MODEL_POINTCLOUD /// @brief point cloud model
};
enum BVHModelType {
BVH_MODEL_UNKNOWN, /// @brief unknown model type
BVH_MODEL_TRIANGLES, /// @brief triangle model
BVH_MODEL_POINTCLOUD /// @brief point cloud model
};
}
} // namespace coal
#endif
......@@ -3,6 +3,7 @@
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* Copyright (c) 2020-2022, INRIA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -35,259 +36,354 @@
/** \author Jia Pan */
#ifndef FCL_BVH_MODEL_H
#define FCL_BVH_MODEL_H
#ifndef COAL_BVH_MODEL_H
#define COAL_BVH_MODEL_H
#include "coal/fwd.hh"
#include "coal/collision_object.h"
#include "coal/BVH/BVH_internal.h"
#include "coal/BV/BV_node.h"
#include "fcl/collision_object.h"
#include "fcl/BVH/BVH_internal.h"
#include "fcl/BV/BV_node.h"
#include "fcl/BVH/BV_splitter.h"
#include "fcl/BVH/BV_fitter.h"
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <memory>
#include <iostream>
namespace coal {
/// @addtogroup Construction_Of_BVH
/// @{
namespace fcl
{
class ConvexBase;
template <typename BV>
class BVFitter;
template <typename BV>
class BVSplitter;
/// @brief A base class describing the bounding hierarchy of a mesh model or a
/// point cloud model (which is viewed as a degraded version of mesh)
class COAL_DLLAPI BVHModelBase : public CollisionGeometry {
public:
/// @brief Geometry point data
std::shared_ptr<std::vector<Vec3s>> vertices;
/// @brief A class describing the bounding hierarchy of a mesh model or a point cloud model (which is viewed as a degraded version of mesh)
template<typename BV>
class BVHModel : public CollisionGeometry,
private boost::noncopyable
{
/// @brief Geometry triangle index data, will be NULL for point clouds
std::shared_ptr<std::vector<Triangle>> tri_indices;
/// @brief Geometry point data in previous frame
std::shared_ptr<std::vector<Vec3s>> prev_vertices;
/// @brief Number of triangles
unsigned int num_tris;
/// @brief Number of points
unsigned int num_vertices;
/// @brief The state of BVH building process
BVHBuildState build_state;
/// @brief Convex<Triangle> representation of this object
shared_ptr<ConvexBase> convex;
public:
/// @brief Model type described by the instance
BVHModelType getModelType() const
{
if(num_tris && num_vertices)
BVHModelType getModelType() const {
if (num_tris && num_vertices)
return BVH_MODEL_TRIANGLES;
else if(num_vertices)
else if (num_vertices)
return BVH_MODEL_POINTCLOUD;
else
return BVH_MODEL_UNKNOWN;
}
/// @brief Constructing an empty BVH
BVHModel() : vertices(NULL),
tri_indices(NULL),
prev_vertices(NULL),
num_tris(0),
num_vertices(0),
build_state(BVH_BUILD_STATE_EMPTY),
bv_splitter(new BVSplitter<BV>(SPLIT_METHOD_MEAN)),
bv_fitter(new BVFitter<BV>()),
num_tris_allocated(0),
num_vertices_allocated(0),
num_bvs_allocated(0),
num_vertex_updated(0),
primitive_indices(NULL),
bvs(NULL),
num_bvs(0)
{
}
BVHModelBase();
/// @brief copy from another BVH
BVHModel(const BVHModel& other);
BVHModelBase(const BVHModelBase& other);
/// @brief deconstruction, delete mesh data related.
~BVHModel()
{
delete [] vertices;
delete [] tri_indices;
delete [] bvs;
delete [] prev_vertices;
delete [] primitive_indices;
}
/// @brief We provide getBV() and getNumBVs() because BVH may be compressed (in future), so we must provide some flexibility here
/// @brief Access the bv giving the its index
const BVNode<BV>& getBV(int id) const
{
return bvs[id];
}
/// @brief Access the bv giving the its index
BVNode<BV>& getBV(int id)
{
return bvs[id];
}
/// @brief Get the number of bv in the BVH
int getNumBVs() const
{
return num_bvs;
}
virtual ~BVHModelBase() {}
/// @brief Get the object type: it is a BVH
OBJECT_TYPE getObjectType() const { return OT_BVH; }
/// @brief Get the BV type: default is unknown
NODE_TYPE getNodeType() const { return BV_UNKNOWN; }
/// @brief Compute the AABB for the BVH, used for broad-phase collision
void computeLocalAABB();
/// @brief Begin a new BVH model
int beginModel(int num_tris = 0, int num_vertices = 0);
int beginModel(unsigned int num_tris = 0, unsigned int num_vertices = 0);
/// @brief Add one point in the new BVH model
int addVertex(const Vec3f& p);
int addVertex(const Vec3s& p);
/// @brief Add points in the new BVH model
int addVertices(const MatrixX3s& points);
/// @brief Add triangles in the new BVH model
int addTriangles(const Matrixx3i& triangles);
/// @brief Add one triangle in the new BVH model
int addTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3);
int addTriangle(const Vec3s& p1, const Vec3s& p2, const Vec3s& p3);
/// @brief Add a set of triangles in the new BVH model
int addSubModel(const std::vector<Vec3f>& ps, const std::vector<Triangle>& ts);
int addSubModel(const std::vector<Vec3s>& ps,
const std::vector<Triangle>& ts);
/// @brief Add a set of points in the new BVH model
int addSubModel(const std::vector<Vec3f>& ps);
int addSubModel(const std::vector<Vec3s>& ps);
/// @brief End BVH model construction, will build the bounding volume hierarchy
/// @brief End BVH model construction, will build the bounding volume
/// hierarchy
int endModel();
/// @brief Replace the geometry information of current frame (i.e. should have the same mesh topology with the previous frame)
/// @brief Replace the geometry information of current frame (i.e. should have
/// the same mesh topology with the previous frame)
int beginReplaceModel();
/// @brief Replace one point in the old BVH model
int replaceVertex(const Vec3f& p);
int replaceVertex(const Vec3s& p);
/// @brief Replace one triangle in the old BVH model
int replaceTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3);
int replaceTriangle(const Vec3s& p1, const Vec3s& p2, const Vec3s& p3);
/// @brief Replace a set of points in the old BVH model
int replaceSubModel(const std::vector<Vec3f>& ps);
int replaceSubModel(const std::vector<Vec3s>& ps);
/// @brief End BVH model replacement, will also refit or rebuild the bounding volume hierarchy
/// @brief End BVH model replacement, will also refit or rebuild the bounding
/// volume hierarchy
int endReplaceModel(bool refit = true, bool bottomup = true);
/// @brief Replace the geometry information of current frame (i.e. should have the same mesh topology with the previous frame).
/// The current frame will be saved as the previous frame in prev_vertices.
/// @brief Replace the geometry information of current frame (i.e. should have
/// the same mesh topology with the previous frame). The current frame will be
/// saved as the previous frame in prev_vertices.
int beginUpdateModel();
/// @brief Update one point in the old BVH model
int updateVertex(const Vec3f& p);
int updateVertex(const Vec3s& p);
/// @brief Update one triangle in the old BVH model
int updateTriangle(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3);
int updateTriangle(const Vec3s& p1, const Vec3s& p2, const Vec3s& p3);
/// @brief Update a set of points in the old BVH model
int updateSubModel(const std::vector<Vec3f>& ps);
int updateSubModel(const std::vector<Vec3s>& ps);
/// @brief End BVH model update, will also refit or rebuild the bounding volume hierarchy
/// @brief End BVH model update, will also refit or rebuild the bounding
/// volume hierarchy
int endUpdateModel(bool refit = true, bool bottomup = true);
/// @brief Check the number of memory used
int memUsage(int msg) const;
/// @brief This is a special acceleration: BVH_model default stores the BV's transform in world coordinate. However, we can also store each BV's transform related to its parent
/// BV node. When traversing the BVH, this can save one matrix transformation.
void makeParentRelative()
{
Vec3f I[3] = {Vec3f(1, 0, 0), Vec3f(0, 1, 0), Vec3f(0, 0, 1)};
makeParentRelativeRecurse(0, I, Vec3f());
}
/// @brief Build this \ref Convex "Convex<Triangle>" representation of this
/// model. The result is stored in attribute \ref convex. \note this only
/// takes the points of this model. It does not check that the
/// object is convex. It does not compute a convex hull.
void buildConvexRepresentation(bool share_memory);
/// @brief Build a convex hull
/// and store it in attribute \ref convex.
/// \param keepTriangle whether the convex should be triangulated.
/// \param qhullCommand see \ref ConvexBase::convexHull.
/// \return \c true if this object is convex, hence the convex hull represents
/// the same object.
/// \sa ConvexBase::convexHull
/// \warning At the moment, the return value only checks whether there are as
/// many points in the convex hull as in the original object. This is
/// neither necessary (duplicated vertices get merged) nor sufficient
/// (think of a U with 4 vertices and 3 edges).
bool buildConvexHull(bool keepTriangle, const char* qhullCommand = NULL);
virtual int memUsage(const bool msg = false) const = 0;
/// @brief This is a special acceleration: BVH_model default stores the BV's
/// transform in world coordinate. However, we can also store each BV's
/// transform related to its parent BV node. When traversing the BVH, this can
/// save one matrix transformation.
virtual void makeParentRelative() = 0;
Vec3s computeCOM() const {
CoalScalar vol = 0;
Vec3s com(0, 0, 0);
if (!(vertices.get())) {
std::cerr << "BVH Error in `computeCOM`! The BVHModel does not contain "
"vertices."
<< std::endl;
return com;
}
const std::vector<Vec3s>& vertices_ = *vertices;
if (!(tri_indices.get())) {
std::cerr << "BVH Error in `computeCOM`! The BVHModel does not contain "
"triangles."
<< std::endl;
return com;
}
const std::vector<Triangle>& tri_indices_ = *tri_indices;
Vec3f computeCOM() const
{
FCL_REAL vol = 0;
Vec3f com;
for(int i = 0; i < num_tris; ++i)
{
const Triangle& tri = tri_indices[i];
FCL_REAL d_six_vol = (vertices[tri[0]].cross(vertices[tri[1]])).dot(vertices[tri[2]]);
for (unsigned int i = 0; i < num_tris; ++i) {
const Triangle& tri = tri_indices_[i];
CoalScalar d_six_vol =
(vertices_[tri[0]].cross(vertices_[tri[1]])).dot(vertices_[tri[2]]);
vol += d_six_vol;
com += (vertices[tri[0]] + vertices[tri[1]] + vertices[tri[2]]) * d_six_vol;
com += (vertices_[tri[0]] + vertices_[tri[1]] + vertices_[tri[2]]) *
d_six_vol;
}
return com / (vol * 4);
}
FCL_REAL computeVolume() const
{
FCL_REAL vol = 0;
for(int i = 0; i < num_tris; ++i)
{
const Triangle& tri = tri_indices[i];
FCL_REAL d_six_vol = (vertices[tri[0]].cross(vertices[tri[1]])).dot(vertices[tri[2]]);
CoalScalar computeVolume() const {
CoalScalar vol = 0;
if (!(vertices.get())) {
std::cerr << "BVH Error in `computeCOM`! The BVHModel does not contain "
"vertices."
<< std::endl;
return vol;
}
const std::vector<Vec3s>& vertices_ = *vertices;
if (!(tri_indices.get())) {
std::cerr << "BVH Error in `computeCOM`! The BVHModel does not contain "
"triangles."
<< std::endl;
return vol;
}
const std::vector<Triangle>& tri_indices_ = *tri_indices;
for (unsigned int i = 0; i < num_tris; ++i) {
const Triangle& tri = tri_indices_[i];
CoalScalar d_six_vol =
(vertices_[tri[0]].cross(vertices_[tri[1]])).dot(vertices_[tri[2]]);
vol += d_six_vol;
}
return vol / 6;
}
Matrix3f computeMomentofInertia() const
{
Matrix3f C(0, 0, 0,
0, 0, 0,
0, 0, 0);
Matrix3f C_canonical(1/60.0, 1/120.0, 1/120.0,
1/120.0, 1/60.0, 1/120.0,
1/120.0, 1/120.0, 1/60.0);
for(int i = 0; i < num_tris; ++i)
{
const Triangle& tri = tri_indices[i];
const Vec3f& v1 = vertices[tri[0]];
const Vec3f& v2 = vertices[tri[1]];
const Vec3f& v3 = vertices[tri[2]];
FCL_REAL d_six_vol = (v1.cross(v2)).dot(v3);
Matrix3f A(v1, v2, v3);
C += transpose(A) * C_canonical * A * d_six_vol;
}
Matrix3s computeMomentofInertia() const {
Matrix3s C = Matrix3s::Zero();
Matrix3s C_canonical;
C_canonical << 1 / 60.0, 1 / 120.0, 1 / 120.0, 1 / 120.0, 1 / 60.0,
1 / 120.0, 1 / 120.0, 1 / 120.0, 1 / 60.0;
FCL_REAL trace_C = C(0, 0) + C(1, 1) + C(2, 2);
if (!(vertices.get())) {
std::cerr << "BVH Error in `computeMomentofInertia`! The BVHModel does "
"not contain vertices."
<< std::endl;
return C;
}
const std::vector<Vec3s>& vertices_ = *vertices;
if (!(vertices.get())) {
std::cerr << "BVH Error in `computeMomentofInertia`! The BVHModel does "
"not contain vertices."
<< std::endl;
return C;
}
const std::vector<Triangle>& tri_indices_ = *tri_indices;
for (unsigned int i = 0; i < num_tris; ++i) {
const Triangle& tri = tri_indices_[i];
const Vec3s& v1 = vertices_[tri[0]];
const Vec3s& v2 = vertices_[tri[1]];
const Vec3s& v3 = vertices_[tri[2]];
Matrix3s A;
A << v1.transpose(), v2.transpose(), v3.transpose();
C += A.derived().transpose() * C_canonical * A * (v1.cross(v2)).dot(v3);
}
return Matrix3f(trace_C - C(0, 0), -C(0, 1), -C(0, 2),
-C(1, 0), trace_C - C(1, 1), -C(1, 2),
-C(2, 0), -C(2, 1), trace_C - C(2, 2));
return C.trace() * Matrix3s::Identity() - C;
}
public:
/// @brief Geometry point data
Vec3f* vertices;
protected:
virtual void deleteBVs() = 0;
virtual bool allocateBVs() = 0;
/// @brief Geometry triangle index data, will be NULL for point clouds
Triangle* tri_indices;
/// @brief Build the bounding volume hierarchy
virtual int buildTree() = 0;
/// @brief Geometry point data in previous frame
Vec3f* prev_vertices;
/// @brief Refit the bounding volume hierarchy
virtual int refitTree(bool bottomup) = 0;
/// @brief Number of triangles
int num_tris;
unsigned int num_tris_allocated;
unsigned int num_vertices_allocated;
unsigned int num_vertex_updated; /// for ccd vertex update
/// @brief Number of points
int num_vertices;
protected:
/// \brief Comparison operators
virtual bool isEqual(const CollisionGeometry& other) const;
};
/// @brief The state of BVH building process
BVHBuildState build_state;
/// @brief A class describing the bounding hierarchy of a mesh model or a point
/// cloud model (which is viewed as a degraded version of mesh) \tparam BV one
/// of the bounding volume class in \ref Bounding_Volume.
template <typename BV>
class COAL_DLLAPI BVHModel : public BVHModelBase {
typedef BVHModelBase Base;
public:
using bv_node_vector_t =
std::vector<BVNode<BV>, Eigen::aligned_allocator<BVNode<BV>>>;
/// @brief Split rule to split one BV node into two children
boost::shared_ptr<BVSplitterBase<BV> > bv_splitter;
shared_ptr<BVSplitter<BV>> bv_splitter;
/// @brief Fitting rule to fit a BV node to a set of geometry primitives
boost::shared_ptr<BVFitterBase<BV> > bv_fitter;
shared_ptr<BVFitter<BV>> bv_fitter;
/// @brief Default constructor to build an empty BVH
BVHModel();
/// @brief Copy constructor from another BVH
///
/// \param[in] other BVHModel to copy.
///
BVHModel(const BVHModel& other);
/// @brief Clone *this into a new BVHModel
virtual BVHModel<BV>* clone() const { return new BVHModel(*this); }
private:
/// @brief deconstruction, delete mesh data related.
~BVHModel() {}
/// @brief We provide getBV() and getNumBVs() because BVH may be compressed
/// (in future), so we must provide some flexibility here
/// @brief Access the bv giving the its index
const BVNode<BV>& getBV(unsigned int i) const {
assert(i < num_bvs);
return (*bvs)[i];
}
/// @brief Access the bv giving the its index
BVNode<BV>& getBV(unsigned int i) {
assert(i < num_bvs);
return (*bvs)[i];
}
/// @brief Get the number of bv in the BVH
unsigned int getNumBVs() const { return num_bvs; }
int num_tris_allocated;
int num_vertices_allocated;
int num_bvs_allocated;
int num_vertex_updated; /// for ccd vertex update
unsigned int* primitive_indices;
/// @brief Get the BV type: default is unknown
NODE_TYPE getNodeType() const { return BV_UNKNOWN; }
/// @brief Check the number of memory used
int memUsage(const bool msg) const;
/// @brief This is a special acceleration: BVH_model default stores the BV's
/// transform in world coordinate. However, we can also store each BV's
/// transform related to its parent BV node. When traversing the BVH, this can
/// save one matrix transformation.
void makeParentRelative() {
Matrix3s I(Matrix3s::Identity());
makeParentRelativeRecurse(0, I, Vec3s::Zero());
}
protected:
void deleteBVs();
bool allocateBVs();
unsigned int num_bvs_allocated;
std::shared_ptr<std::vector<unsigned int>> primitive_indices;
/// @brief Bounding volume hierarchy
BVNode<BV>* bvs;
std::shared_ptr<bv_node_vector_t> bvs;
/// @brief Number of BV nodes in bounding volume hierarchy
int num_bvs;
unsigned int num_bvs;
/// @brief Build the bounding volume hierarchy
int buildTree();
......@@ -295,69 +391,149 @@ private:
/// @brief Refit the bounding volume hierarchy
int refitTree(bool bottomup);
/// @brief Refit the bounding volume hierarchy in a top-down way (slow but more compact)
/// @brief Refit the bounding volume hierarchy in a top-down way (slow but
/// more compact)
int refitTree_topdown();
/// @brief Refit the bounding volume hierarchy in a bottom-up way (fast but less compact)
/// @brief Refit the bounding volume hierarchy in a bottom-up way (fast but
/// less compact)
int refitTree_bottomup();
/// @brief Recursive kernel for hierarchy construction
int recursiveBuildTree(int bv_id, int first_primitive, int num_primitives);
int recursiveBuildTree(int bv_id, unsigned int first_primitive,
unsigned int num_primitives);
/// @brief Recursive kernel for bottomup refitting
/// @brief Recursive kernel for bottomup refitting
int recursiveRefitTree_bottomup(int bv_id);
/// @recursively compute each bv's transform related to its parent. For default BV, only the translation works.
/// For oriented BV (OBB, RSS, OBBRSS), special implementation is provided.
void makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c)
{
if(!bvs[bv_id].isLeaf())
{
makeParentRelativeRecurse(bvs[bv_id].first_child, parent_axis, bvs[bv_id].getCenter());
/// @ recursively compute each bv's transform related to its parent. For
/// default BV, only the translation works. For oriented BV (OBB, RSS,
/// OBBRSS), special implementation is provided.
void makeParentRelativeRecurse(int bv_id, Matrix3s& parent_axes,
const Vec3s& parent_c) {
bv_node_vector_t& bvs_ = *bvs;
if (!bvs_[static_cast<size_t>(bv_id)].isLeaf()) {
makeParentRelativeRecurse(bvs_[static_cast<size_t>(bv_id)].first_child,
parent_axes,
bvs_[static_cast<size_t>(bv_id)].getCenter());
makeParentRelativeRecurse(
bvs_[static_cast<size_t>(bv_id)].first_child + 1, parent_axes,
bvs_[static_cast<size_t>(bv_id)].getCenter());
}
makeParentRelativeRecurse(bvs[bv_id].first_child + 1, parent_axis, bvs[bv_id].getCenter());
bvs_[static_cast<size_t>(bv_id)].bv =
translate(bvs_[static_cast<size_t>(bv_id)].bv, -parent_c);
}
private:
virtual bool isEqual(const CollisionGeometry& _other) const {
const BVHModel* other_ptr = dynamic_cast<const BVHModel*>(&_other);
if (other_ptr == nullptr) return false;
const BVHModel& other = *other_ptr;
bool res = Base::isEqual(other);
if (!res) return false;
// unsigned int other_num_primitives = 0;
// if(other.primitive_indices)
// {
// switch(other.getModelType())
// {
// case BVH_MODEL_TRIANGLES:
// other_num_primitives = num_tris;
// break;
// case BVH_MODEL_POINTCLOUD:
// other_num_primitives = num_vertices;
// break;
// default:
// ;
// }
// }
// unsigned int num_primitives = 0;
// if(primitive_indices)
// {
//
// switch(other.getModelType())
// {
// case BVH_MODEL_TRIANGLES:
// num_primitives = num_tris;
// break;
// case BVH_MODEL_POINTCLOUD:
// num_primitives = num_vertices;
// break;
// default:
// ;
// }
// }
//
// if(num_primitives != other_num_primitives)
// return false;
//
// for(int k = 0; k < num_primitives; ++k)
// {
// if(primitive_indices[k] != other.primitive_indices[k])
// return false;
// }
if (num_bvs != other.num_bvs) return false;
if ((!(bvs.get()) && other.bvs.get()) || (bvs.get() && !(other.bvs.get())))
return false;
if (bvs.get() && other.bvs.get()) {
const bv_node_vector_t& bvs_ = *bvs;
const bv_node_vector_t& other_bvs_ = *(other.bvs);
for (unsigned int k = 0; k < num_bvs; ++k) {
if (bvs_[k] != other_bvs_[k]) return false;
}
}
bvs[bv_id].bv = translate(bvs[bv_id].bv, -parent_c);
return true;
}
};
/// @}
template<>
void BVHModel<OBB>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c);
template<>
void BVHModel<RSS>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c);
template <>
void BVHModel<OBB>::makeParentRelativeRecurse(int bv_id, Matrix3s& parent_axes,
const Vec3s& parent_c);
template<>
void BVHModel<OBBRSS>::makeParentRelativeRecurse(int bv_id, Vec3f parent_axis[], const Vec3f& parent_c);
template <>
void BVHModel<RSS>::makeParentRelativeRecurse(int bv_id, Matrix3s& parent_axes,
const Vec3s& parent_c);
template <>
void BVHModel<OBBRSS>::makeParentRelativeRecurse(int bv_id,
Matrix3s& parent_axes,
const Vec3s& parent_c);
/// @brief Specialization of getNodeType() for BVHModel with different BV types
template<>
template <>
NODE_TYPE BVHModel<AABB>::getNodeType() const;
template<>
template <>
NODE_TYPE BVHModel<OBB>::getNodeType() const;
template<>
template <>
NODE_TYPE BVHModel<RSS>::getNodeType() const;
template<>
template <>
NODE_TYPE BVHModel<kIOS>::getNodeType() const;
template<>
template <>
NODE_TYPE BVHModel<OBBRSS>::getNodeType() const;
template<>
NODE_TYPE BVHModel<KDOP<16> >::getNodeType() const;
template <>
NODE_TYPE BVHModel<KDOP<16>>::getNodeType() const;
template<>
NODE_TYPE BVHModel<KDOP<18> >::getNodeType() const;
template <>
NODE_TYPE BVHModel<KDOP<18>>::getNodeType() const;
template<>
NODE_TYPE BVHModel<KDOP<24> >::getNodeType() const;
template <>
NODE_TYPE BVHModel<KDOP<24>>::getNodeType() const;
}
} // namespace coal
#endif
......@@ -35,138 +35,81 @@
/** \author Jia Pan */
#ifndef FCL_GJK_LIBCCD_H
#define FCL_GJK_LIBCCD_H
#include "fcl/shape/geometric_shapes.h"
#include "fcl/math/transform.h"
#include <ccd/ccd.h>
#include <ccd/quat.h>
namespace fcl
{
namespace details
{
/// @brief callback function used by GJK algorithm
typedef void (*GJKSupportFunction)(const void* obj, const ccd_vec3_t* dir_, ccd_vec3_t* v);
typedef void (*GJKCenterFunction)(const void* obj, ccd_vec3_t* c);
/// @brief initialize GJK stuffs
template<typename T>
class GJKInitializer
{
public:
/// @brief Get GJK support function
static GJKSupportFunction getSupportFunction() { return NULL; }
/// @brief Get GJK center function
static GJKCenterFunction getCenterFunction() { return NULL; }
/// @brief Get GJK object from a shape
/// Notice that only local transformation is applied.
/// Gloal transformation are considered later
static void* createGJKObject(const T& /* s */, const Transform3f& /*tf*/) { return NULL; }
/// @brief Delete GJK object
static void deleteGJKObject(void* o) {}
};
/// @brief initialize GJK Cylinder
template<>
class GJKInitializer<Cylinder>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Cylinder& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Sphere
template<>
class GJKInitializer<Sphere>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Sphere& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Box
template<>
class GJKInitializer<Box>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Box& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Capsule
template<>
class GJKInitializer<Capsule>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Capsule& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Cone
template<>
class GJKInitializer<Cone>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Cone& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Convex
template<>
class GJKInitializer<Convex>
{
public:
static GJKSupportFunction getSupportFunction();
static GJKCenterFunction getCenterFunction();
static void* createGJKObject(const Convex& s, const Transform3f& tf);
static void deleteGJKObject(void* o);
};
/// @brief initialize GJK Triangle
GJKSupportFunction triGetSupportFunction();
GJKCenterFunction triGetCenterFunction();
void* triCreateGJKObject(const Vec3f& P1, const Vec3f& P2, const Vec3f& P3);
void* triCreateGJKObject(const Vec3f& P1, const Vec3f& P2, const Vec3f& P3, const Transform3f& tf);
void triDeleteGJKObject(void* o);
/// @brief GJK collision algorithm
bool GJKCollide(void* obj1, ccd_support_fn supp1, ccd_center_fn cen1,
void* obj2, ccd_support_fn supp2, ccd_center_fn cen2,
unsigned int max_iterations, FCL_REAL tolerance,
Vec3f* contact_points, FCL_REAL* penetration_depth, Vec3f* normal);
bool GJKDistance(void* obj1, ccd_support_fn supp1,
void* obj2, ccd_support_fn supp2,
unsigned int max_iterations, FCL_REAL tolerance,
FCL_REAL* dist, Vec3f* p1, Vec3f* p2);
} // details
}
#ifndef COAL_BVH_UTILITY_H
#define COAL_BVH_UTILITY_H
#include "coal/BVH/BVH_model.h"
namespace coal {
/// @brief Extract the part of the BVHModel that is inside an AABB.
/// A triangle in collision with the AABB is considered inside.
template <typename BV>
COAL_DLLAPI BVHModel<BV>* BVHExtract(const BVHModel<BV>& model,
const Transform3s& pose, const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<OBB>* BVHExtract(const BVHModel<OBB>& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<AABB>* BVHExtract(const BVHModel<AABB>& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<RSS>* BVHExtract(const BVHModel<RSS>& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<kIOS>* BVHExtract(const BVHModel<kIOS>& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<OBBRSS>* BVHExtract(const BVHModel<OBBRSS>& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<KDOP<16> >* BVHExtract(const BVHModel<KDOP<16> >& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<KDOP<18> >* BVHExtract(const BVHModel<KDOP<18> >& model,
const Transform3s& pose,
const AABB& aabb);
template <>
COAL_DLLAPI BVHModel<KDOP<24> >* BVHExtract(const BVHModel<KDOP<24> >& model,
const Transform3s& pose,
const AABB& aabb);
/// @brief Compute the covariance matrix for a set or subset of points. if ts =
/// null, then indices refer to points directly; otherwise refer to triangles
COAL_DLLAPI void getCovariance(Vec3s* ps, Vec3s* ps2, Triangle* ts,
unsigned int* indices, unsigned int n,
Matrix3s& M);
/// @brief Compute the RSS bounding volume parameters: radius, rectangle size
/// and the origin, given the BV axises.
COAL_DLLAPI void getRadiusAndOriginAndRectangleSize(
Vec3s* ps, Vec3s* ps2, Triangle* ts, unsigned int* indices, unsigned int n,
const Matrix3s& axes, Vec3s& origin, CoalScalar l[2], CoalScalar& r);
/// @brief Compute the bounding volume extent and center for a set or subset of
/// points, given the BV axises.
COAL_DLLAPI void getExtentAndCenter(Vec3s* ps, Vec3s* ps2, Triangle* ts,
unsigned int* indices, unsigned int n,
Matrix3s& axes, Vec3s& center,
Vec3s& extent);
/// @brief Compute the center and radius for a triangle's circumcircle
COAL_DLLAPI void circumCircleComputation(const Vec3s& a, const Vec3s& b,
const Vec3s& c, Vec3s& center,
CoalScalar& radius);
/// @brief Compute the maximum distance from a given center point to a point
/// cloud
COAL_DLLAPI CoalScalar maximumDistance(Vec3s* ps, Vec3s* ps2, Triangle* ts,
unsigned int* indices, unsigned int n,
const Vec3s& query);
} // namespace coal
#endif
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2022, Inria
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Open Source Robotics Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COAL_BROADPHASE_BROADPHASE_H
#define COAL_BROADPHASE_BROADPHASE_H
#include "coal/broadphase/broadphase_dynamic_AABB_tree.h"
#include "coal/broadphase/broadphase_dynamic_AABB_tree_array.h"
#include "coal/broadphase/broadphase_bruteforce.h"
#include "coal/broadphase/broadphase_SaP.h"
#include "coal/broadphase/broadphase_SSaP.h"
#include "coal/broadphase/broadphase_interval_tree.h"
#include "coal/broadphase/broadphase_spatialhash.h"
#include "coal/broadphase/default_broadphase_callbacks.h"
#endif // ifndef COAL_BROADPHASE_BROADPHASE_H
......@@ -2,7 +2,7 @@
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -31,25 +31,25 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
/** \author Jia Pan */
/** @author Jia Pan */
#ifndef COAL_BROAD_PHASE_SSAP_H
#define COAL_BROAD_PHASE_SSAP_H
#ifndef FCL_BROAD_PHASE_SSAP_H
#define FCL_BROAD_PHASE_SSAP_H
#include <vector>
#include "coal/broadphase/broadphase_collision_manager.h"
#include "fcl/broadphase/broadphase.h"
namespace coal {
namespace fcl
{
/// @brief Simple SAP collision manager
class COAL_DLLAPI SSaPCollisionManager : public BroadPhaseCollisionManager {
public:
typedef BroadPhaseCollisionManager Base;
using Base::getObjects;
/// @brief Simple SAP collision manager
class SSaPCollisionManager : public BroadPhaseCollisionManager
{
public:
SSaPCollisionManager() : setup_(false)
{}
SSaPCollisionManager();
/// @brief remove one object from the manager
void registerObject(CollisionObject* obj);
......@@ -61,7 +61,7 @@ public:
void setup();
/// @brief update the condition of manager
void update();
virtual void update();
/// @brief clear the manager
void clear();
......@@ -69,75 +69,63 @@ public:
/// @brief return the objects managed by the manager
void getObjects(std::vector<CollisionObject*>& objs) const;
/// @brief perform collision test between one object and all the objects belonging to the manager
void collide(CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test between one object and all the objects
/// belonging to the manager
void collide(CollisionObject* obj, CollisionCallBackBase* callback) const;
/// @brief perform distance computation between one object and all the objects belonging to the manager
void distance(CollisionObject* obj, void* cdata, DistanceCallBack callback) const;
/// @brief perform distance computation between one object and all the objects
/// belonging to the manager
void distance(CollisionObject* obj, DistanceCallBackBase* callback) const;
/// @brief perform collision test for the objects belonging to the manager (i.e., N^2 self collision)
void collide(void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test for the objects belonging to the manager
/// (i.e., N^2 self collision)
void collide(CollisionCallBackBase* callback) const;
/// @brief perform distance test for the objects belonging to the manager (i.e., N^2 self distance)
void distance(void* cdata, DistanceCallBack callback) const;
/// @brief perform distance test for the objects belonging to the manager
/// (i.e., N^2 self distance)
void distance(DistanceCallBackBase* callback) const;
/// @brief perform collision test with objects belonging to another manager
void collide(BroadPhaseCollisionManager* other_manager, void* cdata, CollisionCallBack callback) const;
void collide(BroadPhaseCollisionManager* other_manager,
CollisionCallBackBase* callback) const;
/// @brief perform distance test with objects belonging to another manager
void distance(BroadPhaseCollisionManager* other_manager, void* cdata, DistanceCallBack callback) const;
void distance(BroadPhaseCollisionManager* other_manager,
DistanceCallBackBase* callback) const;
/// @brief whether the manager is empty
bool empty() const;
/// @brief the number of objects managed by the manager
inline size_t size() const { return objs_x.size(); }
protected:
/// @brief check collision between one object and a list of objects, return value is whether stop is possible
bool checkColl(std::vector<CollisionObject*>::const_iterator pos_start, std::vector<CollisionObject*>::const_iterator pos_end,
CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
/// @brief check distance between one object and a list of objects, return value is whether stop is possible
bool checkDis(std::vector<CollisionObject*>::const_iterator pos_start, std::vector<CollisionObject*>::const_iterator pos_end,
CollisionObject* obj, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const;
bool collide_(CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
bool distance_(CollisionObject* obj, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const;
static inline size_t selectOptimalAxis(const std::vector<CollisionObject*>& objs_x, const std::vector<CollisionObject*>& objs_y, const std::vector<CollisionObject*>& objs_z, std::vector<CollisionObject*>::const_iterator& it_beg, std::vector<CollisionObject*>::const_iterator& it_end)
{
/// simple sweep and prune method
double delta_x = (objs_x[objs_x.size() - 1])->getAABB().min_[0] - (objs_x[0])->getAABB().min_[0];
double delta_y = (objs_x[objs_y.size() - 1])->getAABB().min_[1] - (objs_y[0])->getAABB().min_[1];
double delta_z = (objs_z[objs_z.size() - 1])->getAABB().min_[2] - (objs_z[0])->getAABB().min_[2];
int axis = 0;
if(delta_y > delta_x && delta_y > delta_z)
axis = 1;
else if(delta_z > delta_y && delta_z > delta_x)
axis = 2;
switch(axis)
{
case 0:
it_beg = objs_x.begin();
it_end = objs_x.end();
break;
case 1:
it_beg = objs_y.begin();
it_end = objs_y.end();
break;
case 2:
it_beg = objs_z.begin();
it_end = objs_z.end();
break;
}
return axis;
}
/// @brief the number of objects managed by the manager
size_t size() const;
protected:
/// @brief check collision between one object and a list of objects, return
/// value is whether stop is possible
bool checkColl(
typename std::vector<CollisionObject*>::const_iterator pos_start,
typename std::vector<CollisionObject*>::const_iterator pos_end,
CollisionObject* obj, CollisionCallBackBase* callback) const;
/// @brief check distance between one object and a list of objects, return
/// value is whether stop is possible
bool checkDis(
typename std::vector<CollisionObject*>::const_iterator pos_start,
typename std::vector<CollisionObject*>::const_iterator pos_end,
CollisionObject* obj, DistanceCallBackBase* callback,
CoalScalar& min_dist) const;
bool collide_(CollisionObject* obj, CollisionCallBackBase* callback) const;
bool distance_(CollisionObject* obj, DistanceCallBackBase* callback,
CoalScalar& min_dist) const;
static int selectOptimalAxis(
const std::vector<CollisionObject*>& objs_x,
const std::vector<CollisionObject*>& objs_y,
const std::vector<CollisionObject*>& objs_z,
typename std::vector<CollisionObject*>::const_iterator& it_beg,
typename std::vector<CollisionObject*>::const_iterator& it_end);
/// @brief Objects sorted according to lower x value
std::vector<CollisionObject*> objs_x;
......@@ -148,11 +136,11 @@ protected:
/// @brief Objects sorted according to lower z value
std::vector<CollisionObject*> objs_z;
/// @brief tag about whether the environment is maintained suitably (i.e., the objs_x, objs_y, objs_z are sorted correctly
/// @brief tag about whether the environment is maintained suitably (i.e., the
/// objs_x, objs_y, objs_z are sorted correctly
bool setup_;
};
}
} // namespace coal
#endif
......@@ -2,7 +2,7 @@
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -31,39 +31,29 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
/** \author Jia Pan */
/** @author Jia Pan */
#ifndef FCL_BROAD_PHASE_SAP_H
#define FCL_BROAD_PHASE_SAP_H
#include "fcl/broadphase/broadphase.h"
#ifndef COAL_BROAD_PHASE_SAP_H
#define COAL_BROAD_PHASE_SAP_H
#include <map>
#include <list>
namespace fcl
{
#include "coal/broadphase/broadphase_collision_manager.h"
/// @brief Rigorous SAP collision manager
class SaPCollisionManager : public BroadPhaseCollisionManager
{
public:
namespace coal {
SaPCollisionManager()
{
elist[0] = NULL;
elist[1] = NULL;
elist[2] = NULL;
/// @brief Rigorous SAP collision manager
class COAL_DLLAPI SaPCollisionManager : public BroadPhaseCollisionManager {
public:
typedef BroadPhaseCollisionManager Base;
using Base::getObjects;
optimal_axis = 0;
}
SaPCollisionManager();
~SaPCollisionManager()
{
clear();
}
~SaPCollisionManager();
/// @brief add objects to the manager
void registerObjects(const std::vector<CollisionObject*>& other_objs);
......@@ -78,7 +68,7 @@ public:
void setup();
/// @brief update the condition of manager
void update();
virtual void update();
/// @brief update the manager by explicitly given the object updated
void update(CollisionObject* updated_obj);
......@@ -92,37 +82,41 @@ public:
/// @brief return the objects managed by the manager
void getObjects(std::vector<CollisionObject*>& objs) const;
/// @brief perform collision test between one object and all the objects belonging to the manager
void collide(CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test between one object and all the objects
/// belonging to the manager
void collide(CollisionObject* obj, CollisionCallBackBase* callback) const;
/// @brief perform distance computation between one object and all the objects belonging to the manager
void distance(CollisionObject* obj, void* cdata, DistanceCallBack callback) const;
/// @brief perform distance computation between one object and all the objects
/// belonging to the manager
void distance(CollisionObject* obj, DistanceCallBackBase* callback) const;
/// @brief perform collision test for the objects belonging to the manager (i.e., N^2 self collision)
void collide(void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test for the objects belonging to the manager
/// (i.e., N^2 self collision)
void collide(CollisionCallBackBase* callback) const;
/// @brief perform distance test for the objects belonging to the manager (i.e., N^2 self distance)
void distance(void* cdata, DistanceCallBack callback) const;
/// @brief perform distance test for the objects belonging to the manager
/// (i.e., N^2 self distance)
void distance(DistanceCallBackBase* callback) const;
/// @brief perform collision test with objects belonging to another manager
void collide(BroadPhaseCollisionManager* other_manager, void* cdata, CollisionCallBack callback) const;
void collide(BroadPhaseCollisionManager* other_manager,
CollisionCallBackBase* callback) const;
/// @brief perform distance test with objects belonging to another manager
void distance(BroadPhaseCollisionManager* other_manager, void* cdata, DistanceCallBack callback) const;
void distance(BroadPhaseCollisionManager* other_manager,
DistanceCallBackBase* callback) const;
/// @brief whether the manager is empty
bool empty() const;
/// @brief the number of objects managed by the manager
inline size_t size() const { return AABB_arr.size(); }
protected:
/// @brief the number of objects managed by the manager
size_t size() const;
protected:
struct EndPoint;
/// @brief SAP interval for one object
struct SaPAABB
{
struct SaPAABB {
/// @brief object
CollisionObject* obj;
......@@ -137,9 +131,9 @@ protected:
};
/// @brief End point for an interval
struct EndPoint
{
/// @brief tag for whether it is a lower bound or higher bound of an interval, 0 for lo, and 1 for hi
struct EndPoint {
/// @brief tag for whether it is a lower bound or higher bound of an
/// interval, 0 for lo, and 1 for hi
char minmax;
/// @brief back pointer to SAP interval
......@@ -147,116 +141,61 @@ protected:
/// @brief the previous end point in the end point list
EndPoint* prev[3];
/// @brief the next end point in the end point list
EndPoint* next[3];
/// @brief get the value of the end point
inline const Vec3f& getVal() const
{
if(minmax) return aabb->cached.max_;
else return aabb->cached.min_;
}
const Vec3s& getVal() const;
/// @brief set the value of the end point
inline Vec3f& getVal()
{
if(minmax) return aabb->cached.max_;
else return aabb->cached.min_;
}
inline Vec3f::U getVal(size_t i) const
{
if(minmax) return aabb->cached.max_[i];
else return aabb->cached.min_[i];
}
inline Vec3f::U& getVal(size_t i)
{
if(minmax) return aabb->cached.max_[i];
else return aabb->cached.min_[i];
}
Vec3s& getVal();
CoalScalar getVal(int i) const;
CoalScalar& getVal(int i);
};
/// @brief A pair of objects that are not culling away and should further check collision
struct SaPPair
{
SaPPair(CollisionObject* a, CollisionObject* b)
{
if(a < b)
{
obj1 = a;
obj2 = b;
}
else
{
obj1 = b;
obj2 = a;
}
}
/// @brief A pair of objects that are not culling away and should further
/// check collision
struct SaPPair {
SaPPair(CollisionObject* a, CollisionObject* b);
CollisionObject* obj1;
CollisionObject* obj2;
bool operator == (const SaPPair& other) const
{
return ((obj1 == other.obj1) && (obj2 == other.obj2));
}
bool operator==(const SaPPair& other) const;
};
/// @brief Functor to help unregister one object
class isUnregistered
{
class COAL_DLLAPI isUnregistered {
CollisionObject* obj;
public:
isUnregistered(CollisionObject* obj_) : obj(obj_)
{}
public:
isUnregistered(CollisionObject* obj_);
bool operator() (const SaPPair& pair) const
{
return (pair.obj1 == obj) || (pair.obj2 == obj);
}
bool operator()(const SaPPair& pair) const;
};
/// @brief Functor to help remove collision pairs no longer valid (i.e., should be culled away)
class isNotValidPair
{
/// @brief Functor to help remove collision pairs no longer valid (i.e.,
/// should be culled away)
class COAL_DLLAPI isNotValidPair {
CollisionObject* obj1;
CollisionObject* obj2;
public:
isNotValidPair(CollisionObject* obj1_, CollisionObject* obj2_) : obj1(obj1_),
obj2(obj2_)
{}
public:
isNotValidPair(CollisionObject* obj1_, CollisionObject* obj2_);
bool operator() (const SaPPair& pair)
{
return (pair.obj1 == obj1) && (pair.obj2 == obj2);
}
bool operator()(const SaPPair& pair);
};
void update_(SaPAABB* updated_aabb);
void updateVelist()
{
for(int coord = 0; coord < 3; ++coord)
{
velist[coord].resize(size() * 2);
EndPoint* current = elist[coord];
size_t id = 0;
while(current)
{
velist[coord][id] = current;
current = current->next[coord];
id++;
}
}
}
void updateVelist();
/// @brief End point list for x, y, z coordinates
EndPoint* elist[3];
/// @brief vector version of elist, for acceleration
std::vector<EndPoint*> velist[3];
......@@ -266,52 +205,20 @@ protected:
/// @brief The pair of objects that should further check for collision
std::list<SaPPair> overlap_pairs;
size_t optimal_axis;
int optimal_axis;
std::map<CollisionObject*, SaPAABB*> obj_aabb_map;
bool distance_(CollisionObject* obj, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const;
bool collide_(CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
void addToOverlapPairs(const SaPPair& p)
{
bool repeated = false;
for(std::list<SaPPair>::iterator it = overlap_pairs.begin(), end = overlap_pairs.end();
it != end;
++it)
{
if(*it == p)
{
repeated = true;
break;
}
}
if(!repeated)
overlap_pairs.push_back(p);
}
void removeFromOverlapPairs(const SaPPair& p)
{
for(std::list<SaPPair>::iterator it = overlap_pairs.begin(), end = overlap_pairs.end();
it != end;
++it)
{
if(*it == p)
{
overlap_pairs.erase(it);
break;
}
}
// or overlap_pairs.remove_if(isNotValidPair(p));
}
};
bool distance_(CollisionObject* obj, DistanceCallBackBase* callback,
CoalScalar& min_dist) const;
bool collide_(CollisionObject* obj, CollisionCallBackBase* callback) const;
void addToOverlapPairs(const SaPPair& p);
}
void removeFromOverlapPairs(const SaPPair& p);
};
} // namespace coal
#endif
......@@ -2,7 +2,7 @@
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -31,25 +31,25 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
/** \author Jia Pan */
/** @author Jia Pan */
#ifndef FCL_BROAD_PHASE_BRUTE_FORCE_H
#define FCL_BROAD_PHASE_BRUTE_FORCE_H
#ifndef COAL_BROAD_PHASE_BRUTE_FORCE_H
#define COAL_BROAD_PHASE_BRUTE_FORCE_H
#include "fcl/broadphase/broadphase.h"
#include <list>
#include "coal/broadphase/broadphase_collision_manager.h"
namespace fcl
{
namespace coal {
/// @brief Brute force N-body collision manager
class NaiveCollisionManager : public BroadPhaseCollisionManager
{
public:
NaiveCollisionManager() {}
class COAL_DLLAPI NaiveCollisionManager : public BroadPhaseCollisionManager {
public:
typedef BroadPhaseCollisionManager Base;
using Base::getObjects;
NaiveCollisionManager();
/// @brief add objects to the manager
void registerObjects(const std::vector<CollisionObject*>& other_objs);
......@@ -64,7 +64,7 @@ public:
void setup();
/// @brief update the condition of manager
void update();
virtual void update();
/// @brief clear the manager
void clear();
......@@ -72,37 +72,41 @@ public:
/// @brief return the objects managed by the manager
void getObjects(std::vector<CollisionObject*>& objs) const;
/// @brief perform collision test between one object and all the objects belonging to the manager
void collide(CollisionObject* obj, void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test between one object and all the objects
/// belonging to the manager
void collide(CollisionObject* obj, CollisionCallBackBase* callback) const;
/// @brief perform distance computation between one object and all the objects belonging to the manager
void distance(CollisionObject* obj, void* cdata, DistanceCallBack callback) const;
/// @brief perform distance computation between one object and all the objects
/// belonging to the manager
void distance(CollisionObject* obj, DistanceCallBackBase* callback) const;
/// @brief perform collision test for the objects belonging to the manager (i.e., N^2 self collision)
void collide(void* cdata, CollisionCallBack callback) const;
/// @brief perform collision test for the objects belonging to the manager
/// (i.e., N^2 self collision)
void collide(CollisionCallBackBase* callback) const;
/// @brief perform distance test for the objects belonging to the manager (i.e., N^2 self distance)
void distance(void* cdata, DistanceCallBack callback) const;
/// @brief perform distance test for the objects belonging to the manager
/// (i.e., N^2 self distance)
void distance(DistanceCallBackBase* callback) const;
/// @brief perform collision test with objects belonging to another manager
void collide(BroadPhaseCollisionManager* other_manager, void* cdata, CollisionCallBack callback) const;
void collide(BroadPhaseCollisionManager* other_manager,
CollisionCallBackBase* callback) const;
/// @brief perform distance test with objects belonging to another manager
void distance(BroadPhaseCollisionManager* other_manager, void* cdata, DistanceCallBack callback) const;
void distance(BroadPhaseCollisionManager* other_manager,
DistanceCallBackBase* callback) const;
/// @brief whether the manager is empty
bool empty() const;
/// @brief the number of objects managed by the manager
inline size_t size() const { return objs.size(); }
protected:
/// @brief the number of objects managed by the manager
size_t size() const;
protected:
/// @brief objects belonging to the manager are stored in a list structure
std::list<CollisionObject*> objs;
};
}
} // namespace coal
#endif
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2022, INRIA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** @author Justin Carpentier (justin.carpentier@inria.fr) */
#ifndef COAL_BROADPHASE_BROAD_PHASE_CALLBACKS_H
#define COAL_BROADPHASE_BROAD_PHASE_CALLBACKS_H
#include "coal/fwd.hh"
#include "coal/data_types.h"
namespace coal {
/// @brief Base callback class for collision queries.
/// This class can be supersed by child classes to provide desired behaviors
/// according to the application (e.g, only listing the potential
/// CollisionObjects in collision).
struct COAL_DLLAPI CollisionCallBackBase {
/// @brief Initialization of the callback before running the collision
/// broadphase manager.
virtual void init() {};
/// @brief Collision evaluation between two objects in collision.
/// This callback will cause the broadphase evaluation to stop if it
/// returns true.
///
/// @param[in] o1 Collision object #1.
/// @param[in] o2 Collision object #2.
virtual bool collide(CollisionObject* o1, CollisionObject* o2) = 0;
/// @brief Functor call associated to the collide operation.
virtual bool operator()(CollisionObject* o1, CollisionObject* o2) {
return collide(o1, o2);
}
};
/// @brief Base callback class for distance queries.
/// This class can be supersed by child classes to provide desired behaviors
/// according to the application (e.g, only listing the potential
/// CollisionObjects in collision).
struct COAL_DLLAPI DistanceCallBackBase {
/// @brief Initialization of the callback before running the collision
/// broadphase manager.
virtual void init() {};
/// @brief Distance evaluation between two objects in collision.
/// This callback will cause the broadphase evaluation to stop if it
/// returns true.
///
/// @param[in] o1 Collision object #1.
/// @param[in] o2 Collision object #2.
/// @param[out] dist Distance between the two collision geometries.
virtual bool distance(CollisionObject* o1, CollisionObject* o2,
CoalScalar& dist) = 0;
/// @brief Functor call associated to the distance operation.
virtual bool operator()(CollisionObject* o1, CollisionObject* o2,
CoalScalar& dist) {
return distance(o1, o2, dist);
}
};
} // namespace coal
#endif // COAL_BROADPHASE_BROAD_PHASE_CALLBACKS_H
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Open Source Robotics Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** @author Jia Pan */
#ifndef COAL_BROADPHASE_BROADPHASECOLLISIONMANAGER_H
#define COAL_BROADPHASE_BROADPHASECOLLISIONMANAGER_H
#include <set>
#include <vector>
#include <boost/function.hpp>
#include "coal/collision_object.h"
#include "coal/broadphase/broadphase_callbacks.h"
namespace coal {
/// @brief Base class for broad phase collision. It helps to accelerate the
/// collision/distance between N objects. Also support self collision, self
/// distance and collision/distance with another M objects.
class COAL_DLLAPI BroadPhaseCollisionManager {
public:
BroadPhaseCollisionManager();
virtual ~BroadPhaseCollisionManager();
/// @brief add objects to the manager
virtual void registerObjects(const std::vector<CollisionObject*>& other_objs);
/// @brief add one object to the manager
virtual void registerObject(CollisionObject* obj) = 0;
/// @brief remove one object from the manager
virtual void unregisterObject(CollisionObject* obj) = 0;
/// @brief initialize the manager, related with the specific type of manager
virtual void setup() = 0;
/// @brief update the condition of manager
virtual void update() = 0;
/// @brief update the manager by explicitly given the object updated
virtual void update(CollisionObject* updated_obj);
/// @brief update the manager by explicitly given the set of objects update
virtual void update(const std::vector<CollisionObject*>& updated_objs);
/// @brief clear the manager
virtual void clear() = 0;
/// @brief return the objects managed by the manager
virtual void getObjects(std::vector<CollisionObject*>& objs) const = 0;
/// @brief return the objects managed by the manager
virtual std::vector<CollisionObject*> getObjects() const {
std::vector<CollisionObject*> res(size());
getObjects(res);
return res;
};
/// @brief perform collision test between one object and all the objects
/// belonging to the manager
virtual void collide(CollisionObject* obj,
CollisionCallBackBase* callback) const = 0;
/// @brief perform distance computation between one object and all the objects
/// belonging to the manager
virtual void distance(CollisionObject* obj,
DistanceCallBackBase* callback) const = 0;
/// @brief perform collision test for the objects belonging to the manager
/// (i.e., N^2 self collision)
virtual void collide(CollisionCallBackBase* callback) const = 0;
/// @brief perform distance test for the objects belonging to the manager
/// (i.e., N^2 self distance)
virtual void distance(DistanceCallBackBase* callback) const = 0;
/// @brief perform collision test with objects belonging to another manager
virtual void collide(BroadPhaseCollisionManager* other_manager,
CollisionCallBackBase* callback) const = 0;
/// @brief perform distance test with objects belonging to another manager
virtual void distance(BroadPhaseCollisionManager* other_manager,
DistanceCallBackBase* callback) const = 0;
/// @brief whether the manager is empty
virtual bool empty() const = 0;
/// @brief the number of objects managed by the manager
virtual size_t size() const = 0;
protected:
/// @brief tools help to avoid repeating collision or distance callback for
/// the pairs of objects tested before. It can be useful for some of the
/// broadphase algorithms.
mutable std::set<std::pair<CollisionObject*, CollisionObject*> > tested_set;
mutable bool enable_tested_set_;
bool inTestedSet(CollisionObject* a, CollisionObject* b) const;
void insertTestedSet(CollisionObject* a, CollisionObject* b) const;
};
} // namespace coal
#endif
......@@ -2,7 +2,7 @@
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2015, Open Source Robotics Foundation
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -33,59 +33,52 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
/** \author Dalibor Matura, Jia Pan */
/** @author Jia Pan */
#ifndef FCL_CCD_INTERPOLATION_INTERPOLATION_H
#define FCL_CCD_INTERPOLATION_INTERPOLATION_H
#ifndef COAL_BROADPHASE_BROADPHASECONTINUOUSCOLLISIONMANAGER_INL_H
#define COAL_BROADPHASE_BROADPHASECONTINUOUSCOLLISIONMANAGER_INL_H
#include "fcl/data_types.h"
#include "coal/broadphase/broadphase_continuous_collision_manager.h"
#include <algorithm>
namespace fcl
{
namespace coal {
enum InterpolationType
{
LINEAR,
STANDARD
};
class Interpolation
{
public:
Interpolation();
virtual ~Interpolation() {}
Interpolation(FCL_REAL start_value, FCL_REAL end_value);
void setStartValue(FCL_REAL start_value);
void setEndValue(FCL_REAL end_value);
virtual FCL_REAL getValue(FCL_REAL time) const = 0;
/// @brief return the smallest value in time interval [0, 1]
virtual FCL_REAL getValueLowerBound() const = 0;
//==============================================================================
BroadPhaseContinuousCollisionManager::BroadPhaseContinuousCollisionManager() {
// Do nothing
}
/// @brief return the biggest value in time interval [0, 1]
virtual FCL_REAL getValueUpperBound() const = 0;
//==============================================================================
virtual InterpolationType getType() const = 0;
BroadPhaseContinuousCollisionManager::~BroadPhaseContinuousCollisionManager() {
// Do nothing
}
bool operator == (const Interpolation& interpolation) const;
bool operator != (const Interpolation& interpolation) const;
//==============================================================================
virtual FCL_REAL getMovementLengthBound(FCL_REAL time) const = 0;
void BroadPhaseContinuousCollisionManager::registerObjects(
const std::vector<ContinuousCollisionObject*>& other_objs) {
for (size_t i = 0; i < other_objs.size(); ++i) registerObject(other_objs[i]);
}
virtual FCL_REAL getVelocityBound(FCL_REAL time) const = 0;
//==============================================================================
protected:
FCL_REAL value_0_; // value at time = 0.0
FCL_REAL value_1_; // value at time = 1.0
void BroadPhaseContinuousCollisionManager::update(
ContinuousCollisionObject* updated_obj) {
COAL_UNUSED_VARIABLE(updated_obj);
};
update();
}
//==============================================================================
void BroadPhaseContinuousCollisionManager::update(
const std::vector<ContinuousCollisionObject*>& updated_objs) {
COAL_UNUSED_VARIABLE(updated_objs);
update();
}
} // namespace coal
#endif
/*
* Software License Agreement (BSD License)
*
* Copyright (c) 2011-2014, Willow Garage, Inc.
* Copyright (c) 2014-2016, Open Source Robotics Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Open Source Robotics Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** @author Jia Pan */
#ifndef COAL_BROADPHASE_BROADPHASECONTINUOUSCOLLISIONMANAGER_H
#define COAL_BROADPHASE_BROADPHASECONTINUOUSCOLLISIONMANAGER_H
#include "coal/broadphase/broadphase_collision_manager.h"
#include "coal/collision_object.h"
#include "coal/narrowphase/continuous_collision_object.h"
namespace coal {
/// @brief Callback for continuous collision between two objects. Return value
/// is whether can stop now.
template <typename S>
using ContinuousCollisionCallBack = bool (*)(ContinuousCollisionObject* o1,
ContinuousCollisionObject* o2,
void* cdata);
/// @brief Callback for continuous distance between two objects, Return value is
/// whether can stop now, also return the minimum distance till now.
template <typename S>
using ContinuousDistanceCallBack = bool (*)(ContinuousCollisionObject* o1,
ContinuousCollisionObject* o2,
S& dist);
/// @brief Base class for broad phase continuous collision. It helps to
/// accelerate the continuous collision/distance between N objects. Also support
/// self collision, self distance and collision/distance with another M objects.
template <typename S>
class COAL_DLLAPI BroadPhaseContinuousCollisionManager {
public:
BroadPhaseContinuousCollisionManager();
virtual ~BroadPhaseContinuousCollisionManager();
/// @brief add objects to the manager
virtual void registerObjects(
const std::vector<ContinuousCollisionObject*>& other_objs);
/// @brief add one object to the manager
virtual void registerObject(ContinuousCollisionObject* obj) = 0;
/// @brief remove one object from the manager
virtual void unregisterObject(ContinuousCollisionObject* obj) = 0;
/// @brief initialize the manager, related with the specific type of manager
virtual void setup() = 0;
/// @brief update the condition of manager
virtual void update() = 0;
/// @brief update the manager by explicitly given the object updated
virtual void update(ContinuousCollisionObject* updated_obj);
/// @brief update the manager by explicitly given the set of objects update
virtual void update(
const std::vector<ContinuousCollisionObject*>& updated_objs);
/// @brief clear the manager
virtual void clear() = 0;
/// @brief return the objects managed by the manager
virtual void getObjects(
std::vector<ContinuousCollisionObject*>& objs) const = 0;
/// @brief perform collision test between one object and all the objects
/// belonging to the manager
virtual void collide(ContinuousCollisionObject* obj,
CollisionCallBackBase* callback) const = 0;
/// @brief perform distance computation between one object and all the objects
/// belonging to the manager
virtual void distance(ContinuousCollisionObject* obj,
DistanceCallBackBase* callback) const = 0;
/// @brief perform collision test for the objects belonging to the manager
/// (i.e., N^2 self collision)
virtual void collide(CollisionCallBackBase* callback) const = 0;
/// @brief perform distance test for the objects belonging to the manager
/// (i.e., N^2 self distance)
virtual void distance(DistanceCallBackBase* callback) const = 0;
/// @brief perform collision test with objects belonging to another manager
virtual void collide(BroadPhaseContinuousCollisionManager* other_manager,
CollisionCallBackBase* callback) const = 0;
/// @brief perform distance test with objects belonging to another manager
virtual void distance(BroadPhaseContinuousCollisionManager* other_manager,
DistanceCallBackBase* callback) const = 0;
/// @brief whether the manager is empty
virtual bool empty() const = 0;
/// @brief the number of objects managed by the manager
virtual size_t size() const = 0;
};
using BroadPhaseContinuousCollisionManagerf =
BroadPhaseContinuousCollisionManager<float>;
using BroadPhaseContinuousCollisionManagerd =
BroadPhaseContinuousCollisionManager<CoalScalar>;
} // namespace coal
#include "coal/broadphase/broadphase_continuous_collision_manager-inl.h"
#endif