CCPhysics3DObject.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /****************************************************************************
  2. Copyright (c) 2015-2017 Chukong Technologies Inc.
  3. http://www.cocos2d-x.org
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. THE SOFTWARE.
  19. ****************************************************************************/
  20. #include "physics3d/CCPhysics3D.h"
  21. #include "base/ccUTF8.h"
  22. #if CC_USE_3D_PHYSICS
  23. #if (CC_ENABLE_BULLET_INTEGRATION)
  24. #include "bullet/btBulletCollisionCommon.h"
  25. #include "bullet/btBulletDynamicsCommon.h"
  26. NS_CC_BEGIN
  27. Physics3DRigidBody::Physics3DRigidBody()
  28. : _btRigidBody(nullptr)
  29. , _physics3DShape(nullptr)
  30. {
  31. }
  32. Physics3DRigidBody::~Physics3DRigidBody()
  33. {
  34. if (_physicsWorld)
  35. {
  36. for(auto constraint : _constraintList)
  37. {
  38. _physicsWorld->removePhysics3DConstraint(constraint);
  39. }
  40. _constraintList.clear();
  41. }
  42. auto ms = _btRigidBody->getMotionState();
  43. CC_SAFE_DELETE(ms);
  44. CC_SAFE_DELETE(_btRigidBody);
  45. CC_SAFE_RELEASE(_physics3DShape);
  46. }
  47. Physics3DRigidBody* Physics3DRigidBody::create(Physics3DRigidBodyDes* info)
  48. {
  49. auto ret = new (std::nothrow) Physics3DRigidBody();
  50. if (ret->init(info))
  51. {
  52. ret->autorelease();
  53. return ret;
  54. }
  55. CC_SAFE_DELETE(ret);
  56. return ret;
  57. }
  58. bool Physics3DRigidBody::init(Physics3DRigidBodyDes* info)
  59. {
  60. if (info->shape == nullptr)
  61. return false;
  62. btScalar mass = info->mass;
  63. auto shape = info->shape->getbtShape();
  64. auto localInertia = convertVec3TobtVector3(info->localInertia);
  65. if (mass != 0.f)
  66. {
  67. shape->calculateLocalInertia(mass,localInertia);
  68. }
  69. auto transform = convertMat4TobtTransform(info->originalTransform);
  70. btDefaultMotionState* myMotionState = new btDefaultMotionState(transform);
  71. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
  72. _btRigidBody = new btRigidBody(rbInfo);
  73. _type = Physics3DObject::PhysicsObjType::RIGID_BODY;
  74. _physics3DShape = info->shape;
  75. _physics3DShape->retain();
  76. if (info->disableSleep)
  77. _btRigidBody->setActivationState(DISABLE_DEACTIVATION);
  78. return true;
  79. }
  80. void Physics3DRigidBody::setActive(bool active)
  81. {
  82. if (_btRigidBody)
  83. {
  84. _btRigidBody->setActivationState(active ? ACTIVE_TAG : WANTS_DEACTIVATION);
  85. }
  86. }
  87. void Physics3DRigidBody::applyForce( const cocos2d::Vec3& force, const cocos2d::Vec3& rel_pos )
  88. {
  89. _btRigidBody->applyForce(convertVec3TobtVector3(force), convertVec3TobtVector3(rel_pos));
  90. }
  91. void Physics3DRigidBody::setLinearVelocity( const cocos2d::Vec3& lin_vel )
  92. {
  93. _btRigidBody->setLinearVelocity(convertVec3TobtVector3(lin_vel));
  94. }
  95. void Physics3DRigidBody::applyCentralForce( const cocos2d::Vec3& force )
  96. {
  97. _btRigidBody->applyCentralForce(convertVec3TobtVector3(force));
  98. }
  99. void Physics3DRigidBody::applyCentralImpulse( const cocos2d::Vec3& impulse )
  100. {
  101. _btRigidBody->applyCentralImpulse(convertVec3TobtVector3(impulse));
  102. }
  103. void Physics3DRigidBody::applyTorque( const cocos2d::Vec3& torque )
  104. {
  105. _btRigidBody->applyTorque(convertVec3TobtVector3(torque));
  106. }
  107. void Physics3DRigidBody::applyTorqueImpulse( const cocos2d::Vec3& torque )
  108. {
  109. _btRigidBody->applyTorqueImpulse(convertVec3TobtVector3(torque));
  110. }
  111. void Physics3DRigidBody::applyImpulse( const cocos2d::Vec3& impulse, const cocos2d::Vec3& rel_pos )
  112. {
  113. _btRigidBody->applyImpulse(convertVec3TobtVector3(impulse), convertVec3TobtVector3(rel_pos));
  114. }
  115. void Physics3DRigidBody::applyDamping( float timeStep )
  116. {
  117. _btRigidBody->applyDamping(timeStep);
  118. }
  119. cocos2d::Vec3 Physics3DRigidBody::getLinearVelocity() const
  120. {
  121. return convertbtVector3ToVec3(_btRigidBody->getLinearVelocity());
  122. }
  123. void Physics3DRigidBody::setLinearFactor( const cocos2d::Vec3& linearFactor )
  124. {
  125. _btRigidBody->setLinearFactor(convertVec3TobtVector3(linearFactor));
  126. }
  127. cocos2d::Vec3 Physics3DRigidBody::getLinearFactor() const
  128. {
  129. return convertbtVector3ToVec3(_btRigidBody->getLinearFactor());
  130. }
  131. void Physics3DRigidBody::setAngularFactor( const cocos2d::Vec3& angFac )
  132. {
  133. _btRigidBody->setAngularFactor(convertVec3TobtVector3(angFac));
  134. }
  135. void Physics3DRigidBody::setAngularFactor( float angFac )
  136. {
  137. _btRigidBody->setAngularFactor(angFac);
  138. }
  139. cocos2d::Vec3 Physics3DRigidBody::getAngularFactor() const
  140. {
  141. return convertbtVector3ToVec3(_btRigidBody->getAngularFactor());
  142. }
  143. void Physics3DRigidBody::setAngularVelocity( const cocos2d::Vec3& ang_vel )
  144. {
  145. _btRigidBody->setAngularVelocity(convertVec3TobtVector3(ang_vel));
  146. }
  147. cocos2d::Vec3 Physics3DRigidBody::getAngularVelocity() const
  148. {
  149. return convertbtVector3ToVec3(_btRigidBody->getAngularVelocity());
  150. }
  151. void Physics3DRigidBody::setCenterOfMassTransform( const cocos2d::Mat4& xform )
  152. {
  153. _btRigidBody->setCenterOfMassTransform(convertMat4TobtTransform(xform));
  154. }
  155. cocos2d::Mat4 Physics3DRigidBody::getCenterOfMassTransform() const
  156. {
  157. return convertbtTransformToMat4(_btRigidBody->getCenterOfMassTransform());
  158. }
  159. void Physics3DRigidBody::setDamping( float lin_damping, float ang_damping )
  160. {
  161. _btRigidBody->setDamping(lin_damping, ang_damping);
  162. }
  163. float Physics3DRigidBody::getLinearDamping() const
  164. {
  165. return _btRigidBody->getLinearDamping();
  166. }
  167. float Physics3DRigidBody::getAngularDamping() const
  168. {
  169. return _btRigidBody->getAngularDamping();
  170. }
  171. void Physics3DRigidBody::setGravity( const cocos2d::Vec3& acceleration )
  172. {
  173. _btRigidBody->setGravity(convertVec3TobtVector3(acceleration));
  174. }
  175. cocos2d::Vec3 Physics3DRigidBody::getGravity() const
  176. {
  177. return convertbtVector3ToVec3(_btRigidBody->getGravity());
  178. }
  179. void Physics3DRigidBody::setInvInertiaDiagLocal( const cocos2d::Vec3& diagInvInertia )
  180. {
  181. _btRigidBody->setInvInertiaDiagLocal(convertVec3TobtVector3(diagInvInertia));
  182. }
  183. cocos2d::Vec3 Physics3DRigidBody::getInvInertiaDiagLocal() const
  184. {
  185. return convertbtVector3ToVec3(_btRigidBody->getInvInertiaDiagLocal());
  186. }
  187. void Physics3DRigidBody::setMassProps( float mass, const cocos2d::Vec3& inertia )
  188. {
  189. _btRigidBody->setMassProps(mass, convertVec3TobtVector3(inertia));
  190. }
  191. float Physics3DRigidBody::getInvMass() const
  192. {
  193. return _btRigidBody->getInvMass();
  194. }
  195. cocos2d::Vec3 Physics3DRigidBody::getTotalForce() const
  196. {
  197. return convertbtVector3ToVec3(_btRigidBody->getTotalForce());
  198. }
  199. cocos2d::Vec3 Physics3DRigidBody::getTotalTorque() const
  200. {
  201. return convertbtVector3ToVec3(_btRigidBody->getTotalTorque());
  202. }
  203. void Physics3DRigidBody::setRestitution( float rest )
  204. {
  205. _btRigidBody->setRestitution(rest);
  206. }
  207. float Physics3DRigidBody::getRestitution() const
  208. {
  209. return _btRigidBody->getRestitution();
  210. }
  211. void Physics3DRigidBody::setFriction( float frict )
  212. {
  213. _btRigidBody->setFriction(frict);
  214. }
  215. float Physics3DRigidBody::getFriction() const
  216. {
  217. return _btRigidBody->getFriction();
  218. }
  219. void Physics3DRigidBody::setRollingFriction( float frict )
  220. {
  221. _btRigidBody->setRollingFriction(frict);
  222. }
  223. float Physics3DRigidBody::getRollingFriction() const
  224. {
  225. return _btRigidBody->getRollingFriction();
  226. }
  227. void Physics3DRigidBody::setHitFraction( float hitFraction )
  228. {
  229. _btRigidBody->setHitFraction(hitFraction);
  230. }
  231. float Physics3DRigidBody::getHitFraction() const
  232. {
  233. return _btRigidBody->getHitFraction();
  234. }
  235. void Physics3DRigidBody::setCcdMotionThreshold( float ccdMotionThreshold )
  236. {
  237. _btRigidBody->setCcdMotionThreshold(ccdMotionThreshold);
  238. }
  239. float Physics3DRigidBody::getCcdMotionThreshold() const
  240. {
  241. return _btRigidBody->getCcdMotionThreshold();
  242. }
  243. void Physics3DRigidBody::setCcdSweptSphereRadius( float radius )
  244. {
  245. _btRigidBody->setCcdSweptSphereRadius(radius);
  246. }
  247. float Physics3DRigidBody::getCcdSweptSphereRadius() const
  248. {
  249. return _btRigidBody->getCcdSweptSphereRadius();
  250. }
  251. void Physics3DRigidBody::addConstraint( Physics3DConstraint *constraint )
  252. {
  253. auto iter = std::find(_constraintList.begin(), _constraintList.end(), constraint);
  254. if (iter == _constraintList.end()){
  255. _constraintList.push_back(constraint);
  256. constraint->retain();
  257. }
  258. }
  259. void Physics3DRigidBody::removeConstraint( Physics3DConstraint *constraint )
  260. {
  261. auto iter = std::find(_constraintList.begin(), _constraintList.end(), constraint);
  262. if (iter != _constraintList.end()){
  263. constraint->release();
  264. _constraintList.erase(iter);
  265. }
  266. }
  267. void Physics3DRigidBody::removeConstraint( unsigned int idx )
  268. {
  269. CCASSERT(idx < _constraintList.size(), "idx < _constraintList.size()");
  270. removeConstraint(_constraintList[idx]);
  271. }
  272. Physics3DConstraint* Physics3DRigidBody::getConstraint( unsigned int idx ) const
  273. {
  274. CCASSERT(idx < _constraintList.size(), "idx < _constraintList.size()");
  275. return _constraintList[idx];
  276. }
  277. unsigned int Physics3DRigidBody::getConstraintCount() const
  278. {
  279. return (unsigned int)_constraintList.size();
  280. }
  281. cocos2d::Mat4 Physics3DRigidBody::getWorldTransform() const
  282. {
  283. const auto& transform = _btRigidBody->getWorldTransform();
  284. return convertbtTransformToMat4(transform);
  285. }
  286. void Physics3DRigidBody::setKinematic(bool kinematic)
  287. {
  288. if (kinematic)
  289. {
  290. _btRigidBody->setCollisionFlags(_btRigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
  291. _btRigidBody->setActivationState(DISABLE_DEACTIVATION);
  292. }
  293. else
  294. {
  295. _btRigidBody->setCollisionFlags(_btRigidBody->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
  296. _btRigidBody->setActivationState(ACTIVE_TAG);
  297. }
  298. }
  299. bool Physics3DRigidBody::isKinematic() const
  300. {
  301. if (_btRigidBody)
  302. return _btRigidBody->isKinematicObject();
  303. return false;
  304. }
  305. class btCollider : public btGhostObject
  306. {
  307. public:
  308. btCollider(Physics3DCollider *collider)
  309. : _collider(collider)
  310. {};
  311. ~btCollider(){};
  312. ///this method is mainly for expert/internal use only.
  313. virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = nullptr) override
  314. {
  315. btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
  316. btAssert(otherObject);
  317. ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
  318. int index = m_overlappingObjects.findLinearSearch(otherObject);
  319. if (index == m_overlappingObjects.size())
  320. {
  321. //not found
  322. m_overlappingObjects.push_back(otherObject);
  323. if (_collider->onTriggerEnter != nullptr && _collider->isTrigger())
  324. _collider->onTriggerEnter(getPhysicsObject(otherObject));
  325. }
  326. }
  327. ///this method is mainly for expert/internal use only.
  328. virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* /*dispatcher*/, btBroadphaseProxy* thisProxy = nullptr) override
  329. {
  330. btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
  331. btAssert(otherObject);
  332. int index = m_overlappingObjects.findLinearSearch(otherObject);
  333. if (index < m_overlappingObjects.size())
  334. {
  335. m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
  336. m_overlappingObjects.pop_back();
  337. if (_collider->onTriggerExit != nullptr && _collider->isTrigger())
  338. _collider->onTriggerExit(getPhysicsObject(otherObject));
  339. }
  340. }
  341. Physics3DObject* getPhysicsObject(const btCollisionObject* btObj)
  342. {
  343. for (auto it : _collider->getPhysicsWorld()->getPhysicsObjects())
  344. {
  345. if (it->getObjType() == Physics3DObject::PhysicsObjType::RIGID_BODY)
  346. {
  347. if (static_cast<Physics3DRigidBody*>(it)->getRigidBody() == btObj)
  348. return it;
  349. }
  350. else if (it->getObjType() == Physics3DObject::PhysicsObjType::COLLIDER)
  351. {
  352. if (static_cast<Physics3DCollider*>(it)->getGhostObject() == btObj)
  353. return it;
  354. }
  355. }
  356. return nullptr;
  357. }
  358. private:
  359. Physics3DCollider *_collider;
  360. };
  361. Physics3DCollider::Physics3DCollider()
  362. : _btGhostObject(nullptr)
  363. , _physics3DShape(nullptr)
  364. {
  365. }
  366. Physics3DCollider::~Physics3DCollider()
  367. {
  368. CC_SAFE_DELETE(_btGhostObject);
  369. CC_SAFE_RELEASE(_physics3DShape);
  370. }
  371. Physics3DCollider* Physics3DCollider::create(Physics3DColliderDes *info)
  372. {
  373. auto ret = new (std::nothrow) Physics3DCollider();
  374. if (ret->init(info))
  375. {
  376. ret->autorelease();
  377. return ret;
  378. }
  379. CC_SAFE_DELETE(ret);
  380. return ret;
  381. }
  382. float Physics3DCollider::getCcdSweptSphereRadius() const
  383. {
  384. return _btGhostObject->getCcdSweptSphereRadius();
  385. }
  386. void Physics3DCollider::setCcdSweptSphereRadius(float radius)
  387. {
  388. _btGhostObject->setCcdSweptSphereRadius(radius);
  389. }
  390. float Physics3DCollider::getCcdMotionThreshold() const
  391. {
  392. return _btGhostObject->getCcdMotionThreshold();
  393. }
  394. void Physics3DCollider::setCcdMotionThreshold(float ccdMotionThreshold)
  395. {
  396. _btGhostObject->setCcdMotionThreshold(ccdMotionThreshold);
  397. }
  398. float Physics3DCollider::getHitFraction() const
  399. {
  400. return _btGhostObject->getHitFraction();
  401. }
  402. void Physics3DCollider::setHitFraction(float hitFraction)
  403. {
  404. _btGhostObject->setHitFraction(hitFraction);
  405. }
  406. float Physics3DCollider::getRollingFriction() const
  407. {
  408. return _btGhostObject->getRollingFriction();
  409. }
  410. void Physics3DCollider::setRollingFriction(float frict)
  411. {
  412. _btGhostObject->setRollingFriction(frict);
  413. }
  414. float Physics3DCollider::getFriction() const
  415. {
  416. return _btGhostObject->getFriction();
  417. }
  418. void Physics3DCollider::setFriction(float frict)
  419. {
  420. _btGhostObject->setFriction(frict);
  421. }
  422. float Physics3DCollider::getRestitution() const
  423. {
  424. return _btGhostObject->getRestitution();
  425. }
  426. void Physics3DCollider::setRestitution(float rest)
  427. {
  428. _btGhostObject->setRestitution(rest);
  429. }
  430. bool Physics3DCollider::isTrigger() const
  431. {
  432. return (_btGhostObject->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE) != 0;
  433. }
  434. void Physics3DCollider::setTrigger(bool isTrigger)
  435. {
  436. _btGhostObject->setCollisionFlags(isTrigger == true ?
  437. _btGhostObject->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE :
  438. _btGhostObject->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
  439. }
  440. bool Physics3DCollider::init(Physics3DColliderDes *info)
  441. {
  442. _physics3DShape = info->shape;
  443. _physics3DShape->retain();
  444. _btGhostObject = new btCollider(this);
  445. _btGhostObject->setCollisionShape(_physics3DShape->getbtShape());
  446. setTrigger(info->isTrigger);
  447. setFriction(info->friction);
  448. setRollingFriction(info->rollingFriction);
  449. setRestitution(info->restitution);
  450. setHitFraction(info->hitFraction);
  451. setCcdSweptSphereRadius(info->ccdSweptSphereRadius);
  452. setCcdMotionThreshold(info->ccdMotionThreshold);
  453. _type = Physics3DObject::PhysicsObjType::COLLIDER;
  454. return true;
  455. }
  456. cocos2d::Mat4 Physics3DCollider::getWorldTransform() const
  457. {
  458. return convertbtTransformToMat4(_btGhostObject->getWorldTransform());
  459. }
  460. NS_CC_END
  461. #endif // CC_ENABLE_BULLET_INTEGRATION
  462. #endif // CC_USE_3D_PHYSICS