$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/obb.h" 00038 00039 namespace collision_checking 00040 { 00041 OBB::SimpleQuaternion::SimpleQuaternion() {} 00042 00043 OBB::SimpleQuaternion::SimpleQuaternion(BVH_REAL a, BVH_REAL b, BVH_REAL c, BVH_REAL d) 00044 { 00045 data[0] = a; 00046 data[1] = b; 00047 data[2] = c; 00048 data[3] = d; 00049 } 00050 00051 void OBB::SimpleQuaternion::fromRotation(const Vec3f axis[3]) 00052 { 00053 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes 00054 // article "Quaternion Calculus and Fast Animation". 00055 00056 const int next[3] = {1, 2, 0}; 00057 00058 BVH_REAL trace = axis[0][0] + axis[1][1] + axis[2][2]; 00059 BVH_REAL root; 00060 00061 if(trace > 0.0) 00062 { 00063 // |w| > 1/2, may as well choose w > 1/2 00064 root = sqrt(trace + 1.0); // 2w 00065 data[0] = 0.5 * root; 00066 root = 0.5 / root; // 1/(4w) 00067 data[1] = (axis[1][2] - axis[2][1])*root; 00068 data[2] = (axis[2][0] - axis[0][2])*root; 00069 data[3] = (axis[0][1] - axis[1][0])*root; 00070 } 00071 else 00072 { 00073 // |w| <= 1/2 00074 int i = 0; 00075 if(axis[1][1] > axis[0][0]) 00076 { 00077 i = 1; 00078 } 00079 if(axis[2][2] > axis[i][i]) 00080 { 00081 i = 2; 00082 } 00083 int j = next[i]; 00084 int k = next[j]; 00085 00086 root = sqrt(axis[i][i] - axis[j][j] - axis[k][k] + 1.0); 00087 BVH_REAL* quat[3] = { &data[1], &data[2], &data[3] }; 00088 *quat[i] = 0.5 * root; 00089 root = 0.5 / root; 00090 data[0] = (axis[j][k] - axis[k][j]) * root; 00091 *quat[j] = (axis[i][j] + axis[j][i]) * root; 00092 *quat[k] = (axis[i][k] + axis[k][i]) * root; 00093 } 00094 } 00095 00096 void OBB::SimpleQuaternion::toRotation(Vec3f axis[3]) const 00097 { 00098 BVH_REAL twoX = 2.0*data[1]; 00099 BVH_REAL twoY = 2.0*data[2]; 00100 BVH_REAL twoZ = 2.0*data[3]; 00101 BVH_REAL twoWX = twoX*data[0]; 00102 BVH_REAL twoWY = twoY*data[0]; 00103 BVH_REAL twoWZ = twoZ*data[0]; 00104 BVH_REAL twoXX = twoX*data[1]; 00105 BVH_REAL twoXY = twoY*data[1]; 00106 BVH_REAL twoXZ = twoZ*data[1]; 00107 BVH_REAL twoYY = twoY*data[2]; 00108 BVH_REAL twoYZ = twoZ*data[2]; 00109 BVH_REAL twoZZ = twoZ*data[3]; 00110 00111 axis[0] = Vec3f(1.0 - (twoYY + twoZZ), twoXY + twoWZ, twoXZ - twoWY); 00112 axis[1] = Vec3f(twoXY - twoWZ, 1.0 - (twoXX + twoZZ), twoYZ + twoWX); 00113 axis[2] = Vec3f(twoXZ + twoWY, twoYZ - twoWX, 1.0 - (twoXX + twoYY)); 00114 } 00115 00116 BVH_REAL OBB::SimpleQuaternion::dot(const SimpleQuaternion& other) const 00117 { 00118 return data[0] * other.data[0] + data[1] * other.data[1] + data[2] * other.data[2] + data[3] * other.data[3]; 00119 } 00120 00121 OBB::SimpleQuaternion OBB::SimpleQuaternion::operator + (const SimpleQuaternion& other) const 00122 { 00123 return SimpleQuaternion(data[0] + other.data[0], data[1] + other.data[1], 00124 data[2] + other.data[2], data[3] + other.data[3]); 00125 } 00126 00127 OBB::SimpleQuaternion OBB::SimpleQuaternion::operator - () const 00128 { 00129 return SimpleQuaternion(-data[0], -data[1], -data[2], -data[3]); 00130 } 00131 00132 OBB::SimpleQuaternion OBB::SimpleQuaternion::operator * (BVH_REAL t) const 00133 { 00134 return SimpleQuaternion(data[0] * t, data[1] * t, data[2] * t, data[3] * t); 00135 } 00136 00137 bool OBB::overlap(const OBB& other) const 00138 { 00139 // compute what transform [R,T] that takes us from cs1 to cs2. 00140 // [R,T] = [R1,T1]'[R2,T2] = [R1',-R1'T][R2,T2] = [R1'R2, R1'(T2-T1)] 00141 // First compute the rotation part, then translation part 00142 Vec3f t = other.To - To; // T2 - T1 00143 Vec3f T(t.dot(axis[0]), t.dot(axis[1]), t.dot(axis[2])); // R1'(T2-T1) 00144 Vec3f R[3]; 00145 R[0] = Vec3f(axis[0].dot(other.axis[0]), axis[0].dot(other.axis[1]), axis[0].dot(other.axis[2])); 00146 R[1] = Vec3f(axis[1].dot(other.axis[0]), axis[1].dot(other.axis[1]), axis[1].dot(other.axis[2])); 00147 R[2] = Vec3f(axis[2].dot(other.axis[0]), axis[2].dot(other.axis[1]), axis[2].dot(other.axis[2])); 00148 00149 // R is row first 00150 return (obbDisjoint(R, T, extent, other.extent) == 0); 00151 } 00152 00153 00154 bool OBB::contain(const Vec3f& p) const 00155 { 00156 Vec3f local_p = p - To; 00157 BVH_REAL proj = local_p.dot(axis[0]); 00158 if((proj > extent[0]) || (proj < -extent[0])) 00159 return false; 00160 00161 proj = local_p.dot(axis[1]); 00162 if((proj > extent[1]) || (proj < -extent[1])) 00163 return false; 00164 00165 proj = local_p.dot(axis[2]); 00166 if((proj > extent[2]) || (proj < -extent[2])) 00167 return false; 00168 00169 return true; 00170 } 00171 00173 OBB& OBB::operator += (const Vec3f& p) 00174 { 00175 OBB bvp; 00176 bvp.To = p; 00177 bvp.axis[0] = axis[0]; 00178 bvp.axis[1] = axis[1]; 00179 bvp.axis[2] = axis[2]; 00180 bvp.extent = Vec3f(0, 0, 0); 00181 00182 *this += bvp; 00183 return *this; 00184 } 00185 00186 OBB OBB::operator + (const OBB& other) const 00187 { 00188 Vec3f center_diff = To - other.To; 00189 BVH_REAL max_extent = std::max(std::max(extent[0], extent[1]), extent[2]); 00190 BVH_REAL max_extent2 = std::max(std::max(other.extent[0], other.extent[1]), other.extent[2]); 00191 if(center_diff.length() > 2 * (max_extent + max_extent2)) 00192 { 00193 return merge_largedist(*this, other); 00194 } 00195 else 00196 { 00197 return merge_smalldist(*this, other); 00198 } 00199 } 00200 00201 00202 bool OBB::obbDisjoint(const Vec3f B[3], const Vec3f& T, const Vec3f& a, const Vec3f& b) 00203 { 00204 register BVH_REAL t, s; 00205 Vec3f Bf[3]; 00206 const BVH_REAL reps = 1e-6; 00207 00208 Bf[0] = abs(B[0]); 00209 Bf[1] = abs(B[1]); 00210 Bf[2] = abs(B[2]); 00211 00212 Vec3f reps_vec(reps, reps, reps); 00213 00214 Bf[0] += reps_vec; 00215 Bf[1] += reps_vec; 00216 Bf[2] += reps_vec; 00217 00218 Vec3f Bf_col[3] = {Vec3f(Bf[0][0], Bf[1][0], Bf[2][0]), 00219 Vec3f(Bf[0][1], Bf[1][1], Bf[2][1]), 00220 Vec3f(Bf[0][2], Bf[1][2], Bf[2][2])}; 00221 00222 Vec3f B_col[3] = {Vec3f(B[0][0], B[1][0], B[2][0]), 00223 Vec3f(B[0][1], B[1][1], B[2][1]), 00224 Vec3f(B[0][2], B[1][2], B[2][2])}; 00225 00226 00227 // if any of these tests are one-sided, then the polyhedra are disjoint 00228 00229 // A1 x A2 = A0 00230 t = ((T[0] < 0) ? -T[0] : T[0]); 00231 00232 if(t > (a[0] + b.dot(Bf[0]))) 00233 return true; 00234 00235 // B1 x B2 = B0 00236 s = T.dot(B_col[0]); 00237 t = ((s < 0) ? -s : s); 00238 00239 if(t > (b[0] + a.dot(Bf_col[0]))) 00240 return true; 00241 00242 // A2 x A0 = A1 00243 t = ((T[1] < 0) ? -T[1] : T[1]); 00244 00245 if(t > (a[1] + b.dot(Bf[1]))) 00246 return true; 00247 00248 // A0 x A1 = A2 00249 t =((T[2] < 0) ? -T[2] : T[2]); 00250 00251 if(t > (a[2] + b.dot(Bf[2]))) 00252 return true; 00253 00254 // B2 x B0 = B1 00255 s = T.dot(B_col[1]); 00256 t = ((s < 0) ? -s : s); 00257 00258 if(t > (b[1] + a.dot(Bf_col[1]))) 00259 return true; 00260 00261 // B0 x B1 = B2 00262 s = T.dot(B_col[2]); 00263 t = ((s < 0) ? -s : s); 00264 00265 if(t > (b[2] + a.dot(Bf_col[2]))) 00266 return true; 00267 00268 // A0 x B0 00269 s = T[2] * B[1][0] - T[1] * B[2][0]; 00270 t = ((s < 0) ? -s : s); 00271 00272 if(t > (a[1] * Bf[2][0] + a[2] * Bf[1][0] + 00273 b[1] * Bf[0][2] + b[2] * Bf[0][1])) 00274 return true; 00275 00276 // A0 x B1 00277 s = T[2] * B[1][1] - T[1] * B[2][1]; 00278 t = ((s < 0) ? -s : s); 00279 00280 if(t > (a[1] * Bf[2][1] + a[2] * Bf[1][1] + 00281 b[0] * Bf[0][2] + b[2] * Bf[0][0])) 00282 return true; 00283 00284 // A0 x B2 00285 s = T[2] * B[1][2] - T[1] * B[2][2]; 00286 t = ((s < 0) ? -s : s); 00287 00288 if(t > (a[1] * Bf[2][2] + a[2] * Bf[1][2] + 00289 b[0] * Bf[0][1] + b[1] * Bf[0][0])) 00290 return true; 00291 00292 // A1 x B0 00293 s = T[0] * B[2][0] - T[2] * B[0][0]; 00294 t = ((s < 0) ? -s : s); 00295 00296 if(t > (a[0] * Bf[2][0] + a[2] * Bf[0][0] + 00297 b[1] * Bf[1][2] + b[2] * Bf[1][1])) 00298 return true; 00299 00300 // A1 x B1 00301 s = T[0] * B[2][1] - T[2] * B[0][1]; 00302 t = ((s < 0) ? -s : s); 00303 00304 if(t > (a[0] * Bf[2][1] + a[2] * Bf[0][1] + 00305 b[0] * Bf[1][2] + b[2] * Bf[1][0])) 00306 return true; 00307 00308 // A1 x B2 00309 s = T[0] * B[2][2] - T[2] * B[0][2]; 00310 t = ((s < 0) ? -s : s); 00311 00312 if(t > (a[0] * Bf[2][2] + a[2] * Bf[0][2] + 00313 b[0] * Bf[1][1] + b[1] * Bf[1][0])) 00314 return true; 00315 00316 // A2 x B0 00317 s = T[1] * B[0][0] - T[0] * B[1][0]; 00318 t = ((s < 0) ? -s : s); 00319 00320 if(t > (a[0] * Bf[1][0] + a[1] * Bf[0][0] + 00321 b[1] * Bf[2][2] + b[2] * Bf[2][1])) 00322 return true; 00323 00324 // A2 x B1 00325 s = T[1] * B[0][1] - T[0] * B[1][1]; 00326 t = ((s < 0) ? -s : s); 00327 00328 if(t > (a[0] * Bf[1][1] + a[1] * Bf[0][1] + 00329 b[0] * Bf[2][2] + b[2] * Bf[2][0])) 00330 return true; 00331 00332 // A2 x B2 00333 s = T[1] * B[0][2] - T[0] * B[1][2]; 00334 t = ((s < 0) ? -s : s); 00335 00336 if(t > (a[0] * Bf[1][2] + a[1] * Bf[0][2] + 00337 b[0] * Bf[2][1] + b[1] * Bf[2][0])) 00338 return true; 00339 00340 return false; 00341 00342 /* 00343 register int r; 00344 00345 // if any of these tests are one-sided, then the polyhedra are disjoint 00346 r = 1; 00347 00348 // A1 x A2 = A0 00349 t = ((T[0] < 0) ? -T[0] : T[0]); 00350 00351 r &= (t <= 00352 (a[0] + b[0] * Bf[0][0] + b[1] * Bf[0][1] + b[2] * Bf[0][2])); 00353 if (!r) return 1; 00354 00355 // B1 x B2 = B0 00356 s = T[0]*B[0][0] + T[1]*B[1][0] + T[2]*B[2][0]; 00357 t = ((s < 0) ? -s : s); 00358 00359 r &= ( t <= 00360 (b[0] + a[0] * Bf[0][0] + a[1] * Bf[1][0] + a[2] * Bf[2][0])); 00361 if (!r) return 2; 00362 00363 // A2 x A0 = A1 00364 t = ((T[1] < 0) ? -T[1] : T[1]); 00365 00366 r &= ( t <= 00367 (a[1] + b[0] * Bf[1][0] + b[1] * Bf[1][1] + b[2] * Bf[1][2])); 00368 if (!r) return 3; 00369 00370 // A0 x A1 = A2 00371 t =((T[2] < 0) ? -T[2] : T[2]); 00372 00373 r &= ( t <= 00374 (a[2] + b[0] * Bf[2][0] + b[1] * Bf[2][1] + b[2] * Bf[2][2])); 00375 if (!r) return 4; 00376 00377 // B2 x B0 = B1 00378 s = T[0]*B[0][1] + T[1]*B[1][1] + T[2]*B[2][1]; 00379 t = ((s < 0) ? -s : s); 00380 00381 r &= ( t <= 00382 (b[1] + a[0] * Bf[0][1] + a[1] * Bf[1][1] + a[2] * Bf[2][1])); 00383 if (!r) return 5; 00384 00385 // B0 x B1 = B2 00386 s = T[0]*B[0][2] + T[1]*B[1][2] + T[2]*B[2][2]; 00387 t = ((s < 0) ? -s : s); 00388 00389 r &= ( t <= 00390 (b[2] + a[0] * Bf[0][2] + a[1] * Bf[1][2] + a[2] * Bf[2][2])); 00391 if (!r) return 6; 00392 00393 // A0 x B0 00394 s = T[2] * B[1][0] - T[1] * B[2][0]; 00395 t = ((s < 0) ? -s : s); 00396 00397 r &= ( t <= 00398 (a[1] * Bf[2][0] + a[2] * Bf[1][0] + 00399 b[1] * Bf[0][2] + b[2] * Bf[0][1])); 00400 if (!r) return 7; 00401 00402 // A0 x B1 00403 s = T[2] * B[1][1] - T[1] * B[2][1]; 00404 t = ((s < 0) ? -s : s); 00405 00406 r &= ( t <= 00407 (a[1] * Bf[2][1] + a[2] * Bf[1][1] + 00408 b[0] * Bf[0][2] + b[2] * Bf[0][0])); 00409 if (!r) return 8; 00410 00411 // A0 x B2 00412 s = T[2] * B[1][2] - T[1] * B[2][2]; 00413 t = ((s < 0) ? -s : s); 00414 00415 r &= ( t <= 00416 (a[1] * Bf[2][2] + a[2] * Bf[1][2] + 00417 b[0] * Bf[0][1] + b[1] * Bf[0][0])); 00418 if (!r) return 9; 00419 00420 // A1 x B0 00421 s = T[0] * B[2][0] - T[2] * B[0][0]; 00422 t = ((s < 0) ? -s : s); 00423 00424 r &= ( t <= 00425 (a[0] * Bf[2][0] + a[2] * Bf[0][0] + 00426 b[1] * Bf[1][2] + b[2] * Bf[1][1])); 00427 if (!r) return 10; 00428 00429 // A1 x B1 00430 s = T[0] * B[2][1] - T[2] * B[0][1]; 00431 t = ((s < 0) ? -s : s); 00432 00433 r &= ( t <= 00434 (a[0] * Bf[2][1] + a[2] * Bf[0][1] + 00435 b[0] * Bf[1][2] + b[2] * Bf[1][0])); 00436 if (!r) return 11; 00437 00438 // A1 x B2 00439 s = T[0] * B[2][2] - T[2] * B[0][2]; 00440 t = ((s < 0) ? -s : s); 00441 00442 r &= (t <= 00443 (a[0] * Bf[2][2] + a[2] * Bf[0][2] + 00444 b[0] * Bf[1][1] + b[1] * Bf[1][0])); 00445 if (!r) return 12; 00446 00447 // A2 x B0 00448 s = T[1] * B[0][0] - T[0] * B[1][0]; 00449 t = ((s < 0) ? -s : s); 00450 00451 r &= (t <= 00452 (a[0] * Bf[1][0] + a[1] * Bf[0][0] + 00453 b[1] * Bf[2][2] + b[2] * Bf[2][1])); 00454 if (!r) return 13; 00455 00456 // A2 x B1 00457 s = T[1] * B[0][1] - T[0] * B[1][1]; 00458 t = ((s < 0) ? -s : s); 00459 00460 r &= ( t <= 00461 (a[0] * Bf[1][1] + a[1] * Bf[0][1] + 00462 b[0] * Bf[2][2] + b[2] * Bf[2][0])); 00463 if (!r) return 14; 00464 00465 // A2 x B2 00466 s = T[1] * B[0][2] - T[0] * B[1][2]; 00467 t = ((s < 0) ? -s : s); 00468 00469 r &= ( t <= 00470 (a[0] * Bf[1][2] + a[1] * Bf[0][2] + 00471 b[0] * Bf[2][1] + b[1] * Bf[2][0])); 00472 if (!r) return 15; 00473 00474 return 0; // should equal 0 00475 */ 00476 } 00477 00478 00479 void OBB::computeVertices(Vec3f vertex[8]) const 00480 { 00481 Vec3f extAxis0 = axis[0] * extent[0]; 00482 Vec3f extAxis1 = axis[1] * extent[1]; 00483 Vec3f extAxis2 = axis[2] * extent[2]; 00484 00485 vertex[0] = To - extAxis0 - extAxis1 - extAxis2; 00486 vertex[1] = To + extAxis0 - extAxis1 - extAxis2; 00487 vertex[2] = To + extAxis0 + extAxis1 - extAxis2; 00488 vertex[3] = To - extAxis0 + extAxis1 - extAxis2; 00489 vertex[4] = To - extAxis0 - extAxis1 + extAxis2; 00490 vertex[5] = To + extAxis0 - extAxis1 + extAxis2; 00491 vertex[6] = To + extAxis0 + extAxis1 + extAxis2; 00492 vertex[7] = To - extAxis0 + extAxis1 + extAxis2; 00493 } 00494 00495 void OBB::getCovariance(Vec3f* ps, int n, Vec3f M[3]) 00496 { 00497 Vec3f S1; 00498 Vec3f S2[3]; 00499 00500 for(int i = 0; i < n; ++i) 00501 { 00502 Vec3f p = ps[i]; 00503 S1 += p; 00504 S2[0][0] += (p[0] * p[0]); 00505 S2[1][1] += (p[1] * p[1]); 00506 S2[2][2] += (p[2] * p[2]); 00507 S2[0][1] += (p[0] * p[1]); 00508 S2[0][2] += (p[0] * p[2]); 00509 S2[1][2] += (p[1] * p[2]); 00510 } 00511 00512 M[0][0] = S2[0][0] - S1[0]*S1[0] / n; 00513 M[1][1] = S2[1][1] - S1[1]*S1[1] / n; 00514 M[2][2] = S2[2][2] - S1[2]*S1[2] / n; 00515 M[0][1] = S2[0][1] - S1[0]*S1[1] / n; 00516 M[1][2] = S2[1][2] - S1[1]*S1[2] / n; 00517 M[0][2] = S2[0][2] - S1[0]*S1[2] / n; 00518 M[1][0] = M[0][1]; 00519 M[2][0] = M[0][2]; 00520 M[2][1] = M[1][2]; 00521 } 00522 00523 void OBB::Meigen(Vec3f a[3], BVH_REAL dout[3], Vec3f vout[3]) 00524 { 00525 int n = 3; 00526 int j, iq, ip, i; 00527 BVH_REAL tresh, theta, tau, t, sm, s, h, g, c; 00528 int nrot; 00529 BVH_REAL b[3]; 00530 BVH_REAL z[3]; 00531 BVH_REAL v[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; 00532 BVH_REAL d[3]; 00533 00534 for(ip = 0; ip < n; ++ip) 00535 { 00536 b[ip] = a[ip][ip]; 00537 d[ip] = a[ip][ip]; 00538 z[ip] = 0.0; 00539 } 00540 00541 nrot = 0; 00542 00543 for(i = 0; i < 50; ++i) 00544 { 00545 sm = 0.0; 00546 for(ip = 0; ip < n; ++ip) 00547 for(iq = ip + 1; iq < n; ++iq) 00548 sm += fabs(a[ip][iq]); 00549 if(sm == 0.0) 00550 { 00551 vout[0] = Vec3f(v[0][0], v[0][1], v[0][2]); 00552 vout[1] = Vec3f(v[1][0], v[1][1], v[1][2]); 00553 vout[2] = Vec3f(v[2][0], v[2][1], v[2][2]); 00554 dout[0] = d[0]; dout[1] = d[1]; dout[2] = d[2]; 00555 return; 00556 } 00557 00558 if(i < 3) tresh = 0.2 * sm / (n * n); 00559 else tresh = 0.0; 00560 00561 for(ip = 0; ip < n; ++ip) 00562 { 00563 for(iq= ip + 1; iq < n; ++iq) 00564 { 00565 g = 100.0 * fabs(a[ip][iq]); 00566 if(i > 3 && 00567 fabs(d[ip]) + g == fabs(d[ip]) && 00568 fabs(d[iq]) + g == fabs(d[iq])) 00569 a[ip][iq] = 0.0; 00570 else if(fabs(a[ip][iq]) > tresh) 00571 { 00572 h = d[iq] - d[ip]; 00573 if(fabs(h) + g == fabs(h)) t = (a[ip][iq]) / h; 00574 else 00575 { 00576 theta = 0.5 * h / (a[ip][iq]); 00577 t = 1.0 /(fabs(theta) + sqrt(1.0 + theta * theta)); 00578 if(theta < 0.0) t = -t; 00579 } 00580 c = 1.0 / sqrt(1 + t * t); 00581 s = t * c; 00582 tau = s / (1.0 + c); 00583 h = t * a[ip][iq]; 00584 z[ip] -= h; 00585 z[iq] += h; 00586 d[ip] -= h; 00587 d[iq] += h; 00588 a[ip][iq] = 0.0; 00589 for(j = 0; j < ip; ++j) { g = a[j][ip]; h = a[j][iq]; a[j][ip] = g - s * (h + g * tau); a[j][iq] = h + s * (g - h * tau); } 00590 for(j = ip + 1; j < iq; ++j) { g = a[ip][j]; h = a[j][iq]; a[ip][j] = g - s * (h + g * tau); a[j][iq] = h + s * (g - h * tau); } 00591 for(j = iq + 1; j < n; ++j) { g = a[ip][j]; h = a[iq][j]; a[ip][j] = g - s * (h + g * tau); a[iq][j] = h + s * (g - h * tau); } 00592 for(j = 0; j < n; ++j) { g = v[j][ip]; h = v[j][iq]; v[j][ip] = g - s * (h + g * tau); v[j][iq] = h + s * (g - h * tau); } 00593 nrot++; 00594 } 00595 } 00596 } 00597 for(ip = 0; ip < n; ++ip) 00598 { 00599 b[ip] += z[ip]; 00600 d[ip] = b[ip]; 00601 z[ip] = 0.0; 00602 } 00603 } 00604 00605 std::cerr << "eigen: too many iterations in Jacobi transform." << std::endl; 00606 00607 return; 00608 } 00609 00610 void OBB::getExtentAndCenter(Vec3f* ps, int n, Vec3f axis[3], Vec3f& center, Vec3f& extent) 00611 { 00612 BVH_REAL real_max = std::numeric_limits<BVH_REAL>::max(); 00613 BVH_REAL min_coord[3] = {real_max, real_max, real_max}; 00614 BVH_REAL max_coord[3] = {-real_max, -real_max, -real_max}; 00615 00616 for(int i = 0; i < n; ++i) 00617 { 00618 Vec3f v = ps[i]; 00619 BVH_REAL proj[3]; 00620 proj[0] = axis[0].dot(v); 00621 proj[1] = axis[1].dot(v); 00622 proj[2] = axis[2].dot(v); 00623 00624 for(int j = 0; j < 3; ++j) 00625 { 00626 if(proj[j] > max_coord[j]) max_coord[j] = proj[j]; 00627 if(proj[j] < min_coord[j]) min_coord[j] = proj[j]; 00628 } 00629 } 00630 00631 Vec3f o = Vec3f((max_coord[0] + min_coord[0]) / 2, 00632 (max_coord[1] + min_coord[1]) / 2, 00633 (max_coord[2] + min_coord[2]) / 2); 00634 00635 center = axis[0] * o[0] + axis[1] * o[1] + axis[2] * o[2]; 00636 00637 extent = Vec3f((max_coord[0] - min_coord[0]) / 2, 00638 (max_coord[1] - min_coord[1]) / 2, 00639 (max_coord[2] - min_coord[2]) / 2); 00640 00641 } 00642 00643 OBB OBB::merge_largedist(const OBB& b1, const OBB& b2) 00644 { 00645 OBB b; 00646 Vec3f vertex[16]; 00647 b1.computeVertices(vertex); 00648 b2.computeVertices(vertex + 8); 00649 Vec3f M[3]; 00650 Vec3f E[3]; 00651 BVH_REAL s[3] = {0, 0, 0}; 00652 Vec3f R[3]; 00653 00654 R[0] = b1.To - b2.To; 00655 R[0].normalize(); 00656 00657 Vec3f vertex_proj[16]; 00658 for(int i = 0; i < 16; ++i) 00659 vertex_proj[i] = vertex[i] - R[0] * vertex[i].dot(R[0]); 00660 00661 getCovariance(vertex_proj, 16, M); 00662 Meigen(M, s, E); 00663 00664 int min, mid, max; 00665 if (s[0] > s[1]) { max = 0; min = 1; } 00666 else { min = 0; max = 1; } 00667 if (s[2] < s[min]) { mid = min; min = 2; } 00668 else if (s[2] > s[max]) { mid = max; max = 2; } 00669 else { mid = 2; } 00670 00671 00672 R[1] = Vec3f(E[0][max], E[1][max], E[2][max]); 00673 R[2] = Vec3f(E[0][mid], E[1][mid], E[2][mid]); 00674 00675 // set obb axes 00676 b.axis[0] = R[0]; 00677 b.axis[1] = R[1]; 00678 b.axis[2] = R[2]; 00679 00680 // set obb centers and extensions 00681 Vec3f center, extent; 00682 getExtentAndCenter(vertex, 16, R, center, extent); 00683 00684 b.To = center; 00685 b.extent = extent; 00686 00687 return b; 00688 } 00689 00690 OBB OBB::merge_smalldist(const OBB& b1, const OBB& b2) 00691 { 00692 OBB b; 00693 b.To = (b1.To + b2.To) * 0.5; 00694 SimpleQuaternion q0, q1; 00695 q0.fromRotation(b1.axis); 00696 q1.fromRotation(b2.axis); 00697 if(q0.dot(q1) < 0) 00698 q1 = -q1; 00699 00700 SimpleQuaternion q = q0 + q1; 00701 BVH_REAL inv_length = 1.0 / sqrt(q.dot(q)); 00702 q = q * inv_length; 00703 q.toRotation(b.axis); 00704 00705 00706 Vec3f vertex[8], diff; 00707 BVH_REAL real_max = std::numeric_limits<BVH_REAL>::max(); 00708 Vec3f pmin(real_max, real_max, real_max); 00709 Vec3f pmax(-real_max, -real_max, -real_max); 00710 00711 b1.computeVertices(vertex); 00712 for(int i = 0; i < 8; ++i) 00713 { 00714 diff = vertex[i] - b.To; 00715 for(int j = 0; j < 3; ++j) 00716 { 00717 BVH_REAL dot = diff.dot(b.axis[j]); 00718 if(dot > pmax[j]) 00719 pmax[j] = dot; 00720 else if(dot < pmin[j]) 00721 pmin[j] = dot; 00722 } 00723 } 00724 00725 b2.computeVertices(vertex); 00726 for(int i = 0; i < 8; ++i) 00727 { 00728 diff = vertex[i] - b.To; 00729 for(int j = 0; j < 3; ++j) 00730 { 00731 BVH_REAL dot = diff.dot(b.axis[j]); 00732 if(dot > pmax[j]) 00733 pmax[j] = dot; 00734 else if(dot < pmin[j]) 00735 pmin[j] = dot; 00736 } 00737 } 00738 00739 for(int j = 0; j < 3; ++j) 00740 { 00741 b.To += (b.axis[j] * (0.5 * (pmax[j] + pmin[j]))); 00742 b.extent[j] = 0.5 * (pmax[j] - pmin[j]); 00743 } 00744 00745 return b; 00746 } 00747 00748 // R is row first 00749 bool overlap(const Vec3f R0[3], const Vec3f& T0, const OBB& b1, const OBB& b2) 00750 { 00751 // R0 R2 00752 Vec3f Rtemp_col[3]; 00753 Rtemp_col[0] = Vec3f(R0[0].dot(b2.axis[0]), R0[1].dot(b2.axis[0]), R0[2].dot(b2.axis[0])); 00754 Rtemp_col[1] = Vec3f(R0[0].dot(b2.axis[1]), R0[1].dot(b2.axis[1]), R0[2].dot(b2.axis[1])); 00755 Rtemp_col[2] = Vec3f(R0[0].dot(b2.axis[2]), R0[1].dot(b2.axis[2]), R0[2].dot(b2.axis[2])); 00756 00757 // R1'Rtemp 00758 Vec3f R[3]; 00759 R[0] = Vec3f(b1.axis[0].dot(Rtemp_col[0]), b1.axis[0].dot(Rtemp_col[1]), b1.axis[0].dot(Rtemp_col[2])); 00760 R[1] = Vec3f(b1.axis[1].dot(Rtemp_col[0]), b1.axis[1].dot(Rtemp_col[1]), b1.axis[1].dot(Rtemp_col[2])); 00761 R[2] = Vec3f(b1.axis[2].dot(Rtemp_col[0]), b1.axis[2].dot(Rtemp_col[1]), b1.axis[2].dot(Rtemp_col[2])); 00762 00763 Vec3f Ttemp = Vec3f(R0[0].dot(b2.To), R0[1].dot(b2.To), R0[2].dot(b2.To)) + T0 - b1.To; 00764 00765 Vec3f T = Vec3f(Ttemp.dot(b1.axis[0]), Ttemp.dot(b1.axis[1]), Ttemp.dot(b1.axis[2])); 00766 00767 return (OBB::obbDisjoint(R, T, b1.extent, b2.extent) == 0); 00768 } 00769 00770 }