11/*
22A sphere falling and hitting the ground.
3+
4+ It may bounce up a few times depending on the restitution coefficients.
5+
6+ Collisions are detected and printed to output. Releated threads:
7+
8+ - http://stackoverflow.com/questions/11175694/bullet-physics-simplest-collision-example
9+ - http://stackoverflow.com/questions/9117932/detecting-collisions-with-bullet
10+ - http://gamedev.stackexchange.com/questions/22442/how-get-collision-callback-of-two-specific-objects-using-bullet-physics
11+ - http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers
312*/
413
514#include < cstdio>
615#include < cstdlib>
16+ #include < vector>
717
818#include < btBulletDynamicsCommon.h>
919
@@ -18,35 +28,31 @@ constexpr float groundRestitution = 0.9f;
1828constexpr float sphereRestitution = 0 .9f ;
1929constexpr int maxNPoints = 500 ;
2030
21- static void myTickCallback (btDynamicsWorld *world, btScalar timeStep) {
22- bool hadCollision = false ;
31+ std::vector<btVector3> collisions;
32+ void myTickCallback (btDynamicsWorld *dynamicsWorld, btScalar timeStep) {
33+ collisions.clear ();
34+ int numManifolds = dynamicsWorld->getDispatcher ()->getNumManifolds ();
2335 for (int i = 0 ; i < numManifolds; i++) {
24- btPersistentManifold* contactManifold = dynamicsWorld->getDispatcher ()->getManifoldByIndexInternal (i);
25- const btCollisionObject* obA = static_cast <const btCollisionObject*>(contactManifold->getBody0 ());
26- const btCollisionObject* obB = static_cast <const btCollisionObject*>(contactManifold->getBody1 ());
36+ btPersistentManifold *contactManifold = dynamicsWorld->getDispatcher ()->getManifoldByIndexInternal (i);
37+ // TODO those are unused. What can be done with them?
38+ // I think they are the same objects as those in the main loop
39+ // dynamicsWorld->getCollisionObjectArray() and we could compare
40+ // the pointers to see which object collided with which.
41+ {
42+ const btCollisionObject *objA = contactManifold->getBody0 ();
43+ const btCollisionObject *objB = contactManifold->getBody1 ();
44+ }
2745 int numContacts = contactManifold->getNumContacts ();
2846 for (int j = 0 ; j < numContacts; j++) {
29- if (!hadCollision)
30- std::printf (" 1 " );
31- hadCollision = true ;
3247 btManifoldPoint& pt = contactManifold->getContactPoint (j);
33- if (pt.getDistance () < 0 .0f ) {
34- const btVector3& ptA = pt.getPositionWorldOnA ();
35- const btVector3& ptB = pt.getPositionWorldOnB ();
36- const btVector3& normalOnB = pt.m_normalWorldOnB ;
37- std::printf (
38- PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " "
39- PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " "
40- PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " " ,
41- ptA.getX (), ptA.getY (), ptA.getZ (),
42- ptB.getX (), ptB.getY (), ptB.getZ (),
43- normalOnB.getX (), normalOnB.getY (), normalOnB.getZ ());
44- }
48+ const btVector3& ptA = pt.getPositionWorldOnA ();
49+ const btVector3& ptB = pt.getPositionWorldOnB ();
50+ const btVector3& normalOnB = pt.m_normalWorldOnB ;
51+ collisions.push_back (ptA);
52+ collisions.push_back (ptB);
53+ collisions.push_back (normalOnB);
4554 }
4655 }
47- if (!hadCollision)
48- std::printf (" 0 " );
49- puts (" " );
5056}
5157
5258int main () {
@@ -66,20 +72,17 @@ int main() {
6672 // Ground.
6773 {
6874 btTransform groundTransform;
69-
7075 groundTransform.setIdentity ();
7176 groundTransform.setOrigin (btVector3 (0 , 0 , 0 ));
72-
7377 btCollisionShape* groundShape;
7478#if 1
75- // x / z plane.
76- // TODO: what is the planeConstant (second argument)?
77- // Looks like the displacement from the origin.
79+ // x / z plane at y = -1.
7880 groundShape = new btStaticPlaneShape (btVector3 (0 , 1 , 0 ), -1 );
7981#else
8082 // A cube of width 10 at y = -6.
8183 // Does not fall because we won't call:
8284 // colShape->calculateLocalInertia
85+ // TODO: remove this from this example into a collision shape example.
8386 groundTransform.setOrigin(btVector3(0, -6, 0));
8487 groundShape = new btBoxShape(
8588 btVector3(btScalar(5.0), btScalar(5.0), btScalar(5.0)));
@@ -113,7 +116,7 @@ int main() {
113116 // Main loop.
114117 std::printf (" step body x y z collision a b normal\n " );
115118 for (i = 0 ; i < maxNPoints; ++i) {
116- dynamicsWorld->stepSimulation (timeStep, 10 );
119+ dynamicsWorld->stepSimulation (timeStep);
117120 for (j = dynamicsWorld->getNumCollisionObjects () - 1 ; j >= 0 ; --j) {
118121 btCollisionObject *obj = dynamicsWorld->getCollisionObjectArray ()[j];
119122 btRigidBody *body = btRigidBody::upcast (obj);
@@ -130,7 +133,20 @@ int main() {
130133 float (origin.getX ()),
131134 float (origin.getY ()),
132135 float (origin.getZ ()));
133- int numManifolds = dynamicsWorld->getDispatcher ()->getNumManifolds ();
136+ if (collisions.empty ()) {
137+ std::printf (" 0 " );
138+ } else {
139+ std::printf (" 1 " );
140+ // Yes, this is getting reprinted for all bodies when collisions happen.
141+ // It's just a quick and dirty way to visualize it, should be outside
142+ // of this loop normally.
143+ for (auto & v : collisions) {
144+ std::printf (
145+ PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " " ,
146+ v.getX (), v.getY (), v.getZ ());
147+ }
148+ }
149+ puts (" " );
134150 }
135151 }
136152
0 commit comments