PhysicsRigidBody.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. #include "Base.h"
  2. #include "Game.h"
  3. #include "Image.h"
  4. #include "PhysicsController.h"
  5. #include "PhysicsMotionState.h"
  6. #include "PhysicsRigidBody.h"
  7. #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
  8. namespace gameplay
  9. {
  10. const int PhysicsRigidBody::Listener::DIRTY = 0x01;
  11. const int PhysicsRigidBody::Listener::COLLISION = 0x02;
  12. const int PhysicsRigidBody::Listener::REGISTERED = 0x04;
  13. // Internal values used for creating mesh, heightfield, and capsule rigid bodies.
  14. #define SHAPE_MESH ((PhysicsRigidBody::Type)(PhysicsRigidBody::SHAPE_NONE + 1))
  15. #define SHAPE_HEIGHTFIELD ((PhysicsRigidBody::Type)(PhysicsRigidBody::SHAPE_NONE + 2))
  16. #define SHAPE_CAPSULE ((PhysicsRigidBody::Type)(PhysicsRigidBody::SHAPE_NONE + 3))
  17. // Helper function for calculating heights from heightmap (image) or heightfield data.
  18. static float calculateHeight(float* data, unsigned int width, unsigned int height, float x, float y);
  19. PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, float mass,
  20. float friction, float restitution, float linearDamping, float angularDamping)
  21. : _shape(NULL), _body(NULL), _node(node), _listeners(NULL), _angularVelocity(NULL),
  22. _anisotropicFriction(NULL), _gravity(NULL), _linearVelocity(NULL), _vertexData(NULL),
  23. _indexData(NULL), _heightfieldData(NULL), _inverse(NULL), _inverseIsDirty(true)
  24. {
  25. switch (type)
  26. {
  27. case SHAPE_BOX:
  28. {
  29. const BoundingBox& box = node->getModel()->getMesh()->getBoundingBox();
  30. _shape = Game::getInstance()->getPhysicsController()->createBox(box.min, box.max, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
  31. break;
  32. }
  33. case SHAPE_SPHERE:
  34. {
  35. const BoundingSphere& sphere = node->getModel()->getMesh()->getBoundingSphere();
  36. _shape = Game::getInstance()->getPhysicsController()->createSphere(sphere.radius, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
  37. break;
  38. }
  39. case SHAPE_MESH:
  40. {
  41. _shape = Game::getInstance()->getPhysicsController()->createMesh(this);
  42. break;
  43. }
  44. }
  45. // Use the center of the bounding sphere as the center of mass offset.
  46. Vector3 c(node->getModel()->getMesh()->getBoundingSphere().center);
  47. c.negate();
  48. // Create the Bullet rigid body.
  49. if (c.lengthSquared() > MATH_EPSILON)
  50. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
  51. else
  52. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
  53. // Add the rigid body to the physics world.
  54. Game::getInstance()->getPhysicsController()->addRigidBody(this);
  55. }
  56. PhysicsRigidBody::PhysicsRigidBody(Node* node, Image* image, float mass,
  57. float friction, float restitution, float linearDamping, float angularDamping)
  58. : _shape(NULL), _body(NULL), _node(node), _listeners(NULL), _angularVelocity(NULL),
  59. _anisotropicFriction(NULL), _gravity(NULL), _linearVelocity(NULL), _vertexData(NULL),
  60. _indexData(NULL), _heightfieldData(NULL), _inverse(NULL), _inverseIsDirty(true)
  61. {
  62. // Get the width, length and minimum and maximum height of the heightfield.
  63. const BoundingBox& box = node->getModel()->getMesh()->getBoundingBox();
  64. float width = box.max.x - box.min.x;
  65. float minHeight = box.min.y;
  66. float maxHeight = box.max.y;
  67. float length = box.max.z - box.min.z;
  68. // Get the size in bytes of a pixel (we ensure that the image's
  69. // pixel format is actually supported before calling this constructor).
  70. unsigned int pixelSize = 0;
  71. switch (image->getFormat())
  72. {
  73. case Image::RGB:
  74. pixelSize = 3;
  75. break;
  76. case Image::RGBA:
  77. pixelSize = 4;
  78. break;
  79. }
  80. // Calculate the heights for each pixel.
  81. float* data = new float[image->getWidth() * image->getHeight()];
  82. for (unsigned int x = 0; x < image->getWidth(); x++)
  83. {
  84. for (unsigned int y = 0; y < image->getHeight(); y++)
  85. {
  86. data[x + y * image->getWidth()] = ((((float)image->getData()[(x + y * image->getHeight()) * pixelSize + 0]) +
  87. ((float)image->getData()[(x + y * image->getHeight()) * pixelSize + 1]) +
  88. ((float)image->getData()[(x + y * image->getHeight()) * pixelSize + 2])) / 768.0f) * (maxHeight - minHeight) + minHeight;
  89. }
  90. }
  91. // Generate the heightmap data needed for physics (one height per world unit).
  92. unsigned int sizeWidth = width;
  93. unsigned int sizeHeight = length;
  94. _width = sizeWidth + 1;
  95. _height = sizeHeight + 1;
  96. _heightfieldData = new float[_width * _height];
  97. unsigned int heightIndex = 0;
  98. float widthImageFactor = (float)(image->getWidth() - 1) / sizeWidth;
  99. float heightImageFactor = (float)(image->getHeight() - 1) / sizeHeight;
  100. float x = 0.0f;
  101. float z = 0.0f;
  102. for (unsigned int row = 0, z = 0.0f; row <= sizeHeight; row++, z += 1.0f)
  103. {
  104. for (unsigned int col = 0, x = 0.0f; col <= sizeWidth; col++, x += 1.0f)
  105. {
  106. heightIndex = row * _width + col;
  107. _heightfieldData[heightIndex] = calculateHeight(data, image->getWidth(), image->getHeight(), x * widthImageFactor, (sizeHeight - z) * heightImageFactor);
  108. }
  109. }
  110. SAFE_DELETE_ARRAY(data);
  111. // Create the heightfield collision shape.
  112. _shape = bullet_new<btHeightfieldTerrainShape>(_width, _height, _heightfieldData,
  113. 1.0f, minHeight, maxHeight, 1, PHY_FLOAT, false);
  114. // Offset the heightmap's center of mass according to the way that Bullet calculates the origin
  115. // of its heightfield collision shape; see documentation for the btHeightfieldTerrainShape for more info.
  116. Vector3 s;
  117. node->getWorldMatrix().getScale(&s);
  118. Vector3 c (0.0f, -(maxHeight - (0.5f * (maxHeight - minHeight))) / s.y, 0.0f);
  119. // Create the Bullet rigid body.
  120. if (c.lengthSquared() > MATH_EPSILON)
  121. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
  122. else
  123. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
  124. // Add the rigid body to the physics world.
  125. Game::getInstance()->getPhysicsController()->addRigidBody(this);
  126. // Add the rigid body as a listener on the node's transform.
  127. _node->addListener(this);
  128. }
  129. PhysicsRigidBody::PhysicsRigidBody(Node* node, float radius, float height, float mass, float friction,
  130. float restitution, float linearDamping, float angularDamping)
  131. : _shape(NULL), _body(NULL), _node(node), _listeners(NULL), _angularVelocity(NULL),
  132. _anisotropicFriction(NULL), _gravity(NULL), _linearVelocity(NULL), _vertexData(NULL),
  133. _indexData(NULL), _heightfieldData(NULL), _inverse(NULL), _inverseIsDirty(true)
  134. {
  135. // Create the capsule collision shape.
  136. _shape = Game::getInstance()->getPhysicsController()->createCapsule(radius, height);
  137. // Use the center of the bounding sphere as the center of mass offset.
  138. Vector3 c(node->getModel()->getMesh()->getBoundingSphere().center);
  139. c.negate();
  140. // Create the Bullet rigid body.
  141. if (c.lengthSquared() > MATH_EPSILON)
  142. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
  143. else
  144. _body = createRigidBodyInternal(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
  145. // Add the rigid body to the physics world.
  146. Game::getInstance()->getPhysicsController()->addRigidBody(this);
  147. }
  148. PhysicsRigidBody::~PhysicsRigidBody()
  149. {
  150. // Clean up all constraints linked to this rigid body.
  151. PhysicsConstraint* ptr = NULL;
  152. while (_constraints.size() > 0)
  153. {
  154. ptr = _constraints.back();
  155. _constraints.pop_back();
  156. SAFE_DELETE(ptr);
  157. }
  158. // Clean up the rigid body and its related objects.
  159. if (_body)
  160. {
  161. if (_body->getMotionState())
  162. delete _body->getMotionState();
  163. Game::getInstance()->getPhysicsController()->removeRigidBody(this);
  164. SAFE_DELETE(_body);
  165. }
  166. SAFE_DELETE(_listeners);
  167. SAFE_DELETE(_angularVelocity);
  168. SAFE_DELETE(_anisotropicFriction);
  169. SAFE_DELETE(_gravity);
  170. SAFE_DELETE(_linearVelocity);
  171. SAFE_DELETE_ARRAY(_vertexData);
  172. for (unsigned int i = 0; i < _indexData.size(); i++)
  173. {
  174. SAFE_DELETE_ARRAY(_indexData[i]);
  175. }
  176. SAFE_DELETE_ARRAY(_heightfieldData);
  177. SAFE_DELETE(_inverse);
  178. }
  179. void PhysicsRigidBody::addCollisionListener(Listener* listener, PhysicsRigidBody* body)
  180. {
  181. if (!_listeners)
  182. _listeners = new std::vector<Listener*>();
  183. CollisionPair pair(this, body);
  184. listener->_collisionStatus[pair] = PhysicsRigidBody::Listener::REGISTERED;
  185. _listeners->push_back(listener);
  186. }
  187. void PhysicsRigidBody::applyForce(const Vector3& force, const Vector3* relativePosition)
  188. {
  189. // If the force is significant enough, activate the rigid body
  190. // to make sure that it isn't sleeping and apply the force.
  191. if (force.lengthSquared() > MATH_EPSILON)
  192. {
  193. _body->activate();
  194. if (relativePosition)
  195. _body->applyForce(btVector3(force.x, force.y, force.z), btVector3(relativePosition->x, relativePosition->y, relativePosition->z));
  196. else
  197. _body->applyCentralForce(btVector3(force.x, force.y, force.z));
  198. }
  199. }
  200. void PhysicsRigidBody::applyImpulse(const Vector3& impulse, const Vector3* relativePosition)
  201. {
  202. // If the impulse is significant enough, activate the rigid body
  203. // to make sure that it isn't sleeping and apply the impulse.
  204. if (impulse.lengthSquared() > MATH_EPSILON)
  205. {
  206. _body->activate();
  207. if (relativePosition)
  208. {
  209. _body->applyImpulse(btVector3(impulse.x, impulse.y, impulse.z), btVector3(relativePosition->x, relativePosition->y, relativePosition->z));
  210. }
  211. else
  212. _body->applyCentralImpulse(btVector3(impulse.x, impulse.y, impulse.z));
  213. }
  214. }
  215. void PhysicsRigidBody::applyTorque(const Vector3& torque)
  216. {
  217. // If the torque is significant enough, activate the rigid body
  218. // to make sure that it isn't sleeping and apply the torque.
  219. if (torque.lengthSquared() > MATH_EPSILON)
  220. {
  221. _body->activate();
  222. _body->applyTorque(btVector3(torque.x, torque.y, torque.z));
  223. }
  224. }
  225. void PhysicsRigidBody::applyTorqueImpulse(const Vector3& torque)
  226. {
  227. // If the torque impulse is significant enough, activate the rigid body
  228. // to make sure that it isn't sleeping and apply the torque impulse.
  229. if (torque.lengthSquared() > MATH_EPSILON)
  230. {
  231. _body->activate();
  232. _body->applyTorqueImpulse(btVector3(torque.x, torque.y, torque.z));
  233. }
  234. }
  235. bool PhysicsRigidBody::collidesWith(PhysicsRigidBody* body)
  236. {
  237. static CollidesWithCallback callback;
  238. callback.result = false;
  239. Game::getInstance()->getPhysicsController()->_world->contactPairTest(_body, body->_body, callback);
  240. return callback.result;
  241. }
  242. PhysicsRigidBody* PhysicsRigidBody::create(Node* node, const char* filePath)
  243. {
  244. assert(filePath);
  245. // Load the rigid body properties from file.
  246. Properties* properties = Properties::create(filePath);
  247. assert(properties);
  248. if (properties == NULL)
  249. {
  250. WARN_VARG("Failed to load rigid body file: %s", filePath);
  251. return NULL;
  252. }
  253. PhysicsRigidBody* body = create(node, properties->getNextNamespace());
  254. SAFE_DELETE(properties);
  255. return body;
  256. }
  257. PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
  258. {
  259. // Check if the properties is valid and has a valid namespace.
  260. assert(properties);
  261. if (!properties || !(strcmp(properties->getNamespace(), "rigidbody") == 0))
  262. {
  263. WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidbody\'.");
  264. return NULL;
  265. }
  266. // Set values to their defaults.
  267. PhysicsRigidBody::Type type = PhysicsRigidBody::SHAPE_NONE;
  268. float mass = 0.0;
  269. float friction = 0.5;
  270. float restitution = 0.0;
  271. float linearDamping = 0.0;
  272. float angularDamping = 0.0;
  273. bool kinematic = false;
  274. Vector3* gravity = NULL;
  275. Vector3* anisotropicFriction = NULL;
  276. const char* imagePath = NULL;
  277. float radius = -1.0f;
  278. float height = -1.0f;
  279. // Load the defined properties.
  280. properties->rewind();
  281. const char* name;
  282. while (name = properties->getNextProperty())
  283. {
  284. if (strcmp(name, "type") == 0)
  285. {
  286. std::string typeStr = properties->getString();
  287. if (typeStr == "BOX")
  288. type = SHAPE_BOX;
  289. else if (typeStr == "SPHERE")
  290. type = SHAPE_SPHERE;
  291. else if (typeStr == "MESH")
  292. type = SHAPE_MESH;
  293. else if (typeStr == "HEIGHTFIELD")
  294. type = SHAPE_HEIGHTFIELD;
  295. else if (typeStr == "CAPSULE")
  296. type = SHAPE_CAPSULE;
  297. else
  298. {
  299. WARN_VARG("Could not create rigid body; unsupported value for rigid body type: '%s'.", typeStr.c_str());
  300. return NULL;
  301. }
  302. }
  303. else if (strcmp(name, "mass") == 0)
  304. {
  305. mass = properties->getFloat();
  306. }
  307. else if (strcmp(name, "friction") == 0)
  308. {
  309. friction = properties->getFloat();
  310. }
  311. else if (strcmp(name, "restitution") == 0)
  312. {
  313. restitution = properties->getFloat();
  314. }
  315. else if (strcmp(name, "linearDamping") == 0)
  316. {
  317. linearDamping = properties->getFloat();
  318. }
  319. else if (strcmp(name, "angularDamping") == 0)
  320. {
  321. angularDamping = properties->getFloat();
  322. }
  323. else if (strcmp(name, "kinematic") == 0)
  324. {
  325. kinematic = properties->getBool();
  326. }
  327. else if (strcmp(name, "gravity") == 0)
  328. {
  329. gravity = new Vector3();
  330. properties->getVector3(NULL, gravity);
  331. }
  332. else if (strcmp(name, "anisotropicFriction") == 0)
  333. {
  334. anisotropicFriction = new Vector3();
  335. properties->getVector3(NULL, anisotropicFriction);
  336. }
  337. else if (strcmp(name, "image") == 0)
  338. {
  339. imagePath = properties->getString();
  340. }
  341. else if (strcmp(name, "radius") == 0)
  342. {
  343. radius = properties->getFloat();
  344. }
  345. else if (strcmp(name, "height") == 0)
  346. {
  347. height = properties->getFloat();
  348. }
  349. }
  350. // If the rigid body type is equal to mesh, check that the node's mesh's primitive type is supported.
  351. if (type == SHAPE_MESH)
  352. {
  353. Mesh* mesh = node->getModel()->getMesh();
  354. switch (mesh->getPrimitiveType())
  355. {
  356. case Mesh::TRIANGLES:
  357. break;
  358. case Mesh::LINES:
  359. case Mesh::LINE_STRIP:
  360. case Mesh::POINTS:
  361. case Mesh::TRIANGLE_STRIP:
  362. WARN("Mesh rigid bodies are currently only supported on meshes with primitive type equal to TRIANGLES.");
  363. SAFE_DELETE(gravity);
  364. SAFE_DELETE(anisotropicFriction);
  365. return NULL;
  366. }
  367. }
  368. // Create the rigid body.
  369. PhysicsRigidBody* body = NULL;
  370. switch (type)
  371. {
  372. case SHAPE_HEIGHTFIELD:
  373. if (imagePath == NULL)
  374. {
  375. WARN("Heightfield rigid body requires an image path.");
  376. }
  377. else
  378. {
  379. // Load the image data from the given file path.
  380. Image* image = Image::create(imagePath);
  381. if (!image)
  382. return NULL;
  383. // Ensure that the image's pixel format is supported.
  384. switch (image->getFormat())
  385. {
  386. case Image::RGB:
  387. case Image::RGBA:
  388. break;
  389. default:
  390. WARN_VARG("Heightmap: pixel format is not supported: %d", image->getFormat());
  391. return NULL;
  392. }
  393. body = new PhysicsRigidBody(node, image, mass, friction, restitution, linearDamping, angularDamping);
  394. SAFE_RELEASE(image);
  395. }
  396. break;
  397. case SHAPE_CAPSULE:
  398. if (radius == -1.0f || height == -1.0f)
  399. {
  400. WARN("Both 'radius' and 'height' must be specified for a capsule rigid body.");
  401. }
  402. else
  403. {
  404. body = new PhysicsRigidBody(node, radius, height, mass, friction, restitution, linearDamping, angularDamping);
  405. }
  406. break;
  407. default:
  408. body = new PhysicsRigidBody(node, type, mass, friction, restitution, linearDamping, angularDamping);
  409. break;
  410. }
  411. // Set any initially defined properties.
  412. if (kinematic)
  413. body->setKinematic(kinematic);
  414. if (gravity)
  415. body->setGravity(*gravity);
  416. if (anisotropicFriction)
  417. body->setAnisotropicFriction(*anisotropicFriction);
  418. // Clean up any loaded properties that are on the heap.
  419. SAFE_DELETE(gravity);
  420. SAFE_DELETE(anisotropicFriction);
  421. return body;
  422. }
  423. float PhysicsRigidBody::getHeight(float x, float y) const
  424. {
  425. // This function is only supported for heightfield rigid bodies.
  426. if (_shape->getShapeType() != TERRAIN_SHAPE_PROXYTYPE)
  427. {
  428. WARN("Attempting to get the height of a non-heightfield rigid body.");
  429. return 0.0f;
  430. }
  431. // Calculate the correct x, y position relative to the heightfield data.
  432. if (_inverseIsDirty)
  433. {
  434. if (_inverse == NULL)
  435. _inverse = new Matrix();
  436. _node->getWorldMatrix().invert(_inverse);
  437. _inverseIsDirty = false;
  438. }
  439. Vector3 v = (*_inverse) * Vector3(x, 0.0f, y);
  440. x = (v.x + (0.5f * (_width - 1))) * _width / (_width - 1);
  441. y = (v.z + (0.5f * (_height - 1))) * _height / (_height - 1);
  442. // Check that the x, y position is within the bounds.
  443. if (x < 0.0f || x > _width || y < 0.0f || y > _height)
  444. {
  445. WARN_VARG("Attempting to get height at point '%f, %f', which is outside the range of the heightfield with width %d and height %d.", x, y, _width, _height);
  446. return 0.0f;
  447. }
  448. return calculateHeight(_heightfieldData, _width, _height, x, y);
  449. }
  450. btRigidBody* PhysicsRigidBody::createRigidBodyInternal(btCollisionShape* shape, float mass, Node* node,
  451. float friction, float restitution, float linearDamping, float angularDamping,
  452. const Vector3* centerOfMassOffset)
  453. {
  454. // If the mass is non-zero, then the object is dynamic so we calculate the local
  455. // inertia. However, if the collision shape is a triangle mesh, we don't calculate
  456. // inertia since Bullet doesn't currently support this.
  457. btVector3 localInertia(0.0, 0.0, 0.0);
  458. if (mass != 0.0 && shape->getShapeType() != TRIANGLE_MESH_SHAPE_PROXYTYPE)
  459. shape->calculateLocalInertia(mass, localInertia);
  460. // Create the Bullet physics rigid body object.
  461. PhysicsMotionState* motionState = new PhysicsMotionState(node, centerOfMassOffset);
  462. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, motionState, shape, localInertia);
  463. rbInfo.m_friction = friction;
  464. rbInfo.m_restitution = restitution;
  465. rbInfo.m_linearDamping = linearDamping;
  466. rbInfo.m_angularDamping = angularDamping;
  467. btRigidBody* body = bullet_new<btRigidBody>(rbInfo);
  468. return body;
  469. }
  470. void PhysicsRigidBody::addConstraint(PhysicsConstraint* constraint)
  471. {
  472. _constraints.push_back(constraint);
  473. }
  474. void PhysicsRigidBody::removeConstraint(PhysicsConstraint* constraint)
  475. {
  476. for (unsigned int i = 0; i < _constraints.size(); i++)
  477. {
  478. if (_constraints[i] == constraint)
  479. {
  480. _constraints.erase(_constraints.begin() + i);
  481. break;
  482. }
  483. }
  484. }
  485. bool PhysicsRigidBody::supportsConstraints()
  486. {
  487. return _shape->getShapeType() != TRIANGLE_MESH_SHAPE_PROXYTYPE && _shape->getShapeType() != TERRAIN_SHAPE_PROXYTYPE;
  488. }
  489. void PhysicsRigidBody::transformChanged(Transform* transform, long cookie)
  490. {
  491. _inverseIsDirty = true;
  492. }
  493. PhysicsRigidBody::CollisionPair::CollisionPair(PhysicsRigidBody* rbA, PhysicsRigidBody* rbB)
  494. : _rbA(rbA), _rbB(rbB)
  495. {
  496. // Unused
  497. }
  498. PhysicsRigidBody::Listener::~Listener()
  499. {
  500. // Unused
  501. }
  502. btScalar PhysicsRigidBody::Listener::addSingleResult(btManifoldPoint& cp,
  503. const btCollisionObject* a, int partIdA, int indexA,
  504. const btCollisionObject* b, int partIdB, int indexB)
  505. {
  506. // Get pointers to the PhysicsRigidBody objects.
  507. PhysicsRigidBody* rbA = Game::getInstance()->getPhysicsController()->getRigidBody(a);
  508. PhysicsRigidBody* rbB = Game::getInstance()->getPhysicsController()->getRigidBody(b);
  509. // If the given rigid body pair has collided in the past, then
  510. // we notify the listener only if the pair was not colliding
  511. // during the previous frame. Otherwise, it's a new pair, so notify the listener.
  512. CollisionPair pair(rbA, rbB);
  513. if (_collisionStatus.count(pair) > 0)
  514. {
  515. if ((_collisionStatus[pair] & COLLISION) == 0)
  516. collisionEvent(pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()));
  517. }
  518. else
  519. {
  520. collisionEvent(pair, Vector3(cp.getPositionWorldOnA().x(), cp.getPositionWorldOnA().y(), cp.getPositionWorldOnA().z()));
  521. }
  522. // Update the collision status cache (we remove the dirty bit
  523. // set in the controller's update so that this particular collision pair's
  524. // status is not reset to 'no collision' when the controller's update completes).
  525. _collisionStatus[pair] &= ~DIRTY;
  526. _collisionStatus[pair] |= COLLISION;
  527. return 0.0f;
  528. }
  529. btScalar PhysicsRigidBody::CollidesWithCallback::addSingleResult(btManifoldPoint& cp,
  530. const btCollisionObject* a, int partIdA, int indexA,
  531. const btCollisionObject* b, int partIdB, int indexB)
  532. {
  533. result = true;
  534. return 0.0f;
  535. }
  536. float calculateHeight(float* data, unsigned int width, unsigned int height, float x, float y)
  537. {
  538. unsigned int x1 = x;
  539. unsigned int y1 = y;
  540. unsigned int x2 = x1 + 1;
  541. unsigned int y2 = y1 + 1;
  542. float tmp;
  543. float xFactor = modf(x, &tmp);
  544. float yFactor = modf(y, &tmp);
  545. float xFactorI = 1.0f - xFactor;
  546. float yFactorI = 1.0f - yFactor;
  547. if (x2 >= width && y2 >= height)
  548. {
  549. return data[x1 + y1 * width];
  550. }
  551. else if (x2 >= width)
  552. {
  553. return data[x1 + y1 * width] * yFactorI + data[x1 + y2 * width] * yFactor;
  554. }
  555. else if (y2 >= height)
  556. {
  557. return data[x1 + y1 * width] * xFactorI + data[x2 + y1 * width] * xFactor;
  558. }
  559. else
  560. {
  561. return data[x1 + y1 * width] * xFactorI * yFactorI + data[x1 + y2 * width] * xFactorI * yFactor +
  562. data[x2 + y2 * width] * xFactor * yFactor + data[x2 + y1 * width] * xFactor * yFactorI;
  563. }
  564. }
  565. }