$search
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2011, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 00038 #include "collision_checking/distance_primitive.h" 00039 #include "collision_checking/intersect.h" 00040 #include <limits> 00041 #include <queue> 00042 00043 namespace collision_checking 00044 { 00045 00046 00048 struct BVT 00049 { 00051 BVH_REAL d; 00052 00054 int b1, b2; 00055 }; 00056 00058 struct BVT_Comparer 00059 { 00060 bool operator() (const BVT& lhs, const BVT& rhs) const 00061 { 00062 return lhs.d > rhs.d; 00063 } 00064 }; 00065 00066 typedef std::priority_queue<BVT, std::vector<BVT>, BVT_Comparer> BVTQ; 00067 00068 BVH_DistanceResult::BVH_DistanceResult() 00069 { 00070 num_bv_tests = 0; 00071 num_tri_tests = 0; 00072 00073 query_time_seconds = 0; 00074 00075 /* default queue size is 2 */ 00076 qsize = 2; 00077 00078 /* default last_tris are the first triangle on each model */ 00079 last_tri_id1 = 0; 00080 last_tri_id2 = 0; 00081 00083 rel_err = (BVH_REAL)0.01; 00084 abs_err = (BVH_REAL)0.01; 00085 00086 distance = std::numeric_limits<BVH_REAL>::max(); 00087 } 00088 00089 00090 BVH_DistanceResult::~BVH_DistanceResult() 00091 { 00092 00093 } 00094 00095 00097 void distanceQueueRecurse(BVNode<RSS>* tree1, BVNode<RSS>* tree2, 00098 const Vec3f R[3], const Vec3f& T, 00099 int b1, int b2, 00100 Vec3f* vertices1, Vec3f* vertices2, 00101 Triangle* tri_indices1, Triangle* tri_indices2, 00102 BVH_DistanceResult* res, BVHFrontList* front_list) 00103 { 00104 BVTQ bvtq; 00105 00106 BVT min_test; 00107 min_test.b1 = b1; 00108 min_test.b2 = b2; 00109 00110 while(1) 00111 { 00112 BVNode<RSS>* node1 = tree1 + min_test.b1; 00113 BVNode<RSS>* node2 = tree2 + min_test.b2; 00114 00115 bool l1 = node1->isLeaf(); 00116 bool l2 = node2->isLeaf(); 00117 00118 if(l1 && l2) 00119 { 00120 if(front_list) front_list->push_back(BVHFrontNode(b1, b2)); 00121 00122 res->num_tri_tests++; 00123 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1]; 00124 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1]; 00125 00126 const Vec3f& p1 = vertices1[tri_id1[0]]; 00127 const Vec3f& p2 = vertices1[tri_id1[1]]; 00128 const Vec3f& p3 = vertices1[tri_id1[2]]; 00129 00130 const Vec3f& q1 = vertices2[tri_id2[0]]; 00131 const Vec3f& q2 = vertices2[tri_id2[1]]; 00132 const Vec3f& q3 = vertices2[tri_id2[2]]; 00133 00134 // nearest point pair 00135 Vec3f P1, P2; 00136 00137 BVH_REAL d = TriangleDistance::triDistance(p1, p2, p3, q1, q2, q3, 00138 R, T, 00139 P1, P2); 00140 00141 if(d < res->distance) 00142 { 00143 res->distance = d; 00144 00145 res->p1 = P1; 00146 res->p2 = P2; 00147 00148 res->last_tri_id1 = -node1->first_child - 1; 00149 res->last_tri_id2 = -node2->first_child - 1; 00150 } 00151 } 00152 else if((int)bvtq.size() == res->qsize - 1) 00153 { 00154 // queue should not get two more tests, recur 00155 00156 distanceQueueRecurse(tree1, tree2, R, T, min_test.b1, min_test.b2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list); 00157 } 00158 else 00159 { 00160 // queue capacity still small than qsize 00161 00162 00163 BVH_REAL sz1 = node1->bv.size(); 00164 BVH_REAL sz2 = node2->bv.size(); 00165 00166 res->num_bv_tests += 2; 00167 00168 BVT bvt1, bvt2; 00169 00170 if(l2 || (!l1 && (sz1 > sz2))) 00171 { 00172 int c1 = node1->first_child; 00173 int c2 = c1 + 1; 00174 00175 bvt1.b1 = c1; 00176 bvt1.b2 = min_test.b2; 00177 bvt1.d = distance(R, T, (tree1 + bvt1.b1)->bv, (tree2 + bvt1.b2)->bv); 00178 00179 bvt2.b1 = c2; 00180 bvt2.b2 = min_test.b2; 00181 bvt2.d = distance(R, T, (tree1 + bvt2.b1)->bv, (tree2 + bvt2.b2)->bv); 00182 } 00183 else 00184 { 00185 int c1 = node2->first_child; 00186 int c2 = c1 + 1; 00187 00188 bvt1.b1 = min_test.b1; 00189 bvt1.b2 = c1; 00190 bvt1.d = distance(R, T, (tree1 + bvt1.b1)->bv, (tree2 + bvt1.b2)->bv); 00191 00192 bvt2.b1 = min_test.b1; 00193 bvt2.b2 = c2; 00194 bvt2.d = distance(R, T, (tree1 + bvt2.b1)->bv, (tree2 + bvt2.b2)->bv); 00195 } 00196 00197 bvtq.push(bvt1); 00198 bvtq.push(bvt2); 00199 } 00200 00201 if(bvtq.empty()) 00202 { 00203 break; 00204 } 00205 else 00206 { 00207 min_test = bvtq.top(); 00208 bvtq.pop(); 00209 00210 if((min_test.d + res->abs_err >= res->distance) && 00211 ((min_test.d * (1 + res->rel_err)) >= res->distance)) 00212 { 00213 if(front_list) front_list->push_back(BVHFrontNode(min_test.b1, min_test.b2)); 00214 00215 break; 00216 } 00217 } 00218 } 00219 } 00220 00221 00222 void distanceRecurse(BVNode<RSS>* tree1, BVNode<RSS>* tree2, 00223 const Vec3f R[3], const Vec3f& T, 00224 int b1, int b2, 00225 Vec3f* vertices1, Vec3f* vertices2, 00226 Triangle* tri_indices1, Triangle* tri_indices2, 00227 BVH_DistanceResult* res, BVHFrontList* front_list) 00228 { 00229 BVNode<RSS>* node1 = tree1 + b1; 00230 BVNode<RSS>* node2 = tree2 + b2; 00231 00232 bool l1 = node1->isLeaf(); 00233 bool l2 = node2->isLeaf(); 00234 00235 if(l1 && l2) 00236 { 00237 if(front_list) front_list->push_back(BVHFrontNode(b1, b2)); 00238 00239 res->num_tri_tests++; 00240 00241 const Triangle& tri_id1 = tri_indices1[-node1->first_child - 1]; 00242 const Triangle& tri_id2 = tri_indices2[-node2->first_child - 1]; 00243 00244 const Vec3f& p1 = vertices1[tri_id1[0]]; 00245 const Vec3f& p2 = vertices1[tri_id1[1]]; 00246 const Vec3f& p3 = vertices1[tri_id1[2]]; 00247 00248 const Vec3f& q1 = vertices2[tri_id2[0]]; 00249 const Vec3f& q2 = vertices2[tri_id2[1]]; 00250 const Vec3f& q3 = vertices2[tri_id2[2]]; 00251 00252 // nearest point pair 00253 Vec3f P1, P2; 00254 00255 BVH_REAL d = TriangleDistance::triDistance(p1, p2, p3, q1, q2, q3, 00256 R, T, 00257 P1, P2); 00258 00259 if(d < res->distance) 00260 { 00261 res->distance = d; 00262 00263 res->p1 = P1; 00264 res->p2 = P2; 00265 00266 res->last_tri_id1 = -node1->first_child - 1; 00267 res->last_tri_id2 = -node2->first_child - 1; 00268 } 00269 00270 return; 00271 } 00272 00273 BVH_REAL sz1 = node1->bv.size(); 00274 BVH_REAL sz2 = node2->bv.size(); 00275 00276 int a1, a2, c1, c2; 00277 00278 if(l2 || (!l1 && (sz1 > sz2))) 00279 { 00280 a1 = node1->first_child; 00281 a2 = b2; 00282 c1 = node1->first_child + 1; 00283 c2 = b2; 00284 } 00285 else 00286 { 00287 a1 = b1; 00288 a2 = node2->first_child; 00289 c1 = b1; 00290 c2 = node2->first_child + 1; 00291 } 00292 00293 res->num_bv_tests += 2; 00294 00295 BVH_REAL d1 = distance(R, T, (tree1 + a1)->bv, (tree2 + a2)->bv); 00296 BVH_REAL d2 = distance(R, T, (tree1 + c1)->bv, (tree2 + c2)->bv); 00297 00298 if(d2 < d1) 00299 { 00300 if((d2 < (res->distance - res->abs_err)) || (d2 * (1 + res->rel_err) < res->distance)) 00301 { 00302 distanceRecurse(tree1, tree2, R, T, c1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list); 00303 } 00304 else 00305 { 00306 if(front_list) front_list->push_back(BVHFrontNode(c1, c2)); 00307 } 00308 00309 if((d1 < (res->distance - res->abs_err)) || (d1 * (1 + res->rel_err) < res->distance)) 00310 { 00311 distanceRecurse(tree1, tree2, R, T, a1, a2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list); 00312 } 00313 else 00314 { 00315 if(front_list) front_list->push_back(BVHFrontNode(a1, a2)); 00316 } 00317 00318 00319 } 00320 else 00321 { 00322 if((d1 < (res->distance - res->abs_err)) || (d1 * (1 + res->rel_err) < res->distance)) 00323 { 00324 distanceRecurse(tree1, tree2, R, T, a1, a2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list); 00325 } 00326 else 00327 { 00328 if(front_list) front_list->push_back(BVHFrontNode(a1, a2)); 00329 } 00330 00331 if((d2 < (res->distance - res->abs_err)) || (d2 * (1 + res->rel_err) < res->distance)) 00332 { 00333 distanceRecurse(tree1, tree2, R, T, c1, c2, vertices1, vertices2, tri_indices1, tri_indices2, res, front_list); 00334 } 00335 else 00336 { 00337 if(front_list) front_list->push_back(BVHFrontNode(c1, c2)); 00338 } 00339 } 00340 } 00341 00342 00343 }