/* * 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 */ #include #include "fcl/narrowphase/detail/traversal/collision_node.h" #include "test_fcl_utility.h" #include "eigen_matrix_compare.h" #include "fcl_resources/config.h" // TODO(SeanCurtis-TRI): A file called `test_fcl_distance.cpp` should *not* have // collision tests. using namespace fcl; bool verbose = false; template S DELTA() { return 0.001; } template void distance_Test(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, int qsize, test::DistanceRes& distance_result, bool verbose = true); template bool collide_Test_OBB(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, bool verbose); template void distance_Test_Oriented(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, int qsize, test::DistanceRes& distance_result, bool verbose = true); template bool nearlyEqual(const Vector3& a, const Vector3& b) { if(fabs(a[0] - b[0]) > DELTA()) return false; if(fabs(a[1] - b[1]) > DELTA()) return false; if(fabs(a[2] - b[2]) > DELTA()) return false; return true; } template void test_mesh_distance() { std::vector> p1, p2; std::vector t1, t2; test::loadOBJFile(TEST_RESOURCES_DIR"/env.obj", p1, t1); test::loadOBJFile(TEST_RESOURCES_DIR"/rob.obj", p2, t2); aligned_vector> transforms; // t0 S extents[] = {-3000, -3000, 0, 3000, 3000, 3000}; #ifdef NDEBUG std::size_t n = 10; #else std::size_t n = 1; #endif test::generateRandomTransforms(extents, transforms, n); double dis_time = 0; double col_time = 0; test::DistanceRes res, res_now; for(std::size_t i = 0; i < transforms.size(); ++i) { test::Timer timer_col; timer_col.start(); collide_Test_OBB(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, verbose); timer_col.stop(); col_time += timer_col.getElapsedTimeInSec(); test::Timer timer_dist; timer_dist.start(); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res, verbose); timer_dist.stop(); dis_time += timer_dist.getElapsedTimeInSec(); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodekIOS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test_Oriented, detail::MeshDistanceTraversalNodeOBBRSS>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 2, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_MEDIAN, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); distance_Test>(transforms[i], p1, t1, p2, t2, detail::SPLIT_METHOD_BV_CENTER, 20, res_now, verbose); EXPECT_TRUE(fabs(res.distance - res_now.distance) < DELTA()); EXPECT_TRUE(fabs(res.distance) < DELTA() || (res.distance > 0 && nearlyEqual(res.p1, res_now.p1) && nearlyEqual(res.p2, res_now.p2))); } std::cout << "distance timing: " << dis_time << " sec" << std::endl; std::cout << "collision timing: " << col_time << " sec" << std::endl; } GTEST_TEST(FCL_DISTANCE, mesh_distance) { // test_mesh_distance(); test_mesh_distance(); } template void NearestPointFromDegenerateSimplex() { // Tests a historical bug. In certain configurations, the distance query // would terminate with a degenerate 3-simplex; the triangle was actually a // line segment. As a result, nearest points were populated with NaN values. // See https://github.com/flexible-collision-library/fcl/issues/293 for // more discussion. // This test is only relevant if box-box distance is computed via GJK. If // a custom test is created, this may no longer be relevant. // TODO(SeanCurtis-TRI): Provide some mechanism where we can assert what the // solving algorithm is (i.e., default convex vs. custom). DistanceResult result; DistanceRequest request; request.enable_nearest_points = true; request.gjk_solver_type = GJKSolverType::GST_LIBCCD; // These values were extracted from a real-world scenario that produced NaNs. std::shared_ptr> box_geometry_1( new Box(2.750000, 6.000000, 0.050000)); std::shared_ptr> box_geometry_2( new Box(0.424000, 0.150000, 0.168600)); CollisionObject box_object_1( box_geometry_1, Eigen::Quaterniond(1, 0, 0, 0).matrix(), Eigen::Vector3d(1.625000, 0.000000, 0.500000)); CollisionObject box_object_2( box_geometry_2, Eigen::Quaterniond(0.672811, 0.340674, 0.155066, 0.638138).matrix(), Eigen::Vector3d(0.192074, -0.277870, 0.273546)); EXPECT_NO_THROW(fcl::distance(&box_object_1, &box_object_2, request, result)); // These hard-coded values have been previously computed and visually // inspected and considered to be the ground truth for this very specific // test configuration. S expected_dist{0.053516322172152138}; // The "nearest" points (N1 and N2) measured and expressed in box 1's and // box 2's frames (B1 and B2, respectively). const Vector3 expected_p_B1N1{-1.375, -0.098881502700918666, -0.025000000000000022}; const Vector3 expected_p_B2N2{0.21199965773384655, 0.074999692703297122, 0.084299993303443954}; // The nearest points in the world frame. const Vector3 expected_p_WN1 = box_object_1.getTransform() * expected_p_B1N1; const Vector3 expected_p_WN2 = box_object_2.getTransform() * expected_p_B2N2; EXPECT_TRUE(CompareMatrices(result.nearest_points[0], expected_p_WN1, DELTA(), MatrixCompareType::absolute)); EXPECT_TRUE(CompareMatrices(result.nearest_points[1], expected_p_WN2, DELTA(), MatrixCompareType::absolute)); EXPECT_NEAR(expected_dist, result.min_distance, constants::eps_34()); } GTEST_TEST(FCL_DISTANCE, NearestPointFromDegenerateSimplex) { NearestPointFromDegenerateSimplex(); } template void distance_Test_Oriented(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, int qsize, test::DistanceRes& distance_result, bool verbose) { using S = typename BV::S; BVHModel m1; BVHModel m2; m1.bv_splitter.reset(new detail::BVSplitter(split_method)); m2.bv_splitter.reset(new detail::BVSplitter(split_method)); m1.beginModel(); m1.addSubModel(vertices1, triangles1); m1.endModel(); m2.beginModel(); m2.addSubModel(vertices2, triangles2); m2.endModel(); DistanceResult local_result; TraversalNode node; if(!initialize(node, (const BVHModel&)m1, tf, (const BVHModel&)m2, Transform3::Identity(), DistanceRequest(true), local_result)) std::cout << "initialize error" << std::endl; node.enable_statistics = verbose; distance(&node, nullptr, qsize); // points are in local coordinate, to global coordinate Vector3 p1 = local_result.nearest_points[0]; Vector3 p2 = local_result.nearest_points[1]; distance_result.distance = local_result.min_distance; distance_result.p1 = p1; distance_result.p2 = p2; if(verbose) { std::cout << "distance " << local_result.min_distance << std::endl; std::cout << p1[0] << " " << p1[1] << " " << p1[2] << std::endl; std::cout << p2[0] << " " << p2[1] << " " << p2[2] << std::endl; std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; } } template void distance_Test(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, int qsize, test::DistanceRes& distance_result, bool verbose) { using S = typename BV::S; BVHModel m1; BVHModel m2; m1.bv_splitter.reset(new detail::BVSplitter(split_method)); m2.bv_splitter.reset(new detail::BVSplitter(split_method)); m1.beginModel(); m1.addSubModel(vertices1, triangles1); m1.endModel(); m2.beginModel(); m2.addSubModel(vertices2, triangles2); m2.endModel(); Transform3 pose1(tf); Transform3 pose2 = Transform3::Identity(); DistanceResult local_result; detail::MeshDistanceTraversalNode node; if(!detail::initialize(node, m1, pose1, m2, pose2, DistanceRequest(true), local_result)) std::cout << "initialize error" << std::endl; node.enable_statistics = verbose; distance(&node, nullptr, qsize); distance_result.distance = local_result.min_distance; distance_result.p1 = local_result.nearest_points[0]; distance_result.p2 = local_result.nearest_points[1]; if(verbose) { std::cout << "distance " << local_result.min_distance << std::endl; std::cout << local_result.nearest_points[0][0] << " " << local_result.nearest_points[0][1] << " " << local_result.nearest_points[0][2] << std::endl; std::cout << local_result.nearest_points[1][0] << " " << local_result.nearest_points[1][1] << " " << local_result.nearest_points[1][2] << std::endl; std::cout << node.num_bv_tests << " " << node.num_leaf_tests << std::endl; } } template bool collide_Test_OBB(const Transform3& tf, const std::vector>& vertices1, const std::vector& triangles1, const std::vector>& vertices2, const std::vector& triangles2, detail::SplitMethodType split_method, bool verbose) { BVHModel> m1; BVHModel> m2; m1.bv_splitter.reset(new detail::BVSplitter>(split_method)); m2.bv_splitter.reset(new detail::BVSplitter>(split_method)); m1.beginModel(); m1.addSubModel(vertices1, triangles1); m1.endModel(); m2.beginModel(); m2.addSubModel(vertices2, triangles2); m2.endModel(); CollisionResult local_result; detail::MeshCollisionTraversalNodeOBB node; if(!detail::initialize(node, (const BVHModel>&)m1, tf, (const BVHModel>&)m2, Transform3::Identity(), CollisionRequest(), local_result)) std::cout << "initialize error" << std::endl; node.enable_statistics = verbose; collide(&node); if(local_result.numContacts() > 0) return true; else return false; } //============================================================================== int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }