11/*
2- A sphere falling and hitting the ground.
2+ Drop an object to a planar ground.
33
44It may bounce up a few times depending on the restitution coefficients.
55
6- Collisions are detected and printed to output . Releated threads:
6+ Collisions are detected and printed to stdout . Releated threads:
77
88- http://stackoverflow.com/questions/11175694/bullet-physics-simplest-collision-example
99- http://stackoverflow.com/questions/9117932/detecting-collisions-with-bullet
1010- http://gamedev.stackexchange.com/questions/22442/how-get-collision-callback-of-two-specific-objects-using-bullet-physics
1111- http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Collision_Callbacks_and_Triggers
12+
13+ Derived from gravity.cpp
1214*/
1315
1416#include < cstdio>
1517#include < cstdlib>
18+ #include < map>
1619#include < vector>
1720
1821#include < btBulletDynamicsCommon.h>
1922
2023#define PRINTF_FLOAT " %7.3f"
2124
2225constexpr float gravity = -10 .0f ;
26+ // How inclined the ground plane is towards +x.
27+ constexpr float groundXNormal = 0 .0f ;
2328constexpr float initialY = 10 .0f ;
2429constexpr float timeStep = 1 .0f / 60 .0f ;
2530// TODO some combinations of coefficients smaller than 1.0
2631// make the ball go up higher / not lose height. Why?
2732constexpr float groundRestitution = 0 .9f ;
28- constexpr float sphereRestitution = 0 .9f ;
33+ constexpr float objectRestitution = 0 .9f ;
2934constexpr int maxNPoints = 500 ;
3035
31- std::vector<btVector3> collisions ;
36+ std::map< const btCollisionObject*,std:: vector<btManifoldPoint*>> objectsCollisions ;
3237void myTickCallback (btDynamicsWorld *dynamicsWorld, btScalar timeStep) {
33- collisions .clear ();
38+ objectsCollisions .clear ();
3439 int numManifolds = dynamicsWorld->getDispatcher ()->getNumManifolds ();
3540 for (int i = 0 ; i < numManifolds; i++) {
3641 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- }
42+ auto *objA = contactManifold->getBody0 ();
43+ auto *objB = contactManifold->getBody1 ();
44+ auto & collisionsA = objectsCollisions[objA];
45+ auto & collisionsB = objectsCollisions[objB];
4546 int numContacts = contactManifold->getNumContacts ();
4647 for (int j = 0 ; j < numContacts; j++) {
4748 btManifoldPoint& pt = contactManifold->getContactPoint (j);
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);
49+ collisionsA.push_back (&pt);
50+ collisionsB.push_back (&pt);
5451 }
5552 }
5653}
@@ -77,7 +74,7 @@ int main() {
7774 btCollisionShape* groundShape;
7875#if 1
7976 // x / z plane at y = -1.
80- groundShape = new btStaticPlaneShape (btVector3 (0 , 1 , 0 ), -1 );
77+ groundShape = new btStaticPlaneShape (btVector3 (groundXNormal , 1 , 0 ), -1 );
8178#else
8279 // A cube of width 10 at y = -6.
8380 // Does not fall because we won't call:
@@ -96,9 +93,17 @@ int main() {
9693 dynamicsWorld->addRigidBody (body);
9794 }
9895
99- // Sphere .
96+ // Object .
10097 {
101- btCollisionShape* colShape = new btSphereShape (btScalar (1.0 ));
98+ btCollisionShape *colShape;
99+ #if 1
100+ colShape = new btSphereShape (btScalar (1.0 ));
101+ #else
102+ // Because of numerical instabilities, the cube spins all over,
103+ // moving on the x and y directions.
104+ colShape = new btBoxShape(
105+ btVector3(btScalar(1.0), btScalar(1.0), btScalar(1.0)));
106+ #endif
102107 collisionShapes.push_back (colShape);
103108 btTransform startTransform;
104109 startTransform.setIdentity ();
@@ -109,7 +114,7 @@ int main() {
109114 btDefaultMotionState *myMotionState = new btDefaultMotionState (startTransform);
110115 btRigidBody *body = new btRigidBody (btRigidBody::btRigidBodyConstructionInfo (
111116 mass, myMotionState, colShape, localInertia));
112- body->setRestitution (sphereRestitution );
117+ body->setRestitution (objectRestitution );
113118 dynamicsWorld->addRigidBody (body);
114119 }
115120
@@ -128,22 +133,22 @@ int main() {
128133 }
129134 btVector3 origin = trans.getOrigin ();
130135 std::printf (" %d %d " PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " " ,
131- i,
132- j,
133- float (origin.getX ()),
134- float (origin.getY ()),
135- float (origin.getZ ()));
136- if (collisions.empty ()) {
136+ i, j, origin.getX (), origin.getY (), origin.getZ ());
137+ auto & manifoldPoints = objectsCollisions[body];
138+ if (manifoldPoints.empty ()) {
137139 std::printf (" 0 " );
138140 } else {
139141 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 ());
142+ for (auto & pt : manifoldPoints) {
143+ std::vector<btVector3> data;
144+ data.push_back (pt->getPositionWorldOnA ());
145+ data.push_back (pt->getPositionWorldOnB ());
146+ data.push_back (pt->m_normalWorldOnB );
147+ for (auto & v : data) {
148+ std::printf (
149+ PRINTF_FLOAT " " PRINTF_FLOAT " " PRINTF_FLOAT " " ,
150+ v.getX (), v.getY (), v.getZ ());
151+ }
147152 }
148153 }
149154 puts (" " );
0 commit comments