diff --git a/include/fcl/geometry/shape/utility-inl.h b/include/fcl/geometry/shape/utility-inl.h index e2a1725e1..7b0eb799c 100644 --- a/include/fcl/geometry/shape/utility-inl.h +++ b/include/fcl/geometry/shape/utility-inl.h @@ -135,814 +135,197 @@ void constructBox(const KDOP& bv, const Transform3& tf_bv, B namespace detail { //============================================================================== -//============================================================================== template struct ComputeBVImpl { - static void run(const Shape& s, const Transform3& tf, BV& bv) - { - std::vector> convex_bound_vertices = s.getBoundVertices(tf); - fit(convex_bound_vertices.data(), - static_cast(convex_bound_vertices.size()), bv); - } + static void run(const Shape& s, const Transform3& tf, BV& bv); }; -//============================================================================== template struct ComputeBVImpl, Box> { - static void run(const Box& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - S x_range = 0.5 * (fabs(R(0, 0) * s.side[0]) + fabs(R(0, 1) * s.side[1]) + fabs(R(0, 2) * s.side[2])); - S y_range = 0.5 * (fabs(R(1, 0) * s.side[0]) + fabs(R(1, 1) * s.side[1]) + fabs(R(1, 2) * s.side[2])); - S z_range = 0.5 * (fabs(R(2, 0) * s.side[0]) + fabs(R(2, 1) * s.side[1]) + fabs(R(2, 2) * s.side[2])); - - Vector3 v_delta(x_range, y_range, z_range); - bv.max_ = T + v_delta; - bv.min_ = T - v_delta; - } + static void run(const Box& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Box> { - static void run(const Box& s, const Transform3& tf, OBB& bv) - { - bv.axis = tf.linear(); - bv.To = tf.translation(); - bv.extent = s.side * (S)0.5; - } + static void run(const Box& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Capsule> { - static void run(const Capsule& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - S x_range = 0.5 * fabs(R(0, 2) * s.lz) + s.radius; - S y_range = 0.5 * fabs(R(1, 2) * s.lz) + s.radius; - S z_range = 0.5 * fabs(R(2, 2) * s.lz) + s.radius; - - Vector3 v_delta(x_range, y_range, z_range); - bv.max_ = T + v_delta; - bv.min_ = T - v_delta; - } + static void run(const Capsule& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Capsule> { - static void run(const Capsule& s, const Transform3& tf, OBB& bv) - { - bv.axis = tf.linear(); - bv.To = tf.translation(); - bv.extent << s.radius, s.radius, s.lz / 2 + s.radius; - } + static void run(const Capsule& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Cone> { - static void run(const Cone& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - S x_range = fabs(R(0, 0) * s.radius) + fabs(R(0, 1) * s.radius) + 0.5 * fabs(R(0, 2) * s.lz); - S y_range = fabs(R(1, 0) * s.radius) + fabs(R(1, 1) * s.radius) + 0.5 * fabs(R(1, 2) * s.lz); - S z_range = fabs(R(2, 0) * s.radius) + fabs(R(2, 1) * s.radius) + 0.5 * fabs(R(2, 2) * s.lz); - - Vector3 v_delta(x_range, y_range, z_range); - bv.max_ = T + v_delta; - bv.min_ = T - v_delta; - } + static void run(const Cone& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Cone> { - static void run(const Cone& s, const Transform3& tf, OBB& bv) - { - bv.axis = tf.linear(); - bv.To = tf.translation(); - bv.extent << s.radius, s.radius, s.lz / 2; - } + static void run(const Cone& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Convex> { - static void run(const Convex& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - AABB bv_; - for (const auto& vertex : s.getVertices()) - { - Vector3 new_p = R * vertex + T; - bv_ += new_p; - } - - bv = bv_; - } + static void run(const Convex& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Convex> { - static void run(const Convex& s, const Transform3& tf, OBB& bv) - { - fit(s.getVertices().data(), static_cast(s.getVertices().size()), bv); - - bv.axis = tf.linear(); - bv.To = tf * bv.To; - } + static void run(const Convex& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Cylinder> { - static void run(const Cylinder& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - S x_range = fabs(R(0, 0) * s.radius) + fabs(R(0, 1) * s.radius) + 0.5 * fabs(R(0, 2) * s.lz); - S y_range = fabs(R(1, 0) * s.radius) + fabs(R(1, 1) * s.radius) + 0.5 * fabs(R(1, 2) * s.lz); - S z_range = fabs(R(2, 0) * s.radius) + fabs(R(2, 1) * s.radius) + 0.5 * fabs(R(2, 2) * s.lz); - - Vector3 v_delta(x_range, y_range, z_range); - bv.max_ = T + v_delta; - bv.min_ = T - v_delta; - } + static void run(const Cylinder& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Cylinder> { - static void run(const Cylinder& s, const Transform3& tf, OBB& bv) - { - bv.axis = tf.linear(); - bv.To = tf.translation(); - bv.extent << s.radius, s.radius, s.lz / 2; - } + static void run(const Cylinder& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Ellipsoid> { - static void run(const Ellipsoid& s, const Transform3& tf, AABB& bv) - { - const Matrix3& R = tf.linear(); - const Vector3& T = tf.translation(); - - S x_range = (fabs(R(0, 0) * s.radii[0]) + fabs(R(0, 1) * s.radii[1]) + fabs(R(0, 2) * s.radii[2])); - S y_range = (fabs(R(1, 0) * s.radii[0]) + fabs(R(1, 1) * s.radii[1]) + fabs(R(1, 2) * s.radii[2])); - S z_range = (fabs(R(2, 0) * s.radii[0]) + fabs(R(2, 1) * s.radii[1]) + fabs(R(2, 2) * s.radii[2])); - - Vector3 v_delta(x_range, y_range, z_range); - bv.max_ = T + v_delta; - bv.min_ = T - v_delta; - } + static void run(const Ellipsoid& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Ellipsoid> { - static void run(const Ellipsoid& s, const Transform3& tf, OBB& bv) - { - bv.axis = tf.linear(); - bv.To = tf.translation(); - bv.extent = s.radii; - } + static void run(const Ellipsoid& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, AABB& bv) - { - Halfspace new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - AABB bv_; - bv_.min_ = Vector3::Constant(-std::numeric_limits::max()); - bv_.max_ = Vector3::Constant(std::numeric_limits::max()); - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - // normal aligned with x axis - if(n[0] < 0) bv_.min_[0] = -d; - else if(n[0] > 0) bv_.max_[0] = d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - // normal aligned with y axis - if(n[1] < 0) bv_.min_[1] = -d; - else if(n[1] > 0) bv_.max_[1] = d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - // normal aligned with z axis - if(n[2] < 0) bv_.min_[2] = -d; - else if(n[2] > 0) bv_.max_[2] = d; - } - - bv = bv_; - } + static void run(const Halfspace& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, OBB& bv) - { - FCL_UNUSED(s); - FCL_UNUSED(tf); - - /// Half space can only have very rough OBB - bv.axis.setIdentity(); - bv.To.setZero(); - bv.extent.setConstant(std::numeric_limits::max()); - } + static void run(const Halfspace& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, RSS& bv) - { - FCL_UNUSED(s); - FCL_UNUSED(tf); - - /// Half space can only have very rough RSS - bv.axis.setIdentity(); - bv.To.setZero(); - bv.l[0] = bv.l[1] = bv.r = std::numeric_limits::max(); - } + static void run(const Halfspace& s, const Transform3& tf, RSS& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, OBBRSS& bv) - { - computeBV(s, tf, bv.obb); - computeBV(s, tf, bv.rss); - } + static void run(const Halfspace& s, const Transform3& tf, OBBRSS& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, kIOS& bv) - { - bv.num_spheres = 1; - computeBV(s, tf, bv.obb); - bv.spheres[0].o.setZero(); - bv.spheres[0].r = std::numeric_limits::max(); - } + static void run(const Halfspace& s, const Transform3& tf, kIOS& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, KDOP& bv) - { - Halfspace new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 8; - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D) = d; - else bv.dist(0) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 1) = d; - else bv.dist(1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(D + 2) = d; - else bv.dist(2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; - else bv.dist(3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; - else bv.dist(4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; - else bv.dist(5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; - else bv.dist(6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; - else bv.dist(7) = n[0] * d * 2; - } - } + static void run(const Halfspace& s, const Transform3& tf, KDOP& bv); }; -//============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, KDOP& bv) - { - Halfspace new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 9; - - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D) = d; - else bv.dist(0) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 1) = d; - else bv.dist(1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(D + 2) = d; - else bv.dist(2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; - else bv.dist(3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; - else bv.dist(4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; - else bv.dist(5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; - else bv.dist(6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; - else bv.dist(7) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 8) = n[1] * d * 2; - else bv.dist(8) = n[1] * d * 2; - } - } + static void run(const Halfspace& s, const Transform3& tf, KDOP& bv); }; //============================================================================== template struct ComputeBVImpl, Halfspace> { - static void run(const Halfspace& s, const Transform3& tf, KDOP& bv) - { - Halfspace new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 12; - - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D) = d; - else bv.dist(0) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 1) = d; - else bv.dist(1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(D + 2) = d; - else bv.dist(2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; - else bv.dist(3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; - else bv.dist(4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; - else bv.dist(5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; - else bv.dist(6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; - else bv.dist(7) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 8) = n[1] * d * 2; - else bv.dist(8) = n[1] * d * 2; - } - else if(n[0] + n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 9) = n[0] * d * 3; - else bv.dist(9) = n[0] * d * 3; - } - else if(n[0] + n[1] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(D + 10) = n[0] * d * 3; - else bv.dist(10) = n[0] * d * 3; - } - else if(n[0] + n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(D + 11) = n[1] * d * 3; - else bv.dist(11) = n[1] * d * 3; - } - } + static void run(const Halfspace& s, const Transform3& tf, KDOP& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, AABB& bv) - { - Plane new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - AABB bv_; - bv_.min_ = Vector3::Constant(-std::numeric_limits::max()); - bv_.max_ = Vector3::Constant(std::numeric_limits::max()); - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - // normal aligned with x axis - if(n[0] < 0) { bv_.min_[0] = bv_.max_[0] = -d; } - else if(n[0] > 0) { bv_.min_[0] = bv_.max_[0] = d; } - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - // normal aligned with y axis - if(n[1] < 0) { bv_.min_[1] = bv_.max_[1] = -d; } - else if(n[1] > 0) { bv_.min_[1] = bv_.max_[1] = d; } - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - // normal aligned with z axis - if(n[2] < 0) { bv_.min_[2] = bv_.max_[2] = -d; } - else if(n[2] > 0) { bv_.min_[2] = bv_.max_[2] = d; } - } - - bv = bv_; - } + static void run(const Plane& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, OBB& bv) - { - const Vector3 n = tf.linear() * s.n; - bv.axis = generateCoordinateSystem(n); - - bv.extent << 0, std::numeric_limits::max(), std::numeric_limits::max(); - - Vector3 p = s.n * s.d; - bv.To = tf * p; /// n'd' = R * n * (d + (R * n) * T) = R * (n * d) + T - } + static void run(const Plane& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, RSS& bv) - { - const Vector3 n = tf.linear() * s.n; - bv.axis = generateCoordinateSystem(n); - - bv.l[0] = std::numeric_limits::max(); - bv.l[1] = std::numeric_limits::max(); - - bv.r = 0; - - Vector3 p = s.n * s.d; - bv.To = tf * p; - } + static void run(const Plane& s, const Transform3& tf, RSS& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, OBBRSS& bv) - { - computeBV(s, tf, bv.obb); - computeBV(s, tf, bv.rss); - } + static void run(const Plane& s, const Transform3& tf, OBBRSS& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, kIOS& bv) - { - bv.num_spheres = 1; - computeBV(s, tf, bv.obb); - bv.spheres[0].o.setZero(); - bv.spheres[0].r = std::numeric_limits::max(); - } + static void run(const Plane& s, const Transform3& tf, kIOS& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, KDOP& bv) - { - Plane new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 8; - - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; - else bv.dist(0) = bv.dist(D) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; - else bv.dist(1) = bv.dist(D + 1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; - else bv.dist(2) = bv.dist(D + 2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - bv.dist(6) = bv.dist(D + 5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; - } - } + static void run(const Plane& s, const Transform3& tf, KDOP& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, KDOP& bv) - { - Plane new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 9; - - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; - else bv.dist(0) = bv.dist(D) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; - else bv.dist(1) = bv.dist(D + 1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; - else bv.dist(2) = bv.dist(D + 2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - bv.dist(5) = bv.dist(D + 5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - bv.dist(8) = bv.dist(D + 8) = n[1] * d * 2; - } - } + static void run(const Plane& s, const Transform3& tf, KDOP& bv); }; -//============================================================================== template struct ComputeBVImpl, Plane> { - static void run(const Plane& s, const Transform3& tf, KDOP& bv) - { - Plane new_s = transform(s, tf); - const Vector3& n = new_s.n; - const S& d = new_s.d; - - const std::size_t D = 12; - - for(std::size_t i = 0; i < D; ++i) - bv.dist(i) = -std::numeric_limits::max(); - for(std::size_t i = D; i < 2 * D; ++i) - bv.dist(i) = std::numeric_limits::max(); - - if(n[1] == (S)0.0 && n[2] == (S)0.0) - { - if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; - else bv.dist(0) = bv.dist(D) = -d; - } - else if(n[0] == (S)0.0 && n[2] == (S)0.0) - { - if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; - else bv.dist(1) = bv.dist(D + 1) = -d; - } - else if(n[0] == (S)0.0 && n[1] == (S)0.0) - { - if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; - else bv.dist(2) = bv.dist(D + 2) = -d; - } - else if(n[2] == (S)0.0 && n[0] == n[1]) - { - bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] == n[2]) - { - bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] == n[2]) - { - bv.dist(5) = bv.dist(D + 5) = n[1] * d * 2; - } - else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; - } - else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; - } - else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - bv.dist(8) = bv.dist(D + 8) = n[1] * d * 2; - } - else if(n[0] + n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) - { - bv.dist(9) = bv.dist(D + 9) = n[0] * d * 3; - } - else if(n[0] + n[1] == (S)0.0 && n[1] + n[2] == (S)0.0) - { - bv.dist(10) = bv.dist(D + 10) = n[0] * d * 3; - } - else if(n[0] + n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) - { - bv.dist(11) = bv.dist(D + 11) = n[1] * d * 3; - } - } + static void run(const Plane& s, const Transform3& tf, KDOP& bv); }; -//============================================================================== template struct ComputeBVImpl, Sphere> { - static void run(const Sphere& s, const Transform3& tf, AABB& bv) - { - const Vector3 v_delta = Vector3::Constant(s.radius); - bv.max_ = tf.translation() + v_delta; - bv.min_ = tf.translation() - v_delta; - } + static void run(const Sphere& s, const Transform3& tf, AABB& bv); }; -//============================================================================== template struct ComputeBVImpl, Sphere> { - static void run(const Sphere& s, const Transform3& tf, OBB& bv) - { - bv.To = tf.translation(); - bv.axis.setIdentity(); - bv.extent.setConstant(s.radius); - } + static void run(const Sphere& s, const Transform3& tf, OBB& bv); }; -//============================================================================== template struct ComputeBVImpl, TriangleP> { - static void run(const TriangleP& s, const Transform3& tf, AABB& bv) - { - bv = AABB(tf * s.a, tf * s.b, tf * s.c); - } + static void run(const TriangleP& s, const Transform3& tf, AABB& bv); }; //============================================================================== @@ -1061,6 +444,720 @@ struct FCL_EXTERN_TEMPLATE_API ComputeBVImpl, Sphere extern template struct FCL_EXTERN_TEMPLATE_API ComputeBVImpl, TriangleP>; +//============================================================================== +template +void ComputeBVImpl::run(const Shape& s, const Transform3& tf, BV& bv) +{ + std::vector> convex_bound_vertices = s.getBoundVertices(tf); + fit(convex_bound_vertices.data(), + static_cast(convex_bound_vertices.size()), bv); +} + +//============================================================================== +template +void ComputeBVImpl, Box>::run(const Box& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + S x_range = 0.5 * (fabs(R(0, 0) * s.side[0]) + fabs(R(0, 1) * s.side[1]) + fabs(R(0, 2) * s.side[2])); + S y_range = 0.5 * (fabs(R(1, 0) * s.side[0]) + fabs(R(1, 1) * s.side[1]) + fabs(R(1, 2) * s.side[2])); + S z_range = 0.5 * (fabs(R(2, 0) * s.side[0]) + fabs(R(2, 1) * s.side[1]) + fabs(R(2, 2) * s.side[2])); + + Vector3 v_delta(x_range, y_range, z_range); + bv.max_ = T + v_delta; + bv.min_ = T - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Box>::run(const Box& s, const Transform3& tf, OBB& bv) +{ + bv.axis = tf.linear(); + bv.To = tf.translation(); + bv.extent = s.side * (S)0.5; +} + +//============================================================================== +template +void ComputeBVImpl, Capsule>::run(const Capsule& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + S x_range = 0.5 * fabs(R(0, 2) * s.lz) + s.radius; + S y_range = 0.5 * fabs(R(1, 2) * s.lz) + s.radius; + S z_range = 0.5 * fabs(R(2, 2) * s.lz) + s.radius; + + Vector3 v_delta(x_range, y_range, z_range); + bv.max_ = T + v_delta; + bv.min_ = T - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Capsule>::run(const Capsule& s, const Transform3& tf, OBB& bv) +{ + bv.axis = tf.linear(); + bv.To = tf.translation(); + bv.extent << s.radius, s.radius, s.lz / 2 + s.radius; +} + +//============================================================================== +template +void ComputeBVImpl, Cone>::run(const Cone& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + S x_range = fabs(R(0, 0) * s.radius) + fabs(R(0, 1) * s.radius) + 0.5 * fabs(R(0, 2) * s.lz); + S y_range = fabs(R(1, 0) * s.radius) + fabs(R(1, 1) * s.radius) + 0.5 * fabs(R(1, 2) * s.lz); + S z_range = fabs(R(2, 0) * s.radius) + fabs(R(2, 1) * s.radius) + 0.5 * fabs(R(2, 2) * s.lz); + + Vector3 v_delta(x_range, y_range, z_range); + bv.max_ = T + v_delta; + bv.min_ = T - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Cone>::run(const Cone& s, const Transform3& tf, OBB& bv) +{ + bv.axis = tf.linear(); + bv.To = tf.translation(); + bv.extent << s.radius, s.radius, s.lz / 2; +} + +//============================================================================== +template +void ComputeBVImpl, Convex>::run(const Convex& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + AABB bv_; + for (const auto& vertex : s.getVertices()) + { + Vector3 new_p = R * vertex + T; + bv_ += new_p; + } + + bv = bv_; +} + +//============================================================================== +template +void ComputeBVImpl, Convex>::run(const Convex& s, const Transform3& tf, OBB& bv) +{ + fit(s.getVertices().data(), static_cast(s.getVertices().size()), bv); + + bv.axis = tf.linear(); + bv.To = tf * bv.To; +} + +//============================================================================== +template +void ComputeBVImpl, Cylinder>::run(const Cylinder& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + S x_range = fabs(R(0, 0) * s.radius) + fabs(R(0, 1) * s.radius) + 0.5 * fabs(R(0, 2) * s.lz); + S y_range = fabs(R(1, 0) * s.radius) + fabs(R(1, 1) * s.radius) + 0.5 * fabs(R(1, 2) * s.lz); + S z_range = fabs(R(2, 0) * s.radius) + fabs(R(2, 1) * s.radius) + 0.5 * fabs(R(2, 2) * s.lz); + + Vector3 v_delta(x_range, y_range, z_range); + bv.max_ = T + v_delta; + bv.min_ = T - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Cylinder>::run(const Cylinder& s, const Transform3& tf, OBB& bv) +{ + bv.axis = tf.linear(); + bv.To = tf.translation(); + bv.extent << s.radius, s.radius, s.lz / 2; +} + +//============================================================================== +template +void ComputeBVImpl, Ellipsoid>::run(const Ellipsoid& s, const Transform3& tf, AABB& bv) +{ + const Matrix3& R = tf.linear(); + const Vector3& T = tf.translation(); + + S x_range = (fabs(R(0, 0) * s.radii[0]) + fabs(R(0, 1) * s.radii[1]) + fabs(R(0, 2) * s.radii[2])); + S y_range = (fabs(R(1, 0) * s.radii[0]) + fabs(R(1, 1) * s.radii[1]) + fabs(R(1, 2) * s.radii[2])); + S z_range = (fabs(R(2, 0) * s.radii[0]) + fabs(R(2, 1) * s.radii[1]) + fabs(R(2, 2) * s.radii[2])); + + Vector3 v_delta(x_range, y_range, z_range); + bv.max_ = T + v_delta; + bv.min_ = T - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Ellipsoid>::run(const Ellipsoid& s, const Transform3& tf, OBB& bv) +{ + bv.axis = tf.linear(); + bv.To = tf.translation(); + bv.extent = s.radii; +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, AABB& bv) +{ + Halfspace new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + AABB bv_; + bv_.min_ = Vector3::Constant(-std::numeric_limits::max()); + bv_.max_ = Vector3::Constant(std::numeric_limits::max()); + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + // normal aligned with x axis + if(n[0] < 0) bv_.min_[0] = -d; + else if(n[0] > 0) bv_.max_[0] = d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + // normal aligned with y axis + if(n[1] < 0) bv_.min_[1] = -d; + else if(n[1] > 0) bv_.max_[1] = d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + // normal aligned with z axis + if(n[2] < 0) bv_.min_[2] = -d; + else if(n[2] > 0) bv_.max_[2] = d; + } + + bv = bv_; +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, OBB& bv) +{ + FCL_UNUSED(s); + FCL_UNUSED(tf); + + /// Half space can only have very rough OBB + bv.axis.setIdentity(); + bv.To.setZero(); + bv.extent.setConstant(std::numeric_limits::max()); +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, RSS& bv) +{ + FCL_UNUSED(s); + FCL_UNUSED(tf); + + /// Half space can only have very rough RSS + bv.axis.setIdentity(); + bv.To.setZero(); + bv.l[0] = bv.l[1] = bv.r = std::numeric_limits::max(); +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, OBBRSS& bv) +{ + computeBV(s, tf, bv.obb); + computeBV(s, tf, bv.rss); +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, kIOS& bv) +{ + bv.num_spheres = 1; + computeBV(s, tf, bv.obb); + bv.spheres[0].o.setZero(); + bv.spheres[0].r = std::numeric_limits::max(); +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, KDOP& bv) +{ + Halfspace new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 8; + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D) = d; + else bv.dist(0) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 1) = d; + else bv.dist(1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(D + 2) = d; + else bv.dist(2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; + else bv.dist(3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; + else bv.dist(4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; + else bv.dist(5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; + else bv.dist(6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; + else bv.dist(7) = n[0] * d * 2; + } +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, KDOP& bv) +{ + Halfspace new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 9; + + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D) = d; + else bv.dist(0) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 1) = d; + else bv.dist(1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(D + 2) = d; + else bv.dist(2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; + else bv.dist(3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; + else bv.dist(4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; + else bv.dist(5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; + else bv.dist(6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; + else bv.dist(7) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 8) = n[1] * d * 2; + else bv.dist(8) = n[1] * d * 2; + } +} + +//============================================================================== +template +void ComputeBVImpl, Halfspace>::run(const Halfspace& s, const Transform3& tf, KDOP& bv) +{ + Halfspace new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 12; + + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D) = d; + else bv.dist(0) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 1) = d; + else bv.dist(1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(D + 2) = d; + else bv.dist(2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + if(n[0] > 0) bv.dist(D + 3) = n[0] * d * 2; + else bv.dist(3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + if(n[1] > 0) bv.dist(D + 4) = n[0] * d * 2; + else bv.dist(4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + if(n[1] > 0) bv.dist(D + 5) = n[1] * d * 2; + else bv.dist(5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 6) = n[0] * d * 2; + else bv.dist(6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 7) = n[0] * d * 2; + else bv.dist(7) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 8) = n[1] * d * 2; + else bv.dist(8) = n[1] * d * 2; + } + else if(n[0] + n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 9) = n[0] * d * 3; + else bv.dist(9) = n[0] * d * 3; + } + else if(n[0] + n[1] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(D + 10) = n[0] * d * 3; + else bv.dist(10) = n[0] * d * 3; + } + else if(n[0] + n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(D + 11) = n[1] * d * 3; + else bv.dist(11) = n[1] * d * 3; + } +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, AABB& bv) +{ + Plane new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + AABB bv_; + bv_.min_ = Vector3::Constant(-std::numeric_limits::max()); + bv_.max_ = Vector3::Constant(std::numeric_limits::max()); + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + // normal aligned with x axis + if(n[0] < 0) { bv_.min_[0] = bv_.max_[0] = -d; } + else if(n[0] > 0) { bv_.min_[0] = bv_.max_[0] = d; } + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + // normal aligned with y axis + if(n[1] < 0) { bv_.min_[1] = bv_.max_[1] = -d; } + else if(n[1] > 0) { bv_.min_[1] = bv_.max_[1] = d; } + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + // normal aligned with z axis + if(n[2] < 0) { bv_.min_[2] = bv_.max_[2] = -d; } + else if(n[2] > 0) { bv_.min_[2] = bv_.max_[2] = d; } + } + + bv = bv_; +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, OBB& bv) +{ + const Vector3 n = tf.linear() * s.n; + bv.axis = generateCoordinateSystem(n); + + bv.extent << 0, std::numeric_limits::max(), std::numeric_limits::max(); + + Vector3 p = s.n * s.d; + bv.To = tf * p; /// n'd' = R * n * (d + (R * n) * T) = R * (n * d) + T +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, RSS& bv) +{ + const Vector3 n = tf.linear() * s.n; + bv.axis = generateCoordinateSystem(n); + + bv.l[0] = std::numeric_limits::max(); + bv.l[1] = std::numeric_limits::max(); + + bv.r = 0; + + Vector3 p = s.n * s.d; + bv.To = tf * p; +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, OBBRSS& bv) +{ + computeBV(s, tf, bv.obb); + computeBV(s, tf, bv.rss); +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, kIOS& bv) +{ + bv.num_spheres = 1; + computeBV(s, tf, bv.obb); + bv.spheres[0].o.setZero(); + bv.spheres[0].r = std::numeric_limits::max(); +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, KDOP& bv) +{ + Plane new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 8; + + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; + else bv.dist(0) = bv.dist(D) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; + else bv.dist(1) = bv.dist(D + 1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; + else bv.dist(2) = bv.dist(D + 2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + bv.dist(6) = bv.dist(D + 5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; + } +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, KDOP& bv) +{ + Plane new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 9; + + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; + else bv.dist(0) = bv.dist(D) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; + else bv.dist(1) = bv.dist(D + 1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; + else bv.dist(2) = bv.dist(D + 2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + bv.dist(5) = bv.dist(D + 5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + bv.dist(8) = bv.dist(D + 8) = n[1] * d * 2; + } +} + +//============================================================================== +template +void ComputeBVImpl, Plane>::run(const Plane& s, const Transform3& tf, KDOP& bv) +{ + Plane new_s = transform(s, tf); + const Vector3& n = new_s.n; + const S& d = new_s.d; + + const std::size_t D = 12; + + for(std::size_t i = 0; i < D; ++i) + bv.dist(i) = -std::numeric_limits::max(); + for(std::size_t i = D; i < 2 * D; ++i) + bv.dist(i) = std::numeric_limits::max(); + + if(n[1] == (S)0.0 && n[2] == (S)0.0) + { + if(n[0] > 0) bv.dist(0) = bv.dist(D) = d; + else bv.dist(0) = bv.dist(D) = -d; + } + else if(n[0] == (S)0.0 && n[2] == (S)0.0) + { + if(n[1] > 0) bv.dist(1) = bv.dist(D + 1) = d; + else bv.dist(1) = bv.dist(D + 1) = -d; + } + else if(n[0] == (S)0.0 && n[1] == (S)0.0) + { + if(n[2] > 0) bv.dist(2) = bv.dist(D + 2) = d; + else bv.dist(2) = bv.dist(D + 2) = -d; + } + else if(n[2] == (S)0.0 && n[0] == n[1]) + { + bv.dist(3) = bv.dist(D + 3) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] == n[2]) + { + bv.dist(4) = bv.dist(D + 4) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] == n[2]) + { + bv.dist(5) = bv.dist(D + 5) = n[1] * d * 2; + } + else if(n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + bv.dist(6) = bv.dist(D + 6) = n[0] * d * 2; + } + else if(n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + bv.dist(7) = bv.dist(D + 7) = n[0] * d * 2; + } + else if(n[0] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + bv.dist(8) = bv.dist(D + 8) = n[1] * d * 2; + } + else if(n[0] + n[2] == (S)0.0 && n[0] + n[1] == (S)0.0) + { + bv.dist(9) = bv.dist(D + 9) = n[0] * d * 3; + } + else if(n[0] + n[1] == (S)0.0 && n[1] + n[2] == (S)0.0) + { + bv.dist(10) = bv.dist(D + 10) = n[0] * d * 3; + } + else if(n[0] + n[1] == (S)0.0 && n[0] + n[2] == (S)0.0) + { + bv.dist(11) = bv.dist(D + 11) = n[1] * d * 3; + } +} + +//============================================================================== +template +void ComputeBVImpl, Sphere>::run(const Sphere& s, const Transform3& tf, AABB& bv) +{ + const Vector3 v_delta = Vector3::Constant(s.radius); + bv.max_ = tf.translation() + v_delta; + bv.min_ = tf.translation() - v_delta; +} + +//============================================================================== +template +void ComputeBVImpl, Sphere>::run(const Sphere& s, const Transform3& tf, OBB& bv) +{ + bv.To = tf.translation(); + bv.axis.setIdentity(); + bv.extent.setConstant(s.radius); +} + +//============================================================================== +template +void ComputeBVImpl, TriangleP>::run(const TriangleP& s, const Transform3& tf, AABB& bv) +{ + bv = AABB(tf * s.a, tf * s.b, tf * s.c); +} + //============================================================================== } // namespace detail //==============================================================================