00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037 #ifndef COLLISION_CHECKING_COLLISION_GEOM_H
00038 #define COLLISION_CHECKING_COLLISION_GEOM_H
00039
00040 #include <fstream>
00041 #include <vector>
00042 #include <boost/math/constants/constants.hpp>
00043 #include <LinearMath/btTransform.h>
00044 #include "collision_checking/collision.h"
00045
00046 namespace collision_checking
00047 {
00048
00049 inline void saveOBjFile(const std::string& name, const std::vector<Vec3f>& points, const std::vector<Triangle>& tri_indices)
00050 {
00051 std::ofstream file(name.c_str());
00052 file << points.size() << " " << tri_indices.size() << std::endl;
00053 for(unsigned int i = 0; i < points.size(); ++i)
00054 {
00055 file << "v " << points[i][0] << " " << points[i][1] << " " << points[i][2] << std::endl;
00056 }
00057 for(unsigned int i = 0; i < tri_indices.size(); ++i)
00058 {
00059 file << "f " << tri_indices[i][0] + 1 << " " << tri_indices[i][1] + 1 << " " << tri_indices[i][2] + 1 << std::endl;
00060 }
00061 }
00062
00063 struct CollisionGeom
00064 {
00065 CollisionGeom()
00066 {
00067 ccd = false;
00068 t1.setIdentity();
00069 t2.setIdentity();
00070 }
00071
00072 virtual ~CollisionGeom()
00073 {}
00074
00075 virtual BVH_CollideResult collide(CollisionGeom* other, int num_contacts = 0) { BVH_CollideResult res; return res; }
00076
00077 virtual void applyTransform(const btTransform& pose, bool refit = true, bool bottomup = true)
00078 {
00079 t2 = t1;
00080 t1 = pose;
00081 }
00082
00083 virtual void computeAABB() {}
00084
00085 bool ccd;
00086 btTransform t1;
00087 btTransform t2;
00088
00089 AABB aabb;
00090 };
00091
00092
00093
00094 template<typename BV>
00095 struct CollisionMesh;
00096 template<typename BV>
00097 CollisionMesh<BV>* makeMesh(const std::vector<Vec3f>& points, const std::vector<Triangle>& tri_indices);
00098 template<typename BV>
00099 CollisionMesh<BV>* makeBox(double a, double b, double c);
00100 template<typename BV>
00101 CollisionMesh<BV>* makeCylinder(double r, double h, unsigned int tot = 16);
00102 template<typename BV>
00103 CollisionMesh<BV>* makeSphere(double r, unsigned int seg = 16, unsigned int ring = 16);
00104
00105 template<typename BV>
00106 struct CollisionMesh : public CollisionGeom
00107 {
00108 private:
00109 CollisionMesh() : CollisionGeom()
00110 {
00111 }
00112
00113 public:
00114 friend CollisionMesh<BV>* makeMesh<>(const std::vector<Vec3f>& points, const std::vector<Triangle>& tri_indices);
00115 friend CollisionMesh<BV>* makeBox<>(double a, double b, double c);
00116 friend CollisionMesh<BV>* makeCylinder<>(double r, double h, unsigned int tot);
00117 friend CollisionMesh<BV>* makeSphere<>(double r, unsigned int seg, unsigned int ring);
00118
00119
00120 BVH_CollideResult collide(CollisionGeom* other, int num_max_contacts = 0)
00121 {
00122 BVH_CollideResult res;
00123 res.num_max_contacts = num_max_contacts;
00124 CollisionMesh<BV>* othermesh = dynamic_cast<CollisionMesh<BV>* >(other);
00125 if(othermesh)
00126 {
00127 collision_checking::collide(model, othermesh->model, &res);
00128 }
00129
00130 return res;
00131 }
00132
00133 void applyTransform(const btTransform& pose, bool refit = false, bool bottomup = true)
00134 {
00135 t2 = t1;
00136 t1 = pose;
00137
00138 std::vector<Vec3f> points;
00139 for(int i = 0; i < model.num_vertices; ++i)
00140 {
00141 const Vec3f& p = model.vertices[i];
00142 btVector3 v(p[0], p[1], p[2]);
00143 v = pose * v;
00144 points[i] = Vec3f(v.x(), v.y(), v.z());
00145 }
00146
00147 if(ccd)
00148 {
00149 model.beginUpdateModel();
00150 model.updateSubModel(points);
00151 model.endUpdateModel(refit, bottomup);
00152 }
00153 else
00154 {
00155 model.beginReplaceModel();
00156 model.replaceSubModel(points);
00157 model.endReplaceModel(refit, bottomup);
00158 }
00159
00160 computeAABB();
00161 }
00162
00163 void computeAABB()
00164 {
00165 AABB aabb_;
00166 if(ccd)
00167 {
00168 for(int i = 0; i < model.num_vertices; ++i)
00169 {
00170 aabb_ += model.vertices[i];
00171 aabb_ += model.prev_vertices[i];
00172 }
00173 }
00174 else
00175 {
00176 for(int i = 0; i < model.num_vertices; ++i)
00177 {
00178 aabb_ += model.vertices[i];
00179 }
00180 }
00181
00182 aabb = aabb_;
00183 }
00184
00185
00186 BVHModel<BV> model;
00187 };
00188
00189
00191 template<>
00192 struct CollisionMesh<OBB> : public CollisionGeom
00193 {
00194 private:
00195 CollisionMesh() : CollisionGeom()
00196 {
00197 }
00198
00199 public:
00200 friend CollisionMesh<OBB>* makeMesh<>(const std::vector<Vec3f>& points, const std::vector<Triangle>& tri_indices);
00201 friend CollisionMesh<OBB>* makeBox<>(double a, double b, double c);
00202 friend CollisionMesh<OBB>* makeCylinder<>(double r, double h, unsigned int tot);
00203 friend CollisionMesh<OBB>* makeSphere<>(double r, unsigned int seg, unsigned int ring);
00204
00205
00206 BVH_CollideResult collide(CollisionGeom* other, int num_max_contacts = 0)
00207 {
00208 BVH_CollideResult res;
00209 res.num_max_contacts = num_max_contacts;
00210 CollisionMesh<OBB>* othermesh = dynamic_cast<CollisionMesh<OBB>* >(other);
00211 if(othermesh)
00212 {
00213 Vec3f R1[3];
00214 Vec3f R2[3];
00215 Vec3f T1;
00216 Vec3f T2;
00217 btVector3 t = t1.getOrigin();
00218 T1 = Vec3f(t.x(), t.y(), t.z());
00219 btMatrix3x3 r = t1.getBasis();
00220 for(int i = 0; i < 3; ++i)
00221 R1[i] = Vec3f(r[i].x(), r[i].y(), r[i].z());
00222
00223 t = othermesh->t1.getOrigin();
00224 T2 = Vec3f(t.x(), t.y(), t.z());
00225 r = othermesh->t1.getBasis();
00226 for(int i = 0; i < 3; ++i)
00227 R2[i] = Vec3f(r[i].x(), r[i].y(), r[i].z());
00228
00229 collision_checking::collide(model, R1, T1, othermesh->model, R2, T2, &res);
00230 }
00231
00232 return res;
00233 }
00234
00235 void applyTransform(const btTransform& pose, bool refit = true, bool bottomup = true)
00236 {
00237 t2 = t1;
00238 t1 = pose;
00239
00240 computeAABB();
00241 }
00242
00243 void computeAABB()
00244 {
00245 AABB aabb_;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 if(ccd)
00276 {
00277 BVNode<OBB>* obb = model.bvs;
00278 Vec3f p;
00279 btVector3 v;
00280 btVector3 v1;
00281
00282 Vec3f& axis0 = obb->bv.axis[0];
00283 Vec3f& axis1 = obb->bv.axis[1];
00284 Vec3f& axis2 = obb->bv.axis[2];
00285 Vec3f& To = obb->bv.To;
00286 Vec3f& extent = obb->bv.extent;
00287
00288 p = To + axis0 * extent[0] + axis1 * extent[1] + axis2 * extent[2];
00289 v = btVector3(p[0], p[1], p[2]);
00290 v1 = t1 * v;
00291 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00292 v1 = t2 * v;
00293 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00294
00295 p = To + axis0 * extent[0] + axis1 * extent[1] + axis2 * (-extent[2]);
00296 v = btVector3(p[0], p[1], p[2]);
00297 v1 = t1 * v;
00298 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00299 v1 = t2 * v;
00300 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00301
00302 p = To + axis0 * extent[0] + axis1 * (-extent[1]) + axis2 * extent[2];
00303 v = btVector3(p[0], p[1], p[2]);
00304 v1 = t1 * v;
00305 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00306 v1 = t2 * v;
00307 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00308
00309 p = To + axis0 * extent[0] + axis1 * (-extent[1]) + axis2 * (-extent[2]);
00310 v = btVector3(p[0], p[1], p[2]);
00311 v1 = t1 * v;
00312 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00313 v1 = t2 * v;
00314 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00315
00316 p = To + axis0 * (-extent[0]) + axis1 * extent[1] + axis2 * extent[2];
00317 v = btVector3(p[0], p[1], p[2]);
00318 v1 = t1 * v;
00319 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00320 v1 = t2 * v;
00321 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00322
00323 p = To + axis0 * (-extent[0]) + axis1 * extent[1] + axis2 * (-extent[2]);
00324 v = btVector3(p[0], p[1], p[2]);
00325 v1 = t1 * v;
00326 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00327 v1 = t2 * v;
00328 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00329
00330 p = To + axis0 * (-extent[0]) + axis1 * (-extent[1]) + axis2 * extent[2];
00331 v = btVector3(p[0], p[1], p[2]);
00332 v1 = t1 * v;
00333 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00334 v1 = t2 * v;
00335 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00336
00337 p = To + axis0 * (-extent[0]) + axis1 * (-extent[1]) + axis2 * (-extent[2]);
00338 v = btVector3(p[0], p[1], p[2]);
00339 v1 = t1 * v;
00340 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00341 v1 = t2 * v;
00342 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00343 }
00344 else
00345 {
00346 BVNode<OBB>* obb = model.bvs;
00347 Vec3f p;
00348 btVector3 v;
00349 btVector3 v1;
00350
00351 Vec3f& axis0 = obb->bv.axis[0];
00352 Vec3f& axis1 = obb->bv.axis[1];
00353 Vec3f& axis2 = obb->bv.axis[2];
00354 Vec3f& To = obb->bv.To;
00355 Vec3f& extent = obb->bv.extent;
00356
00357 p = To + axis0 * extent[0] + axis1 * extent[1] + axis2 * extent[2];
00358 v = btVector3(p[0], p[1], p[2]);
00359 v1 = t1 * v;
00360 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00361
00362 p = To + axis0 * extent[0] + axis1 * extent[1] + axis2 * (-extent[2]);
00363 v = btVector3(p[0], p[1], p[2]);
00364 v1 = t1 * v;
00365 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00366
00367 p = To + axis0 * extent[0] + axis1 * (-extent[1]) + axis2 * extent[2];
00368 v = btVector3(p[0], p[1], p[2]);
00369 v1 = t1 * v;
00370 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00371
00372 p = To + axis0 * extent[0] + axis1 * (-extent[1]) + axis2 * (-extent[2]);
00373 v = btVector3(p[0], p[1], p[2]);
00374 v1 = t1 * v;
00375 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00376
00377 p = To + axis0 * (-extent[0]) + axis1 * extent[1] + axis2 * extent[2];
00378 v = btVector3(p[0], p[1], p[2]);
00379 v1 = t1 * v;
00380 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00381
00382 p = To + axis0 * (-extent[0]) + axis1 * extent[1] + axis2 * (-extent[2]);
00383 v = btVector3(p[0], p[1], p[2]);
00384 v1 = t1 * v;
00385 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00386
00387 p = To + axis0 * (-extent[0]) + axis1 * (-extent[1]) + axis2 * extent[2];
00388 v = btVector3(p[0], p[1], p[2]);
00389 v1 = t1 * v;
00390 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00391
00392 p = To + axis0 * (-extent[0]) + axis1 * (-extent[1]) + axis2 * (-extent[2]);
00393 v = btVector3(p[0], p[1], p[2]);
00394 v1 = t1 * v;
00395 aabb_ += Vec3f(v1.x(), v1.y(), v1.z());
00396 }
00397
00398 aabb = aabb_;
00399 }
00400
00401 BVHModel<OBB> model;
00402 };
00403
00404
00405 template<typename BV>
00406 inline CollisionMesh<BV>* makeMesh(const std::vector<Vec3f>& points, const std::vector<Triangle>& tri_indices)
00407 {
00408 CollisionMesh<BV>* m = new CollisionMesh<BV>;
00409 m->model.beginModel();
00410 m->model.addSubModel(points, tri_indices);
00411 m->model.endModel();
00412 m->computeAABB();
00413
00414 return m;
00415 }
00416
00417 template<typename BV>
00418 inline CollisionMesh<BV>* makeBox(double a, double b, double c)
00419 {
00420 std::vector<Vec3f> points(8);
00421 std::vector<Triangle> tri_indices(12);
00422 points[0] = Vec3f(0.5 * a, -0.5 * b, 0.5 * c);
00423 points[1] = Vec3f(0.5 * a, 0.5 * b, 0.5 * c);
00424 points[2] = Vec3f(-0.5 * a, 0.5 * b, 0.5 * c);
00425 points[3] = Vec3f(-0.5 * a, -0.5 * b, 0.5 * c);
00426 points[4] = Vec3f(0.5 * a, -0.5 * b, -0.5 * c);
00427 points[5] = Vec3f(0.5 * a, 0.5 * b, -0.5 * c);
00428 points[6] = Vec3f(-0.5 * a, 0.5 * b, -0.5 * c);
00429 points[7] = Vec3f(-0.5 * a, -0.5 * b, -0.5 * c);
00430
00431 tri_indices[0] = Triangle(0, 4, 1);
00432 tri_indices[1] = Triangle(1, 4, 5);
00433 tri_indices[2] = Triangle(2, 5, 3);
00434 tri_indices[3] = Triangle(3, 6, 7);
00435 tri_indices[4] = Triangle(3, 0, 2);
00436 tri_indices[5] = Triangle(2, 0, 1);
00437 tri_indices[6] = Triangle(6, 5, 7);
00438 tri_indices[7] = Triangle(7, 5, 4);
00439 tri_indices[8] = Triangle(1, 5, 2);
00440 tri_indices[9] = Triangle(2, 5, 6);
00441 tri_indices[10] = Triangle(3, 7, 0);
00442 tri_indices[11] = Triangle(0, 7, 4);
00443
00444
00445 CollisionMesh<BV>* m = new CollisionMesh<BV>;
00446 m->model.beginModel();
00447 m->model.addSubModel(points, tri_indices);
00448 m->model.endModel();
00449 m->computeAABB();
00450
00451 return m;
00452 }
00453
00454 template<typename BV>
00455 inline CollisionMesh<BV>* makeCylinder(double r, double h, unsigned int tot)
00456 {
00457 std::vector<Vec3f> points;
00458 std::vector<Triangle> tri_indices;
00459
00460 double phi, phid;
00461 const double pi = boost::math::constants::pi<double>();
00462 phid = pi * 2 / tot;
00463 phi = 0;
00464
00465 double circle_edge = phid * r;
00466
00467 unsigned int h_num = 1;
00468 double hd = h / h_num;
00469
00470 for(unsigned int i = 0; i < tot; ++i)
00471 points.push_back(Vec3f(r * cos(phi + phid * i), r * sin(phi + phid * i), h / 2));
00472
00473 for(unsigned int i = 0; i < h_num - 1; ++i)
00474 {
00475 for(unsigned int j = 0; j < tot; ++j)
00476 {
00477 points.push_back(Vec3f(r * cos(phi + phid * j), r * sin(phi + phid * j), h / 2 - (i + 1) * hd));
00478 }
00479 }
00480
00481 for(unsigned int i = 0; i < tot; ++i)
00482 points.push_back(Vec3f(r * cos(phi + phid * i), r * sin(phi + phid * i), - h / 2));
00483
00484 points.push_back(Vec3f(0, 0, h / 2));
00485 points.push_back(Vec3f(0, 0, -h / 2));
00486
00487 for(unsigned int i = 0; i < tot; ++i)
00488 {
00489 Triangle tmp((h_num + 1) * tot, i, ((i == tot - 1) ? 0 : (i + 1)));
00490 tri_indices.push_back(tmp);
00491 }
00492
00493 for(unsigned int i = 0; i < tot; ++i)
00494 {
00495 Triangle tmp((h_num + 1) * tot + 1, h_num * tot + i, h_num * tot + ((i == tot - 1) ? 0 : (i + 1)));
00496 tri_indices.push_back(tmp);
00497 }
00498
00499 for(unsigned int i = 0; i < h_num; ++i)
00500 {
00501 for(unsigned int j = 0; j < tot; ++j)
00502 {
00503 int a, b, c, d;
00504 a = j;
00505 b = (j == tot - 1) ? 0 : (j + 1);
00506 c = j + tot;
00507 d = (j == tot - 1) ? tot : (j + 1 + tot);
00508
00509 int start = i * tot;
00510 tri_indices.push_back(Triangle(start + b, start + a, start + c));
00511 tri_indices.push_back(Triangle(start + b, start + c, start + d));
00512 }
00513 }
00514
00515 CollisionMesh<BV>* m = new CollisionMesh<BV>;
00516 m->model.beginModel();
00517 m->model.addSubModel(points, tri_indices);
00518 m->model.endModel();
00519 m->computeAABB();
00520
00521 return m;
00522 }
00523
00524 template<typename BV>
00525 inline CollisionMesh<BV>* makeSphere(double r, unsigned int seg, unsigned int ring)
00526 {
00527 std::vector<Vec3f> points;
00528 std::vector<Triangle> tri_indices;
00529
00530 double phi, phid;
00531 const double pi = boost::math::constants::pi<double>();
00532 phid = pi * 2 / seg;
00533 phi = 0;
00534
00535 double theta, thetad;
00536 thetad = pi / (ring + 1);
00537 theta = 0;
00538
00539 for(unsigned int i = 0; i < ring; ++i)
00540 {
00541 double theta_ = theta + thetad * (i + 1);
00542 for(unsigned int j = 0; j < seg; ++j)
00543 {
00544 points.push_back(Vec3f(r * sin(theta_) * cos(phi + j * phid), r * sin(theta_) * sin(phi + j * phid), r * cos(theta_)));
00545 }
00546 }
00547 points.push_back(Vec3f(0, 0, r));
00548 points.push_back(Vec3f(0, 0, -r));
00549
00550 for(unsigned int i = 0; i < ring - 1; ++i)
00551 {
00552 for(unsigned int j = 0; j < seg; ++j)
00553 {
00554 unsigned int a, b, c, d;
00555 a = i * seg + j;
00556 b = (j == seg - 1) ? (i * seg) : (i * seg + j + 1);
00557 c = (i + 1) * seg + j;
00558 d = (j == seg - 1) ? ((i + 1) * seg) : ((i + 1) * seg + j + 1);
00559 tri_indices.push_back(Triangle(a, c, b));
00560 tri_indices.push_back(Triangle(b, c, d));
00561 }
00562 }
00563
00564 for(unsigned int j = 0; j < seg; ++j)
00565 {
00566 unsigned int a, b;
00567 a = j;
00568 b = (j == seg - 1) ? 0 : (j + 1);
00569 tri_indices.push_back(Triangle(ring * seg, a, b));
00570
00571 a = (ring - 1) * seg + j;
00572 b = (j == seg - 1) ? (ring - 1) * seg : ((ring - 1) * seg + j + 1);
00573 tri_indices.push_back(Triangle(a, ring * seg + 1, b));
00574 }
00575
00576 CollisionMesh<BV>* m = new CollisionMesh<BV>;
00577 m->model.beginModel();
00578 m->model.addSubModel(points, tri_indices);
00579 m->model.endModel();
00580 m->computeAABB();
00581
00582 return m;
00583 }
00584
00585
00586
00587
00588 }
00589
00590 #endif