forked from cirosantilli/cpp-cheat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
which_collision.cpp
133 lines (121 loc) · 5.44 KB
/
which_collision.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
Drop two objects to the ground, starting from different heights.
Whenever a collision happens, determine which object has collided with which object:
http://gamedev.stackexchange.com/questions/22442/how-get-collision-callback-of-two-specific-objects-using-bullet-physics
Derived from drop_object.cpp
*/
#include <cstdio>
#include <cstdlib>
#include <map>
#include <type_traits>
#include <vector>
#include <btBulletDynamicsCommon.h>
#include "common.hpp"
constexpr float gravity = -10.0f;
constexpr float timeStep = 1.0f / 60.0f;
constexpr float groundRestitution = 0.9f;
constexpr float objectRestitution = 0.9f;
constexpr unsigned int nSteps = 500;
constexpr float initialXs[] = { 0.0f, 5.0f };
constexpr float initialYs[] = { 10.0f, 5.0f };
constexpr size_t nObjects = sizeof(initialYs) / sizeof(float);
std::map<const btCollisionObject*,std::vector<btManifoldPoint*>> objectsCollisions;
void myTickCallback(btDynamicsWorld *dynamicsWorld, btScalar timeStep) {
objectsCollisions.clear();
int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
for (int i = 0; i < numManifolds; i++) {
btPersistentManifold *contactManifold = dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
auto *objA = contactManifold->getBody0();
auto *objB = contactManifold->getBody1();
auto& collisionsA = objectsCollisions[objA];
auto& collisionsB = objectsCollisions[objB];
int numContacts = contactManifold->getNumContacts();
for (int j = 0; j < numContacts; j++) {
btManifoldPoint& pt = contactManifold->getContactPoint(j);
collisionsA.push_back(&pt);
collisionsB.push_back(&pt);
}
}
}
int main() {
btDefaultCollisionConfiguration *collisionConfiguration
= new btDefaultCollisionConfiguration();
btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
btBroadphaseInterface *overlappingPairCache = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld *dynamicsWorld = new btDiscreteDynamicsWorld(
dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0, gravity, 0));
dynamicsWorld->setInternalTickCallback(myTickCallback);
btAlignedObjectArray<btCollisionShape*> collisionShapes;
// Ground.
{
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0, 0, 0));
btCollisionShape* groundShape;
groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), -1);
collisionShapes.push_back(groundShape);
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(0, myMotionState, groundShape, btVector3(0, 0, 0));
btRigidBody* body = new btRigidBody(rbInfo);
body->setRestitution(groundRestitution);
dynamicsWorld->addRigidBody(body);
}
// Objects.
std::vector<btRigidBody*> objects;
for (size_t i = 0; i < nObjects; ++i) {
btCollisionShape *colShape;
colShape = new btSphereShape(btScalar(1.0));
collisionShapes.push_back(colShape);
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(initialXs[i], initialYs[i], 0));
btVector3 localInertia(0, 0, 0);
btScalar mass(1.0f);
colShape->calculateLocalInertia(mass, localInertia);
btDefaultMotionState *myMotionState = new btDefaultMotionState(startTransform);
btRigidBody *body = new btRigidBody(btRigidBody::btRigidBodyConstructionInfo(
mass, myMotionState, colShape, localInertia));
body->setRestitution(objectRestitution);
dynamicsWorld->addRigidBody(body);
objects.push_back(body);
}
// Main loop.
std::printf(COMMON_PRINTF_HEADER " collision1 collision2\n");
for (std::remove_const<decltype(nSteps)>::type step = 0; step < nSteps; ++step) {
dynamicsWorld->stepSimulation(timeStep);
auto nCollisionObjects = dynamicsWorld->getNumCollisionObjects();
for (std::remove_const<decltype(nCollisionObjects)>::type objectIndex = 0; objectIndex < nCollisionObjects; ++objectIndex) {
btRigidBody *body = btRigidBody::upcast(dynamicsWorld->getCollisionObjectArray()[objectIndex]);
commonPrintBodyState(body, step, objectIndex);
// We could use objects[i] here to check for one of the objects we've created.
auto manifoldPoints = objectsCollisions[body];
if (manifoldPoints.empty()) {
std::printf("0");
} else {
std::printf("1");
}
std::printf("\n");
}
}
// Cleanup.
for (int i = dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; --i) {
btCollisionObject *obj = dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody *body = btRigidBody::upcast(obj);
if (body && body->getMotionState()) {
delete body->getMotionState();
}
dynamicsWorld->removeCollisionObject(obj);
delete obj;
}
for (int i = 0; i < collisionShapes.size(); ++i) {
delete collisionShapes[i];
}
delete dynamicsWorld;
delete solver;
delete overlappingPairCache;
delete dispatcher;
delete collisionConfiguration;
collisionShapes.clear();
}