From c92151a6cd7f5f555f8b50d0dec44f68ed6af25c Mon Sep 17 00:00:00 2001 From: Lucile Remigy <lucile.remigy@epitech.eu> Date: Thu, 26 Sep 2019 13:25:47 +0200 Subject: [PATCH] File BV_splitter.h and BV_fitter.h private --- include/hpp/fcl/BVH/BVH_model.h | 4 +- src/BVH/BV_fitter.cpp | 2 +- src/BVH/BV_fitter.h | 228 ++++++++++++++++++++ src/BVH/BV_splitter.cpp | 2 +- src/BVH/BV_splitter.h | 274 +++++++++++++++++++++++++ src/shape/geometric_shapes_utility.cpp | 2 +- 6 files changed, 507 insertions(+), 5 deletions(-) create mode 100644 src/BVH/BV_fitter.h create mode 100644 src/BVH/BV_splitter.h diff --git a/include/hpp/fcl/BVH/BVH_model.h b/include/hpp/fcl/BVH/BVH_model.h index 7d7f00c8..7612f9f8 100644 --- a/include/hpp/fcl/BVH/BVH_model.h +++ b/include/hpp/fcl/BVH/BVH_model.h @@ -41,8 +41,8 @@ #include <hpp/fcl/collision_object.h> #include <hpp/fcl/BVH/BVH_internal.h> #include <hpp/fcl/BV/BV_node.h> -#include <hpp/fcl/BVH/BV_splitter.h> -#include <hpp/fcl/BVH/BV_fitter.h> +#include "../../src/BVH/BV_splitter.h" +#include "../../src/BVH/BV_fitter.h" #include <vector> #include <boost/shared_ptr.hpp> #include <boost/noncopyable.hpp> diff --git a/src/BVH/BV_fitter.cpp b/src/BVH/BV_fitter.cpp index d04481fb..df9b26cb 100644 --- a/src/BVH/BV_fitter.cpp +++ b/src/BVH/BV_fitter.cpp @@ -35,7 +35,7 @@ /** \author Jia Pan */ -#include <hpp/fcl/BVH/BV_fitter.h> +#include "BV_fitter.h" #include <hpp/fcl/BVH/BVH_utility.h> #include <limits> #include "../math/tools.h" diff --git a/src/BVH/BV_fitter.h b/src/BVH/BV_fitter.h new file mode 100644 index 00000000..d8070d69 --- /dev/null +++ b/src/BVH/BV_fitter.h @@ -0,0 +1,228 @@ +/* + * 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 HPP_FCL_BV_FITTER_H +#define HPP_FCL_BV_FITTER_H + +#include <hpp/fcl/BVH/BVH_internal.h> +#include <hpp/fcl/BV/kIOS.h> +#include <hpp/fcl/BV/OBBRSS.h> +#include <hpp/fcl/BV/AABB.h> +#include <iostream> + +namespace hpp +{ +namespace fcl +{ + +/// @brief Compute a bounding volume that fits a set of n points. +template<typename BV> +void fit(Vec3f* ps, int n, BV& bv) +{ + for(int i = 0; i < n; ++i) + { + bv += ps[i]; + } +} + +template<> +void fit<OBB>(Vec3f* ps, int n, OBB& bv); + +template<> +void fit<RSS>(Vec3f* ps, int n, RSS& bv); + +template<> +void fit<kIOS>(Vec3f* ps, int n, kIOS& bv); + +template<> +void fit<OBBRSS>(Vec3f* ps, int n, OBBRSS& bv); + +template<> +void fit<AABB>(Vec3f* ps, int n, AABB& bv); + +/// @brief The class for the default algorithm fitting a bounding volume to a set of points +template<typename BV> +class BVFitterTpl +{ +public: + /// @brief default deconstructor + virtual ~BVFitterTpl() {} + + /// @brief Prepare the geometry primitive data for fitting + void set(Vec3f* vertices_, Triangle* tri_indices_, BVHModelType type_) + { + vertices = vertices_; + prev_vertices = NULL; + tri_indices = tri_indices_; + type = type_; + } + + /// @brief Prepare the geometry primitive data for fitting, for deformable mesh + void set(Vec3f* vertices_, Vec3f* prev_vertices_, Triangle* tri_indices_, BVHModelType type_) + { + vertices = vertices_; + prev_vertices = prev_vertices_; + tri_indices = tri_indices_; + type = type_; + } + + /// @brief Compute the fitting BV + virtual BV fit(unsigned int* primitive_indices, int num_primitives) = 0; + + /// @brief Clear the geometry primitive data + void clear() + { + vertices = NULL; + prev_vertices = NULL; + tri_indices = NULL; + type = BVH_MODEL_UNKNOWN; + } + +protected: + + Vec3f* vertices; + Vec3f* prev_vertices; + Triangle* tri_indices; + BVHModelType type; +}; + +/// @brief The class for the default algorithm fitting a bounding volume to a set of points +template<typename BV> +class BVFitter : public BVFitterTpl<BV> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data + BV fit(unsigned int* primitive_indices, int num_primitives) + { + BV bv; + + if(type == BVH_MODEL_TRIANGLES) /// The primitive is triangle + { + for(int i = 0; i < num_primitives; ++i) + { + Triangle t = tri_indices[primitive_indices[i]]; + bv += vertices[t[0]]; + bv += vertices[t[1]]; + bv += vertices[t[2]]; + + if(prev_vertices) /// can fitting both current and previous frame + { + bv += prev_vertices[t[0]]; + bv += prev_vertices[t[1]]; + bv += prev_vertices[t[2]]; + } + } + } + else if(type == BVH_MODEL_POINTCLOUD) /// The primitive is point + { + for(int i = 0; i < num_primitives; ++i) + { + bv += vertices[primitive_indices[i]]; + + if(prev_vertices) /// can fitting both current and previous frame + { + bv += prev_vertices[primitive_indices[i]]; + } + } + } + + return bv; + } + +protected: + using BVFitterTpl<BV>::vertices; + using BVFitterTpl<BV>::prev_vertices; + using BVFitterTpl<BV>::tri_indices; + using BVFitterTpl<BV>::type; +}; + +/// @brief Specification of BVFitter for OBB bounding volume +template<> +class BVFitter<OBB> : public BVFitterTpl<OBB> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data. + OBB fit(unsigned int* primitive_indices, int num_primitives); +}; + +/// @brief Specification of BVFitter for RSS bounding volume +template<> +class BVFitter<RSS> : public BVFitterTpl<RSS> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data. + RSS fit(unsigned int* primitive_indices, int num_primitives); +}; + +/// @brief Specification of BVFitter for kIOS bounding volume +template<> +class BVFitter<kIOS> : public BVFitterTpl<kIOS> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data. + kIOS fit(unsigned int* primitive_indices, int num_primitives); +}; + +/// @brief Specification of BVFitter for OBBRSS bounding volume +template<> +class BVFitter<OBBRSS> : public BVFitterTpl<OBBRSS> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data. + OBBRSS fit(unsigned int* primitive_indices, int num_primitives); +}; + +/// @brief Specification of BVFitter for AABB bounding volume +template<> +class BVFitter<AABB> : public BVFitterTpl<AABB> +{ +public: + /// @brief Compute a bounding volume that fits a set of primitives (points or triangles). + /// The primitive data was set by set function and primitive_indices is the primitive index relative to the data. + AABB fit(unsigned int* primitive_indices, int num_primitives); +}; + +} + +} // namespace hpp + +#endif diff --git a/src/BVH/BV_splitter.cpp b/src/BVH/BV_splitter.cpp index 1674cef4..c709ed63 100644 --- a/src/BVH/BV_splitter.cpp +++ b/src/BVH/BV_splitter.cpp @@ -35,7 +35,7 @@ /** \author Jia Pan */ -#include <hpp/fcl/BVH/BV_splitter.h> +#include "BV_splitter.h" namespace hpp { diff --git a/src/BVH/BV_splitter.h b/src/BVH/BV_splitter.h new file mode 100644 index 00000000..7be8ca74 --- /dev/null +++ b/src/BVH/BV_splitter.h @@ -0,0 +1,274 @@ +/* + * 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 HPP_FCL_BV_SPLITTER_H +#define HPP_FCL_BV_SPLITTER_H + +#include <hpp/fcl/BVH/BVH_internal.h> +#include <hpp/fcl/BV/kIOS.h> +#include <hpp/fcl/BV/OBBRSS.h> +#include <vector> +#include <iostream> + +namespace hpp +{ +namespace fcl +{ + +/// @brief Three types of split algorithms are provided in FCL as default +enum SplitMethodType {SPLIT_METHOD_MEAN, SPLIT_METHOD_MEDIAN, SPLIT_METHOD_BV_CENTER}; + + +/// @brief A class describing the split rule that splits each BV node +template<typename BV> +class BVSplitter +{ +public: + + BVSplitter(SplitMethodType method) : split_vector(0,0,0), split_method(method) + { + } + + /// @brief Default deconstructor + virtual ~BVSplitter() {} + + /// @brief Set the geometry data needed by the split rule + void set(Vec3f* vertices_, Triangle* tri_indices_, BVHModelType type_) + { + vertices = vertices_; + tri_indices = tri_indices_; + type = type_; + } + + /// @brief Compute the split rule according to a subset of geometry and the corresponding BV node + void computeRule(const BV& bv, unsigned int* primitive_indices, int num_primitives) + { + switch(split_method) + { + case SPLIT_METHOD_MEAN: + computeRule_mean(bv, primitive_indices, num_primitives); + break; + case SPLIT_METHOD_MEDIAN: + computeRule_median(bv, primitive_indices, num_primitives); + break; + case SPLIT_METHOD_BV_CENTER: + computeRule_bvcenter(bv, primitive_indices, num_primitives); + break; + default: + std::cerr << "Split method not supported" << std::endl; + } + } + + /// @brief Apply the split rule on a given point + bool apply(const Vec3f& q) const + { + return q[split_axis] > split_value; + } + + /// @brief Clear the geometry data set before + void clear() + { + vertices = NULL; + tri_indices = NULL; + type = BVH_MODEL_UNKNOWN; + } + +private: + + /// @brief The axis based on which the split decision is made. For most BV, the axis is aligned with one of the world coordinate, so only split_axis is needed. + /// For oriented node, we can use a vector to make a better split decision. + int split_axis; + Vec3f split_vector; + + /// @brief The split threshold, different primitives are splitted according whether their projection on the split_axis is larger or smaller than the threshold + FCL_REAL split_value; + + /// @brief The mesh vertices or points handled by the splitter + Vec3f* vertices; + + /// @brief The triangles handled by the splitter + Triangle* tri_indices; + + /// @brief Whether the geometry is mesh or point cloud + BVHModelType type; + + /// @brief The split algorithm used + SplitMethodType split_method; + + /// @brief Split algorithm 1: Split the node from center + void computeRule_bvcenter(const BV& bv, unsigned int*, int) + { + Vec3f center = bv.center(); + int axis = 2; + + if(bv.width() >= bv.height() && bv.width() >= bv.depth()) + axis = 0; + else if(bv.height() >= bv.width() && bv.height() >= bv.depth()) + axis = 1; + + split_axis = axis; + split_value = center[axis]; + } + + /// @brief Split algorithm 2: Split the node according to the mean of the data contained + void computeRule_mean(const BV& bv, unsigned int* primitive_indices, int num_primitives) + { + int axis = 2; + + if(bv.width() >= bv.height() && bv.width() >= bv.depth()) + axis = 0; + else if(bv.height() >= bv.width() && bv.height() >= bv.depth()) + axis = 1; + + split_axis = axis; + FCL_REAL sum = 0; + + if(type == BVH_MODEL_TRIANGLES) + { + for(int i = 0; i < num_primitives; ++i) + { + const Triangle& t = tri_indices[primitive_indices[i]]; + sum += (vertices[t[0]][split_axis] + vertices[t[1]][split_axis] + vertices[t[2]][split_axis]); + } + + sum /= 3; + } + else if(type == BVH_MODEL_POINTCLOUD) + { + for(int i = 0; i < num_primitives; ++i) + { + sum += vertices[primitive_indices[i]][split_axis]; + } + } + + split_value = sum / num_primitives; + } + + /// @brief Split algorithm 3: Split the node according to the median of the data contained + void computeRule_median(const BV& bv, unsigned int* primitive_indices, int num_primitives) + { + int axis = 2; + + if(bv.width() >= bv.height() && bv.width() >= bv.depth()) + axis = 0; + else if(bv.height() >= bv.width() && bv.height() >= bv.depth()) + axis = 1; + + split_axis = axis; + std::vector<FCL_REAL> proj(num_primitives); + + if(type == BVH_MODEL_TRIANGLES) + { + for(int i = 0; i < num_primitives; ++i) + { + const Triangle& t = tri_indices[primitive_indices[i]]; + proj[i] = (vertices[t[0]][split_axis] + vertices[t[1]][split_axis] + vertices[t[2]][split_axis]) / 3; + } + } + else if(type == BVH_MODEL_POINTCLOUD) + { + for(int i = 0; i < num_primitives; ++i) + proj[i] = vertices[primitive_indices[i]][split_axis]; + } + + std::sort(proj.begin(), proj.end()); + + if(num_primitives % 2 == 1) + { + split_value = proj[(num_primitives - 1) / 2]; + } + else + { + split_value = (proj[num_primitives / 2] + proj[num_primitives / 2 - 1]) / 2; + } + } +}; + + +template<> +bool BVSplitter<OBB>::apply(const Vec3f& q) const; + +template<> +bool BVSplitter<RSS>::apply(const Vec3f& q) const; + +template<> +bool BVSplitter<kIOS>::apply(const Vec3f& q) const; + +template<> +bool BVSplitter<OBBRSS>::apply(const Vec3f& q) const; + +template<> +void BVSplitter<OBB>::computeRule_bvcenter(const OBB& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<OBB>::computeRule_mean(const OBB& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<OBB>::computeRule_median(const OBB& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<RSS>::computeRule_bvcenter(const RSS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<RSS>::computeRule_mean(const RSS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<RSS>::computeRule_median(const RSS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<kIOS>::computeRule_bvcenter(const kIOS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<kIOS>::computeRule_mean(const kIOS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<kIOS>::computeRule_median(const kIOS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<OBBRSS>::computeRule_bvcenter(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<OBBRSS>::computeRule_mean(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives); + +template<> +void BVSplitter<OBBRSS>::computeRule_median(const OBBRSS& bv, unsigned int* primitive_indices, int num_primitives); + +} + +} // namespace hpp + +#endif diff --git a/src/shape/geometric_shapes_utility.cpp b/src/shape/geometric_shapes_utility.cpp index 70f26152..0a82aeb2 100644 --- a/src/shape/geometric_shapes_utility.cpp +++ b/src/shape/geometric_shapes_utility.cpp @@ -37,7 +37,7 @@ #include <hpp/fcl/shape/geometric_shapes_utility.h> -#include <hpp/fcl/BVH/BV_fitter.h> +#include "../BVH/BV_fitter.h" #include "../math/tools.h" namespace hpp -- GitLab