$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 00037 #include "collision_checking/rss.h" 00038 00039 namespace collision_checking 00040 { 00041 00042 bool RSS::overlap(const RSS& other) const 00043 { 00044 // compute what transform [R,T] that takes us from cs1 to cs2. 00045 // [R,T] = [R1,T1]'[R2,T2] = [R1',-R1'T][R2,T2] = [R1'R2, R1'(T2-T1)] 00046 // First compute the rotation part, then translation part 00047 Vec3f t = other.Tr - Tr; // T2 - T1 00048 Vec3f T(t.dot(axis[0]), t.dot(axis[1]), t.dot(axis[2])); // R1'(T2-T1) 00049 Vec3f R[3]; 00050 R[0] = Vec3f(axis[0].dot(other.axis[0]), axis[0].dot(other.axis[1]), axis[0].dot(other.axis[2])); 00051 R[1] = Vec3f(axis[1].dot(other.axis[0]), axis[1].dot(other.axis[1]), axis[1].dot(other.axis[2])); 00052 R[2] = Vec3f(axis[2].dot(other.axis[0]), axis[2].dot(other.axis[1]), axis[2].dot(other.axis[2])); 00053 00054 BVH_REAL dist = rectDistance(R, T, l, other.l); 00055 if(dist <= (r + other.r)) return true; 00056 return false; 00057 } 00058 00059 bool overlap(const Vec3f R0[3], const Vec3f& T0, const RSS& b1, const RSS& b2) 00060 { 00061 // R0 R2 00062 Vec3f Rtemp_col[3]; 00063 Rtemp_col[0] = Vec3f(R0[0].dot(b2.axis[0]), R0[1].dot(b2.axis[0]), R0[2].dot(b2.axis[0])); 00064 Rtemp_col[1] = Vec3f(R0[0].dot(b2.axis[1]), R0[1].dot(b2.axis[1]), R0[2].dot(b2.axis[1])); 00065 Rtemp_col[2] = Vec3f(R0[0].dot(b2.axis[2]), R0[1].dot(b2.axis[2]), R0[2].dot(b2.axis[2])); 00066 00067 // R1'Rtemp 00068 Vec3f R[3]; 00069 R[0] = Vec3f(b1.axis[0].dot(Rtemp_col[0]), b1.axis[0].dot(Rtemp_col[1]), b1.axis[0].dot(Rtemp_col[2])); 00070 R[1] = Vec3f(b1.axis[1].dot(Rtemp_col[0]), b1.axis[1].dot(Rtemp_col[1]), b1.axis[1].dot(Rtemp_col[2])); 00071 R[2] = Vec3f(b1.axis[2].dot(Rtemp_col[0]), b1.axis[2].dot(Rtemp_col[1]), b1.axis[2].dot(Rtemp_col[2])); 00072 00073 Vec3f Ttemp = Vec3f(R0[0].dot(b2.Tr), R0[1].dot(b2.Tr), R0[2].dot(b2.Tr)) + T0 - b1.Tr; 00074 00075 Vec3f T = Vec3f(Ttemp.dot(b1.axis[0]), Ttemp.dot(b1.axis[1]), Ttemp.dot(b1.axis[2])); 00076 00077 BVH_REAL dist = RSS::rectDistance(R, T, b1.l, b2.l); 00078 if(dist <= (b1.r + b2.r)) return true; 00079 return false; 00080 } 00081 00082 bool RSS::contain(const Vec3f& p) const 00083 { 00084 Vec3f local_p = p - Tr; 00085 BVH_REAL proj0 = local_p.dot(axis[0]); 00086 BVH_REAL proj1 = local_p.dot(axis[1]); 00087 BVH_REAL proj2 = local_p.dot(axis[2]); 00088 BVH_REAL abs_proj2 = fabs(proj2); 00089 Vec3f proj(proj0, proj1, proj2); 00090 00091 // projection is within the rectangle 00092 if((proj0 < l[0]) && (proj0 > 0) && (proj1 < l[1]) && (proj1 > 0)) 00093 { 00094 if(abs_proj2 < r) 00095 return true; 00096 else 00097 return false; 00098 } 00099 else if((proj0 < l[0]) && (proj0 > 0) && ((proj1 < 0) || (proj1 > l[1]))) 00100 { 00101 BVH_REAL y = (proj1 > 0) ? l[1] : 0; 00102 Vec3f v(proj0, y, 0); 00103 if((proj - v).sqrLength() < r * r) 00104 return true; 00105 else 00106 return false; 00107 } 00108 else if((proj1 < l[1]) && (proj1 > 0) && ((proj0 < 0) || (proj0 > l[0]))) 00109 { 00110 BVH_REAL x = (proj0 > 0) ? l[0] : 0; 00111 Vec3f v(x, proj1, 0); 00112 if((proj - v).sqrLength() < r * r) 00113 return true; 00114 else 00115 return false; 00116 } 00117 else 00118 { 00119 BVH_REAL x = (proj0 > 0) ? l[0] : 0; 00120 BVH_REAL y = (proj1 > 0) ? l[1] : 0; 00121 Vec3f v(x, y, 0); 00122 if((proj - v).sqrLength() < r * r) 00123 return true; 00124 else 00125 return false; 00126 } 00127 } 00128 00129 RSS& RSS::operator += (const Vec3f& p) 00130 { 00131 Vec3f local_p = p - Tr; 00132 BVH_REAL proj0 = local_p.dot(axis[0]); 00133 BVH_REAL proj1 = local_p.dot(axis[1]); 00134 BVH_REAL proj2 = local_p.dot(axis[2]); 00135 BVH_REAL abs_proj2 = fabs(proj2); 00136 Vec3f proj(proj0, proj1, proj2); 00137 00138 // projection is within the rectangle 00139 if((proj0 < l[0]) && (proj0 > 0) && (proj1 < l[1]) && (proj1 > 0)) 00140 { 00141 if(abs_proj2 < r) 00142 ; // do nothing 00143 else 00144 { 00145 r = 0.5 * (r + abs_proj2); // enlarge the r 00146 // change RSS origin position 00147 if(proj2 > 0) 00148 Tr[2] += 0.5 * (abs_proj2 - r); 00149 else 00150 Tr[2] -= 0.5 * (abs_proj2 - r); 00151 } 00152 } 00153 else if((proj0 < l[0]) && (proj0 > 0) && ((proj1 < 0) || (proj1 > l[1]))) 00154 { 00155 BVH_REAL y = (proj1 > 0) ? l[1] : 0; 00156 Vec3f v(proj0, y, 0); 00157 BVH_REAL new_r_sqr = (proj - v).sqrLength(); 00158 if(new_r_sqr < r * r) 00159 ; // do nothing 00160 else 00161 { 00162 if(abs_proj2 < r) 00163 { 00164 BVH_REAL delta_y = - sqrt(r * r - proj2 * proj2) + fabs(proj1 - y); 00165 l[1] += delta_y; 00166 if(proj1 < 0) 00167 Tr[1] -= delta_y; 00168 } 00169 else 00170 { 00171 BVH_REAL delta_y = fabs(proj1 - y); 00172 l[1] += delta_y; 00173 if(proj1 < 0) 00174 Tr[1] -= delta_y; 00175 00176 if(proj2 > 0) 00177 Tr[2] += 0.5 * (abs_proj2 - r); 00178 else 00179 Tr[2] -= 0.5 * (abs_proj2 - r); 00180 } 00181 } 00182 } 00183 else if((proj1 < l[1]) && (proj1 > 0) && ((proj0 < 0) || (proj0 > l[0]))) 00184 { 00185 BVH_REAL x = (proj0 > 0) ? l[0] : 0; 00186 Vec3f v(x, proj1, 0); 00187 BVH_REAL new_r_sqr = (proj - v).sqrLength(); 00188 if(new_r_sqr < r * r) 00189 ; // do nothing 00190 else 00191 { 00192 if(abs_proj2 < r) 00193 { 00194 BVH_REAL delta_x = - sqrt(r * r - proj2 * proj2) + fabs(proj0 - x); 00195 l[0] += delta_x; 00196 if(proj0 < 0) 00197 Tr[0] -= delta_x; 00198 } 00199 else 00200 { 00201 BVH_REAL delta_x = fabs(proj0 - x); 00202 l[0] += delta_x; 00203 if(proj0 < 0) 00204 Tr[0] -= delta_x; 00205 00206 if(proj2 > 0) 00207 Tr[2] += 0.5 * (abs_proj2 - r); 00208 else 00209 Tr[2] -= 0.5 * (abs_proj2 - r); 00210 } 00211 } 00212 } 00213 else 00214 { 00215 BVH_REAL x = (proj0 > 0) ? l[0] : 0; 00216 BVH_REAL y = (proj1 > 0) ? l[1] : 0; 00217 Vec3f v(x, y, 0); 00218 BVH_REAL new_r_sqr = (proj - v).sqrLength(); 00219 if(new_r_sqr < r * r) 00220 ; // do nothing 00221 else 00222 { 00223 if(abs_proj2 < r) 00224 { 00225 BVH_REAL diag = sqrt(new_r_sqr - proj2 * proj2); 00226 BVH_REAL delta_diag = - sqrt(r * r - proj2 * proj2) + diag; 00227 00228 BVH_REAL delta_x = delta_diag / diag * fabs(proj0 - x); 00229 BVH_REAL delta_y = delta_diag / diag * fabs(proj1 - y); 00230 l[0] += delta_x; 00231 l[1] += delta_y; 00232 00233 if(proj0 < 0 && proj1 < 0) 00234 { 00235 Tr[0] -= delta_x; 00236 Tr[1] -= delta_y; 00237 } 00238 } 00239 else 00240 { 00241 BVH_REAL delta_x = fabs(proj0 - x); 00242 BVH_REAL delta_y = fabs(proj1 - y); 00243 00244 l[0] += delta_x; 00245 l[1] += delta_y; 00246 00247 if(proj0 < 0 && proj1 < 0) 00248 { 00249 Tr[0] -= delta_x; 00250 Tr[1] -= delta_y; 00251 } 00252 00253 if(proj2 > 0) 00254 Tr[2] += 0.5 * (abs_proj2 - r); 00255 else 00256 Tr[2] -= 0.5 * (abs_proj2 - r); 00257 } 00258 } 00259 } 00260 00261 return *this; 00262 } 00263 00264 RSS RSS::operator + (const RSS& other) const 00265 { 00266 RSS res = *this; 00267 00268 Vec3f d0_pos = other.axis[0] * (other.l[0] + other.r); 00269 Vec3f d1_pos = other.axis[1] * (other.l[1] + other.r); 00270 Vec3f d0_neg = other.axis[0] * (-other.r); 00271 Vec3f d1_neg = other.axis[1] * (-other.r); 00272 Vec3f d2_pos = other.axis[2] * other.r; 00273 Vec3f d2_neg = other.axis[2] * (-other.r); 00274 00275 Vec3f v[8]; 00276 v[0] = other.Tr + d0_pos + d1_pos + d2_pos; 00277 v[1] = other.Tr + d0_pos + d1_pos + d2_neg; 00278 v[2] = other.Tr + d0_pos + d1_neg + d2_pos; 00279 v[3] = other.Tr + d0_pos + d1_neg + d2_neg; 00280 v[4] = other.Tr + d0_neg + d1_pos + d2_pos; 00281 v[5] = other.Tr + d0_neg + d1_pos + d2_neg; 00282 v[6] = other.Tr + d0_neg + d1_neg + d2_pos; 00283 v[7] = other.Tr + d0_neg + d1_neg + d2_neg; 00284 00285 for(int i = 0; i < 8; ++i) 00286 { 00287 res += v[i]; 00288 } 00289 00290 return res; 00291 } 00292 00293 BVH_REAL RSS::distance(const RSS& other) const 00294 { 00295 // compute what transform [R,T] that takes us from cs1 to cs2. 00296 // [R,T] = [R1,T1]'[R2,T2] = [R1',-R1'T][R2,T2] = [R1'R2, R1'(T2-T1)] 00297 // First compute the rotation part, then translation part 00298 Vec3f t = other.Tr - Tr; // T2 - T1 00299 Vec3f T(t.dot(axis[0]), t.dot(axis[1]), t.dot(axis[2])); // R1'(T2-T1) 00300 Vec3f R[3]; 00301 R[0] = Vec3f(axis[0].dot(other.axis[0]), axis[0].dot(other.axis[1]), axis[0].dot(other.axis[2])); 00302 R[1] = Vec3f(axis[1].dot(other.axis[0]), axis[1].dot(other.axis[1]), axis[1].dot(other.axis[2])); 00303 R[2] = Vec3f(axis[2].dot(other.axis[0]), axis[2].dot(other.axis[1]), axis[2].dot(other.axis[2])); 00304 00305 BVH_REAL dist = rectDistance(R, T, l, other.l); 00306 dist -= (r + other.r); 00307 return (dist < (BVH_REAL)0.0) ? (BVH_REAL)0.0 : dist; 00308 } 00309 00310 BVH_REAL distance(const Vec3f R0[3], const Vec3f& T0, const RSS& b1, const RSS& b2, Vec3f* P, Vec3f* Q) 00311 { 00312 // R0 R2 00313 Vec3f Rtemp_col[3]; 00314 Rtemp_col[0] = Vec3f(R0[0].dot(b2.axis[0]), R0[1].dot(b2.axis[0]), R0[2].dot(b2.axis[0])); 00315 Rtemp_col[1] = Vec3f(R0[0].dot(b2.axis[1]), R0[1].dot(b2.axis[1]), R0[2].dot(b2.axis[1])); 00316 Rtemp_col[2] = Vec3f(R0[0].dot(b2.axis[2]), R0[1].dot(b2.axis[2]), R0[2].dot(b2.axis[2])); 00317 00318 // R1'Rtemp 00319 Vec3f R[3]; 00320 R[0] = Vec3f(b1.axis[0].dot(Rtemp_col[0]), b1.axis[0].dot(Rtemp_col[1]), b1.axis[0].dot(Rtemp_col[2])); 00321 R[1] = Vec3f(b1.axis[1].dot(Rtemp_col[0]), b1.axis[1].dot(Rtemp_col[1]), b1.axis[1].dot(Rtemp_col[2])); 00322 R[2] = Vec3f(b1.axis[2].dot(Rtemp_col[0]), b1.axis[2].dot(Rtemp_col[1]), b1.axis[2].dot(Rtemp_col[2])); 00323 00324 Vec3f Ttemp = Vec3f(R0[0].dot(b2.Tr), R0[1].dot(b2.Tr), R0[2].dot(b2.Tr)) + T0 - b1.Tr; 00325 00326 Vec3f T = Vec3f(Ttemp.dot(b1.axis[0]), Ttemp.dot(b1.axis[1]), Ttemp.dot(b1.axis[2])); 00327 00328 BVH_REAL dist = RSS::rectDistance(R, T, b1.l, b2.l, P, Q); 00329 dist -= (b1.r + b2.r); 00330 return (dist < (BVH_REAL)0.0) ? (BVH_REAL)0.0 : dist; 00331 } 00332 00333 00334 BVH_REAL RSS::rectDistance(const Vec3f Rab[3], Vec3f const& Tab, const BVH_REAL a[2], const BVH_REAL b[2], Vec3f* P, Vec3f* Q) 00335 { 00336 BVH_REAL A0_dot_B0, A0_dot_B1, A1_dot_B0, A1_dot_B1; 00337 00338 A0_dot_B0 = Rab[0][0]; 00339 A0_dot_B1 = Rab[0][1]; 00340 A1_dot_B0 = Rab[1][0]; 00341 A1_dot_B1 = Rab[1][1]; 00342 00343 BVH_REAL aA0_dot_B0, aA0_dot_B1, aA1_dot_B0, aA1_dot_B1; 00344 BVH_REAL bA0_dot_B0, bA0_dot_B1, bA1_dot_B0, bA1_dot_B1; 00345 00346 aA0_dot_B0 = a[0] * A0_dot_B0; 00347 aA0_dot_B1 = a[0] * A0_dot_B1; 00348 aA1_dot_B0 = a[1] * A1_dot_B0; 00349 aA1_dot_B1 = a[1] * A1_dot_B1; 00350 bA0_dot_B0 = b[0] * A0_dot_B0; 00351 bA1_dot_B0 = b[0] * A1_dot_B0; 00352 bA0_dot_B1 = b[1] * A0_dot_B1; 00353 bA1_dot_B1 = b[1] * A1_dot_B1; 00354 00355 Vec3f Tba = MTxV(Rab, Tab); 00356 00357 Vec3f S; 00358 BVH_REAL t, u; 00359 00360 // determine if any edge pair contains the closest points 00361 00362 BVH_REAL ALL_x, ALU_x, AUL_x, AUU_x; 00363 BVH_REAL BLL_x, BLU_x, BUL_x, BUU_x; 00364 BVH_REAL LA1_lx, LA1_ux, UA1_lx, UA1_ux, LB1_lx, LB1_ux, UB1_lx, UB1_ux; 00365 00366 ALL_x = -Tba[0]; 00367 ALU_x = ALL_x + aA1_dot_B0; 00368 AUL_x = ALL_x + aA0_dot_B0; 00369 AUU_x = ALU_x + aA0_dot_B0; 00370 00371 if(ALL_x < ALU_x) 00372 { 00373 LA1_lx = ALL_x; 00374 LA1_ux = ALU_x; 00375 UA1_lx = AUL_x; 00376 UA1_ux = AUU_x; 00377 } 00378 else 00379 { 00380 LA1_lx = ALU_x; 00381 LA1_ux = ALL_x; 00382 UA1_lx = AUU_x; 00383 UA1_ux = AUL_x; 00384 } 00385 00386 BLL_x = Tab[0]; 00387 BLU_x = BLL_x + bA0_dot_B1; 00388 BUL_x = BLL_x + bA0_dot_B0; 00389 BUU_x = BLU_x + bA0_dot_B0; 00390 00391 if(BLL_x < BLU_x) 00392 { 00393 LB1_lx = BLL_x; 00394 LB1_ux = BLU_x; 00395 UB1_lx = BUL_x; 00396 UB1_ux = BUU_x; 00397 } 00398 else 00399 { 00400 LB1_lx = BLU_x; 00401 LB1_ux = BLL_x; 00402 UB1_lx = BUU_x; 00403 UB1_ux = BUL_x; 00404 } 00405 00406 // UA1, UB1 00407 00408 if((UA1_ux > b[0]) && (UB1_ux > a[0])) 00409 { 00410 if(((UA1_lx > b[0]) || 00411 inVoronoi(b[1], a[1], A1_dot_B0, aA0_dot_B0 - b[0] - Tba[0], 00412 A1_dot_B1, aA0_dot_B1 - Tba[1], 00413 -Tab[1] - bA1_dot_B0)) 00414 && 00415 ((UB1_lx > a[0]) || 00416 inVoronoi(a[1], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0 - a[0], 00417 A1_dot_B1, Tab[1] + bA1_dot_B0, Tba[1] - aA0_dot_B1))) 00418 { 00419 segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1] + bA1_dot_B0, 00420 Tba[1] - aA0_dot_B1); 00421 00422 S[0] = Tab[0] + Rab[0][0] * b[0] + Rab[0][1] * u - a[0] ; 00423 S[1] = Tab[1] + Rab[1][0] * b[0] + Rab[1][1] * u - t; 00424 S[2] = Tab[2] + Rab[2][0] * b[0] + Rab[2][1] * u; 00425 00426 if(P && Q) 00427 { 00428 *P = Vec3f(a[0], t, 0); 00429 *Q = S + (*P); 00430 } 00431 00432 return S.length(); 00433 } 00434 } 00435 00436 00437 // UA1, LB1 00438 00439 if((UA1_lx < 0) && (LB1_ux > a[0])) 00440 { 00441 if(((UA1_ux < 0) || 00442 inVoronoi(b[1], a[1], -A1_dot_B0, Tba[0] - aA0_dot_B0, 00443 A1_dot_B1, aA0_dot_B1 - Tba[1], -Tab[1])) 00444 && 00445 ((LB1_lx > a[0]) || 00446 inVoronoi(a[1], b[1], A0_dot_B1, Tab[0] - a[0], 00447 A1_dot_B1, Tab[1], Tba[1] - aA0_dot_B1))) 00448 { 00449 segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1], Tba[1] - aA0_dot_B1); 00450 00451 S[0] = Tab[0] + Rab[0][1] * u - a[0]; 00452 S[1] = Tab[1] + Rab[1][1] * u - t; 00453 S[2] = Tab[2] + Rab[2][1] * u; 00454 00455 if(P && Q) 00456 { 00457 *P = Vec3f(a[0], t, 0); 00458 *Q = S + (*P); 00459 } 00460 00461 return S.length(); 00462 } 00463 } 00464 00465 // LA1, UB1 00466 00467 if((LA1_ux > b[0]) && (UB1_lx < 0)) 00468 { 00469 if(((LA1_lx > b[0]) || 00470 inVoronoi(b[1], a[1], A1_dot_B0, -Tba[0] - b[0], 00471 A1_dot_B1, -Tba[1], -Tab[1] - bA1_dot_B0)) 00472 && 00473 ((UB1_ux < 0) || 00474 inVoronoi(a[1], b[1], -A0_dot_B1, -Tab[0] - bA0_dot_B0, 00475 A1_dot_B1, Tab[1] + bA1_dot_B0, Tba[1]))) 00476 { 00477 segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1] + bA1_dot_B0, Tba[1]); 00478 00479 S[0] = Tab[0] + Rab[0][0] * b[0] + Rab[0][1] * u; 00480 S[1] = Tab[1] + Rab[1][0] * b[0] + Rab[1][1] * u - t; 00481 S[2] = Tab[2] + Rab[2][0] * b[0] + Rab[2][1] * u; 00482 00483 if(P && Q) 00484 { 00485 *P = Vec3f(0, t, 0); 00486 *Q = S + (*P); 00487 } 00488 00489 return S.length(); 00490 } 00491 } 00492 00493 // LA1, LB1 00494 00495 if((LA1_lx < 0) && (LB1_lx < 0)) 00496 { 00497 if (((LA1_ux < 0) || 00498 inVoronoi(b[1], a[1], -A1_dot_B0, Tba[0], A1_dot_B1, 00499 -Tba[1], -Tab[1])) 00500 && 00501 ((LB1_ux < 0) || 00502 inVoronoi(a[1], b[1], -A0_dot_B1, -Tab[0], A1_dot_B1, 00503 Tab[1], Tba[1]))) 00504 { 00505 segCoords(t, u, a[1], b[1], A1_dot_B1, Tab[1], Tba[1]); 00506 00507 S[0] = Tab[0] + Rab[0][1] * u; 00508 S[1] = Tab[1] + Rab[1][1] * u - t; 00509 S[2] = Tab[2] + Rab[2][1] * u; 00510 00511 if(P && Q) 00512 { 00513 *P = Vec3f(0, t, 0); 00514 *Q = S + (*P); 00515 } 00516 00517 return S.length(); 00518 } 00519 } 00520 00521 BVH_REAL ALL_y, ALU_y, AUL_y, AUU_y; 00522 00523 ALL_y = -Tba[1]; 00524 ALU_y = ALL_y + aA1_dot_B1; 00525 AUL_y = ALL_y + aA0_dot_B1; 00526 AUU_y = ALU_y + aA0_dot_B1; 00527 00528 BVH_REAL LA1_ly, LA1_uy, UA1_ly, UA1_uy, LB0_lx, LB0_ux, UB0_lx, UB0_ux; 00529 00530 if(ALL_y < ALU_y) 00531 { 00532 LA1_ly = ALL_y; 00533 LA1_uy = ALU_y; 00534 UA1_ly = AUL_y; 00535 UA1_uy = AUU_y; 00536 } 00537 else 00538 { 00539 LA1_ly = ALU_y; 00540 LA1_uy = ALL_y; 00541 UA1_ly = AUU_y; 00542 UA1_uy = AUL_y; 00543 } 00544 00545 if(BLL_x < BUL_x) 00546 { 00547 LB0_lx = BLL_x; 00548 LB0_ux = BUL_x; 00549 UB0_lx = BLU_x; 00550 UB0_ux = BUU_x; 00551 } 00552 else 00553 { 00554 LB0_lx = BUL_x; 00555 LB0_ux = BLL_x; 00556 UB0_lx = BUU_x; 00557 UB0_ux = BLU_x; 00558 } 00559 00560 // UA1, UB0 00561 00562 if((UA1_uy > b[1]) && (UB0_ux > a[0])) 00563 { 00564 if(((UA1_ly > b[1]) || 00565 inVoronoi(b[0], a[1], A1_dot_B1, aA0_dot_B1 - Tba[1] - b[1], 00566 A1_dot_B0, aA0_dot_B0 - Tba[0], -Tab[1] - bA1_dot_B1)) 00567 && 00568 ((UB0_lx > a[0]) || 00569 inVoronoi(a[1], b[0], A0_dot_B0, Tab[0] - a[0] + bA0_dot_B1, 00570 A1_dot_B0, Tab[1] + bA1_dot_B1, Tba[0] - aA0_dot_B0))) 00571 { 00572 segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1] + bA1_dot_B1, 00573 Tba[0] - aA0_dot_B0); 00574 00575 S[0] = Tab[0] + Rab[0][1] * b[1] + Rab[0][0] * u - a[0] ; 00576 S[1] = Tab[1] + Rab[1][1] * b[1] + Rab[1][0] * u - t; 00577 S[2] = Tab[2] + Rab[2][1] * b[1] + Rab[2][0] * u; 00578 00579 if(P && Q) 00580 { 00581 *P = Vec3f(a[0], t, 0); 00582 *Q = S + (*P); 00583 } 00584 00585 return S.length(); 00586 } 00587 } 00588 00589 // UA1, LB0 00590 00591 if((UA1_ly < 0) && (LB0_ux > a[0])) 00592 { 00593 if(((UA1_uy < 0) || 00594 inVoronoi(b[0], a[1], -A1_dot_B1, Tba[1] - aA0_dot_B1, A1_dot_B0, 00595 aA0_dot_B0 - Tba[0], -Tab[1])) 00596 && 00597 ((LB0_lx > a[0]) || 00598 inVoronoi(a[1], b[0], A0_dot_B0, Tab[0] - a[0], 00599 A1_dot_B0, Tab[1], Tba[0] - aA0_dot_B0))) 00600 { 00601 segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1], Tba[0] - aA0_dot_B0); 00602 00603 S[0] = Tab[0] + Rab[0][0] * u - a[0]; 00604 S[1] = Tab[1] + Rab[1][0] * u - t; 00605 S[2] = Tab[2] + Rab[2][0] * u; 00606 00607 if(P && Q) 00608 { 00609 *P = Vec3f(a[0], t, 0); 00610 *Q = S + (*P); 00611 } 00612 00613 return S.length(); 00614 } 00615 } 00616 00617 // LA1, UB0 00618 00619 if((LA1_uy > b[1]) && (UB0_lx < 0)) 00620 { 00621 if(((LA1_ly > b[1]) || 00622 inVoronoi(b[0], a[1], A1_dot_B1, -Tba[1] - b[1], 00623 A1_dot_B0, -Tba[0], -Tab[1] - bA1_dot_B1)) 00624 && 00625 00626 ((UB0_ux < 0) || 00627 inVoronoi(a[1], b[0], -A0_dot_B0, -Tab[0] - bA0_dot_B1, A1_dot_B0, 00628 Tab[1] + bA1_dot_B1, Tba[0]))) 00629 { 00630 segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1] + bA1_dot_B1, Tba[0]); 00631 00632 S[0] = Tab[0] + Rab[0][1] * b[1] + Rab[0][0] * u; 00633 S[1] = Tab[1] + Rab[1][1] * b[1] + Rab[1][0] * u - t; 00634 S[2] = Tab[2] + Rab[2][1] * b[1] + Rab[2][0] * u; 00635 00636 if(P && Q) 00637 { 00638 *P = Vec3f(0, t, 0); 00639 *Q = S + (*P); 00640 } 00641 00642 00643 return S.length(); 00644 } 00645 } 00646 00647 // LA1, LB0 00648 00649 if((LA1_ly < 0) && (LB0_lx < 0)) 00650 { 00651 if(((LA1_uy < 0) || 00652 inVoronoi(b[0], a[1], -A1_dot_B1, Tba[1], A1_dot_B0, 00653 -Tba[0], -Tab[1])) 00654 && 00655 ((LB0_ux < 0) || 00656 inVoronoi(a[1], b[0], -A0_dot_B0, -Tab[0], A1_dot_B0, 00657 Tab[1], Tba[0]))) 00658 { 00659 segCoords(t, u, a[1], b[0], A1_dot_B0, Tab[1], Tba[0]); 00660 00661 S[0] = Tab[0] + Rab[0][0] * u; 00662 S[1] = Tab[1] + Rab[1][0] * u - t; 00663 S[2] = Tab[2] + Rab[2][0] * u; 00664 00665 if(P&& Q) 00666 { 00667 *P = Vec3f(0, t, 0); 00668 *Q = S + (*P); 00669 } 00670 00671 return S.length(); 00672 } 00673 } 00674 00675 BVH_REAL BLL_y, BLU_y, BUL_y, BUU_y; 00676 00677 BLL_y = Tab[1]; 00678 BLU_y = BLL_y + bA1_dot_B1; 00679 BUL_y = BLL_y + bA1_dot_B0; 00680 BUU_y = BLU_y + bA1_dot_B0; 00681 00682 BVH_REAL LA0_lx, LA0_ux, UA0_lx, UA0_ux, LB1_ly, LB1_uy, UB1_ly, UB1_uy; 00683 00684 if(ALL_x < AUL_x) 00685 { 00686 LA0_lx = ALL_x; 00687 LA0_ux = AUL_x; 00688 UA0_lx = ALU_x; 00689 UA0_ux = AUU_x; 00690 } 00691 else 00692 { 00693 LA0_lx = AUL_x; 00694 LA0_ux = ALL_x; 00695 UA0_lx = AUU_x; 00696 UA0_ux = ALU_x; 00697 } 00698 00699 if(BLL_y < BLU_y) 00700 { 00701 LB1_ly = BLL_y; 00702 LB1_uy = BLU_y; 00703 UB1_ly = BUL_y; 00704 UB1_uy = BUU_y; 00705 } 00706 else 00707 { 00708 LB1_ly = BLU_y; 00709 LB1_uy = BLL_y; 00710 UB1_ly = BUU_y; 00711 UB1_uy = BUL_y; 00712 } 00713 00714 // UA0, UB1 00715 00716 if((UA0_ux > b[0]) && (UB1_uy > a[1])) 00717 { 00718 if(((UA0_lx > b[0]) || 00719 inVoronoi(b[1], a[0], A0_dot_B0, aA1_dot_B0 - Tba[0] - b[0], 00720 A0_dot_B1, aA1_dot_B1 - Tba[1], -Tab[0] - bA0_dot_B0)) 00721 && 00722 ((UB1_ly > a[1]) || 00723 inVoronoi(a[0], b[1], A1_dot_B1, Tab[1] - a[1] + bA1_dot_B0, 00724 A0_dot_B1, Tab[0] + bA0_dot_B0, Tba[1] - aA1_dot_B1))) 00725 { 00726 segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0, 00727 Tba[1] - aA1_dot_B1); 00728 00729 S[0] = Tab[0] + Rab[0][0] * b[0] + Rab[0][1] * u - t; 00730 S[1] = Tab[1] + Rab[1][0] * b[0] + Rab[1][1] * u - a[1]; 00731 S[2] = Tab[2] + Rab[2][0] * b[0] + Rab[2][1] * u; 00732 00733 if(P && Q) 00734 { 00735 *P = Vec3f(t, a[1], 0); 00736 *Q = S + (*P); 00737 } 00738 00739 return S.length(); 00740 } 00741 } 00742 00743 // UA0, LB1 00744 00745 if((UA0_lx < 0) && (LB1_uy > a[1])) 00746 { 00747 if(((UA0_ux < 0) || 00748 inVoronoi(b[1], a[0], -A0_dot_B0, Tba[0] - aA1_dot_B0, A0_dot_B1, 00749 aA1_dot_B1 - Tba[1], -Tab[0])) 00750 && 00751 ((LB1_ly > a[1]) || 00752 inVoronoi(a[0], b[1], A1_dot_B1, Tab[1] - a[1], A0_dot_B1, Tab[0], 00753 Tba[1] - aA1_dot_B1))) 00754 { 00755 segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0], Tba[1] - aA1_dot_B1); 00756 00757 S[0] = Tab[0] + Rab[0][1] * u - t; 00758 S[1] = Tab[1] + Rab[1][1] * u - a[1]; 00759 S[2] = Tab[2] + Rab[2][1] * u; 00760 00761 if(P && Q) 00762 { 00763 *P = Vec3f(t, a[1], 0); 00764 *Q = S + (*P); 00765 } 00766 00767 return S.length(); 00768 } 00769 } 00770 00771 // LA0, UB1 00772 00773 if((LA0_ux > b[0]) && (UB1_ly < 0)) 00774 { 00775 if(((LA0_lx > b[0]) || 00776 inVoronoi(b[1], a[0], A0_dot_B0, -b[0] - Tba[0], A0_dot_B1, -Tba[1], 00777 -bA0_dot_B0 - Tab[0])) 00778 && 00779 ((UB1_uy < 0) || 00780 inVoronoi(a[0], b[1], -A1_dot_B1, -Tab[1] - bA1_dot_B0, A0_dot_B1, 00781 Tab[0] + bA0_dot_B0, Tba[1]))) 00782 { 00783 segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0] + bA0_dot_B0, Tba[1]); 00784 00785 S[0] = Tab[0] + Rab[0][0] * b[0] + Rab[0][1] * u - t; 00786 S[1] = Tab[1] + Rab[1][0] * b[0] + Rab[1][1] * u; 00787 S[2] = Tab[2] + Rab[2][0] * b[0] + Rab[2][1] * u; 00788 00789 if(P && Q) 00790 { 00791 *P = Vec3f(t, 0, 0); 00792 *Q = S + (*P); 00793 } 00794 00795 return S.length(); 00796 } 00797 } 00798 00799 // LA0, LB1 00800 00801 if((LA0_lx < 0) && (LB1_ly < 0)) 00802 { 00803 if(((LA0_ux < 0) || 00804 inVoronoi(b[1], a[0], -A0_dot_B0, Tba[0], A0_dot_B1, -Tba[1], 00805 -Tab[0])) 00806 && 00807 ((LB1_uy < 0) || 00808 inVoronoi(a[0], b[1], -A1_dot_B1, -Tab[1], A0_dot_B1, 00809 Tab[0], Tba[1]))) 00810 { 00811 segCoords(t, u, a[0], b[1], A0_dot_B1, Tab[0], Tba[1]); 00812 00813 S[0] = Tab[0] + Rab[0][1] * u - t; 00814 S[1] = Tab[1] + Rab[1][1] * u; 00815 S[2] = Tab[2] + Rab[2][1] * u; 00816 00817 if(P && Q) 00818 { 00819 *P = Vec3f(t, 0, 0); 00820 *Q = S + (*P); 00821 } 00822 00823 return S.length(); 00824 } 00825 } 00826 00827 BVH_REAL LA0_ly, LA0_uy, UA0_ly, UA0_uy, LB0_ly, LB0_uy, UB0_ly, UB0_uy; 00828 00829 if(ALL_y < AUL_y) 00830 { 00831 LA0_ly = ALL_y; 00832 LA0_uy = AUL_y; 00833 UA0_ly = ALU_y; 00834 UA0_uy = AUU_y; 00835 } 00836 else 00837 { 00838 LA0_ly = AUL_y; 00839 LA0_uy = ALL_y; 00840 UA0_ly = AUU_y; 00841 UA0_uy = ALU_y; 00842 } 00843 00844 if(BLL_y < BUL_y) 00845 { 00846 LB0_ly = BLL_y; 00847 LB0_uy = BUL_y; 00848 UB0_ly = BLU_y; 00849 UB0_uy = BUU_y; 00850 } 00851 else 00852 { 00853 LB0_ly = BUL_y; 00854 LB0_uy = BLL_y; 00855 UB0_ly = BUU_y; 00856 UB0_uy = BLU_y; 00857 } 00858 00859 // UA0, UB0 00860 00861 if((UA0_uy > b[1]) && (UB0_uy > a[1])) 00862 { 00863 if(((UA0_ly > b[1]) || 00864 inVoronoi(b[0], a[0], A0_dot_B1, aA1_dot_B1 - Tba[1] - b[1], 00865 A0_dot_B0, aA1_dot_B0 - Tba[0], -Tab[0] - bA0_dot_B1)) 00866 && 00867 ((UB0_ly > a[1]) || 00868 inVoronoi(a[0], b[0], A1_dot_B0, Tab[1] - a[1] + bA1_dot_B1, A0_dot_B0, 00869 Tab[0] + bA0_dot_B1, Tba[0] - aA1_dot_B0))) 00870 { 00871 segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0] + bA0_dot_B1, 00872 Tba[0] - aA1_dot_B0); 00873 00874 S[0] = Tab[0] + Rab[0][1] * b[1] + Rab[0][0] * u - t; 00875 S[1] = Tab[1] + Rab[1][1] * b[1] + Rab[1][0] * u - a[1]; 00876 S[2] = Tab[2] + Rab[2][1] * b[1] + Rab[2][0] * u; 00877 00878 if(P && Q) 00879 { 00880 *P = Vec3f(t, a[1], 0); 00881 *Q = S + (*P); 00882 } 00883 00884 return S.length(); 00885 } 00886 } 00887 00888 // UA0, LB0 00889 00890 if((UA0_ly < 0) && (LB0_uy > a[1])) 00891 { 00892 if(((UA0_uy < 0) || 00893 inVoronoi(b[0], a[0], -A0_dot_B1, Tba[1] - aA1_dot_B1, A0_dot_B0, 00894 aA1_dot_B0 - Tba[0], -Tab[0])) 00895 && 00896 ((LB0_ly > a[1]) || 00897 inVoronoi(a[0], b[0], A1_dot_B0, Tab[1] - a[1], 00898 A0_dot_B0, Tab[0], Tba[0] - aA1_dot_B0))) 00899 { 00900 segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0], Tba[0] - aA1_dot_B0); 00901 00902 S[0] = Tab[0] + Rab[0][0] * u - t; 00903 S[1] = Tab[1] + Rab[1][0] * u - a[1]; 00904 S[2] = Tab[2] + Rab[2][0] * u; 00905 00906 if(P && Q) 00907 { 00908 *P = Vec3f(t, a[1], 0); 00909 *Q = S + (*P); 00910 } 00911 00912 return S.length(); 00913 } 00914 } 00915 00916 // LA0, UB0 00917 00918 if((LA0_uy > b[1]) && (UB0_ly < 0)) 00919 { 00920 if(((LA0_ly > b[1]) || 00921 inVoronoi(b[0], a[0], A0_dot_B1, -Tba[1] - b[1], A0_dot_B0, -Tba[0], 00922 -Tab[0] - bA0_dot_B1)) 00923 && 00924 00925 ((UB0_uy < 0) || 00926 inVoronoi(a[0], b[0], -A1_dot_B0, -Tab[1] - bA1_dot_B1, A0_dot_B0, 00927 Tab[0] + bA0_dot_B1, Tba[0]))) 00928 { 00929 segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0] + bA0_dot_B1, Tba[0]); 00930 00931 S[0] = Tab[0] + Rab[0][1] * b[1] + Rab[0][0] * u - t; 00932 S[1] = Tab[1] + Rab[1][1] * b[1] + Rab[1][0] * u; 00933 S[2] = Tab[2] + Rab[2][1] * b[1] + Rab[2][0] * u; 00934 00935 if(P && Q) 00936 { 00937 *P = Vec3f(t, 0, 0); 00938 *Q = S + (*P); 00939 } 00940 00941 return S.length(); 00942 } 00943 } 00944 00945 // LA0, LB0 00946 00947 if((LA0_ly < 0) && (LB0_ly < 0)) 00948 { 00949 if(((LA0_uy < 0) || 00950 inVoronoi(b[0], a[0], -A0_dot_B1, Tba[1], A0_dot_B0, 00951 -Tba[0], -Tab[0])) 00952 && 00953 ((LB0_uy < 0) || 00954 inVoronoi(a[0], b[0], -A1_dot_B0, -Tab[1], A0_dot_B0, 00955 Tab[0], Tba[0]))) 00956 { 00957 segCoords(t, u, a[0], b[0], A0_dot_B0, Tab[0], Tba[0]); 00958 00959 S[0] = Tab[0] + Rab[0][0] * u - t; 00960 S[1] = Tab[1] + Rab[1][0] * u; 00961 S[2] = Tab[2] + Rab[2][0] * u; 00962 00963 if(P && Q) 00964 { 00965 *P = Vec3f(t, 0, 0); 00966 *Q = S + (*P); 00967 } 00968 00969 return S.length(); 00970 } 00971 } 00972 00973 // no edges passed, take max separation along face normals 00974 00975 BVH_REAL sep1, sep2; 00976 00977 if(Tab[2] > 0.0) 00978 { 00979 sep1 = Tab[2]; 00980 if (Rab[2][0] < 0.0) sep1 += b[0] * Rab[2][0]; 00981 if (Rab[2][1] < 0.0) sep1 += b[1] * Rab[2][1]; 00982 } 00983 else 00984 { 00985 sep1 = -Tab[2]; 00986 if (Rab[2][0] > 0.0) sep1 -= b[0] * Rab[2][0]; 00987 if (Rab[2][1] > 0.0) sep1 -= b[1] * Rab[2][1]; 00988 } 00989 00990 if(Tba[2] < 0) 00991 { 00992 sep2 = -Tba[2]; 00993 if (Rab[0][2] < 0.0) sep2 += a[0] * Rab[0][2]; 00994 if (Rab[1][2] < 0.0) sep2 += a[1] * Rab[1][2]; 00995 } 00996 else 00997 { 00998 sep2 = Tba[2]; 00999 if (Rab[0][2] > 0.0) sep2 -= a[0] * Rab[0][2]; 01000 if (Rab[1][2] > 0.0) sep2 -= a[1] * Rab[1][2]; 01001 } 01002 01003 if(sep1 >= sep2 && sep1 >= 0) 01004 { 01005 if(Tab[2] > 0) 01006 S = Vec3f(0, 0, sep1); 01007 else 01008 S = Vec3f(0, 0, -sep1); 01009 01010 if(P && Q) 01011 { 01012 *Q = S; 01013 *P = Vec3f(0, 0, 0); 01014 } 01015 } 01016 01017 if(sep2 >= sep1 && sep2 >= 0) 01018 { 01019 Vec3f Q_(Tab[0], Tab[1], Tab[2]); 01020 Vec3f P_; 01021 if(Tba[2] < 0) 01022 { 01023 P_[0] = Rab[0][2] * sep2 + Tab[0]; 01024 P_[1] = Rab[1][2] * sep2 + Tab[1]; 01025 P_[2] = Rab[2][2] * sep2 + Tab[2]; 01026 } 01027 else 01028 { 01029 P_[0] = -Rab[0][2] * sep2 + Tab[0]; 01030 P_[1] = -Rab[1][2] * sep2 + Tab[1]; 01031 P_[2] = -Rab[2][2] * sep2 + Tab[2]; 01032 } 01033 01034 S = Q_ - P_; 01035 01036 if(P && Q) 01037 { 01038 *P = P_; 01039 *Q = Q_; 01040 } 01041 } 01042 01043 BVH_REAL sep = (sep1 > sep2 ? sep1 : sep2); 01044 return (sep > 0 ? sep : 0); 01045 } 01046 01047 01048 void RSS::clipToRange(BVH_REAL& val, BVH_REAL a, BVH_REAL b) 01049 { 01050 if(val < a) val = a; 01051 else if(val > b) val = b; 01052 } 01053 01054 01055 void RSS::segCoords(BVH_REAL& t, BVH_REAL& u, BVH_REAL a, BVH_REAL b, BVH_REAL A_dot_B, BVH_REAL A_dot_T, BVH_REAL B_dot_T) 01056 { 01057 BVH_REAL denom = 1 - A_dot_B * A_dot_B; 01058 01059 if(denom == 0) t = 0; 01060 else 01061 { 01062 t = (A_dot_T - B_dot_T * A_dot_B) / denom; 01063 clipToRange(t, 0, a); 01064 } 01065 01066 u = t * A_dot_B - B_dot_T; 01067 if(u < 0) 01068 { 01069 u = 0; 01070 t = A_dot_T; 01071 clipToRange(t, 0, a); 01072 } 01073 else if(u > b) 01074 { 01075 u = b; 01076 t = u * A_dot_B + A_dot_T; 01077 clipToRange(t, 0, a); 01078 } 01079 } 01080 01081 bool RSS::inVoronoi(BVH_REAL a, BVH_REAL b, BVH_REAL Anorm_dot_B, BVH_REAL Anorm_dot_T, BVH_REAL A_dot_B, BVH_REAL A_dot_T, BVH_REAL B_dot_T) 01082 { 01083 if(fabs(Anorm_dot_B) < 1e-7) return false; 01084 01085 BVH_REAL t, u, v; 01086 01087 u = -Anorm_dot_T / Anorm_dot_B; 01088 clipToRange(u, 0, b); 01089 01090 t = u * A_dot_B + A_dot_T; 01091 clipToRange(t, 0, a); 01092 01093 v = t * A_dot_B - B_dot_T; 01094 01095 if(Anorm_dot_B > 0) 01096 { 01097 if(v > (u + 1e-7)) return true; 01098 } 01099 else 01100 { 01101 if(v < (u - 1e-7)) return true; 01102 } 01103 return false; 01104 } 01105 01106 01107 01108 01109 01110 }