Body.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /**
  2. * Copyright (c) 2006-2013 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Body.h"
  21. #include "common/math.h"
  22. #include "common/Memoizer.h"
  23. #include "Shape.h"
  24. #include "Fixture.h"
  25. #include "World.h"
  26. #include "Physics.h"
  27. namespace love
  28. {
  29. namespace physics
  30. {
  31. namespace box2d
  32. {
  33. Body::Body(World *world, b2Vec2 p, Body::Type type)
  34. : world(world)
  35. {
  36. world->retain();
  37. b2BodyDef def;
  38. def.position = Physics::scaleDown(p);
  39. body = world->world->CreateBody(&def);
  40. // Box2D body holds a reference to the love Body.
  41. this->retain();
  42. this->setType(type);
  43. Memoizer::add(body, this);
  44. }
  45. Body::Body(b2Body *b)
  46. : body(b)
  47. {
  48. world = (World *)Memoizer::find(b->GetWorld());
  49. world->retain();
  50. // Box2D body holds a reference to the love Body.
  51. this->retain();
  52. Memoizer::add(body, this);
  53. }
  54. Body::~Body()
  55. {
  56. world->release();
  57. body = 0;
  58. }
  59. float Body::getX()
  60. {
  61. return Physics::scaleUp(body->GetPosition().x);
  62. }
  63. float Body::getY()
  64. {
  65. return Physics::scaleUp(body->GetPosition().y);
  66. }
  67. void Body::getPosition(float &x_o, float &y_o)
  68. {
  69. b2Vec2 v = Physics::scaleUp(body->GetPosition());
  70. x_o = v.x;
  71. y_o = v.y;
  72. }
  73. void Body::getLinearVelocity(float &x_o, float &y_o)
  74. {
  75. b2Vec2 v = Physics::scaleUp(body->GetLinearVelocity());
  76. x_o = v.x;
  77. y_o = v.y;
  78. }
  79. float Body::getAngle()
  80. {
  81. return body->GetAngle();
  82. }
  83. void Body::getWorldCenter(float &x_o, float &y_o)
  84. {
  85. b2Vec2 v = Physics::scaleUp(body->GetWorldCenter());
  86. x_o = v.x;
  87. y_o = v.y;
  88. }
  89. void Body::getLocalCenter(float &x_o, float &y_o)
  90. {
  91. b2Vec2 v = Physics::scaleUp(body->GetLocalCenter());
  92. x_o = v.x;
  93. y_o = v.y;
  94. }
  95. float Body::getAngularVelocity() const
  96. {
  97. return body->GetAngularVelocity();
  98. }
  99. float Body::getMass() const
  100. {
  101. return body->GetMass();
  102. }
  103. float Body::getInertia() const
  104. {
  105. return Physics::scaleUp(Physics::scaleUp(body->GetInertia()));
  106. }
  107. int Body::getMassData(lua_State *L)
  108. {
  109. b2MassData data;
  110. body->GetMassData(&data);
  111. b2Vec2 center = Physics::scaleUp(data.center);
  112. lua_pushnumber(L, center.x);
  113. lua_pushnumber(L, center.y);
  114. lua_pushnumber(L, data.mass);
  115. lua_pushnumber(L, Physics::scaleUp(Physics::scaleUp(data.I)));
  116. return 4;
  117. }
  118. float Body::getAngularDamping() const
  119. {
  120. return body->GetAngularDamping();
  121. }
  122. float Body::getLinearDamping() const
  123. {
  124. return body->GetLinearDamping();
  125. }
  126. float Body::getGravityScale() const
  127. {
  128. return body->GetGravityScale();
  129. }
  130. Body::Type Body::getType() const
  131. {
  132. switch (body->GetType())
  133. {
  134. case b2_staticBody:
  135. return BODY_STATIC;
  136. break;
  137. case b2_dynamicBody:
  138. return BODY_DYNAMIC;
  139. break;
  140. case b2_kinematicBody:
  141. return BODY_KINEMATIC;
  142. break;
  143. default:
  144. return BODY_INVALID;
  145. break;
  146. }
  147. }
  148. void Body::applyLinearImpulse(float jx, float jy, bool wake)
  149. {
  150. body->ApplyLinearImpulse(Physics::scaleDown(b2Vec2(jx, jy)), body->GetWorldCenter(), wake);
  151. }
  152. void Body::applyLinearImpulse(float jx, float jy, float rx, float ry, bool wake)
  153. {
  154. body->ApplyLinearImpulse(Physics::scaleDown(b2Vec2(jx, jy)), Physics::scaleDown(b2Vec2(rx, ry)), wake);
  155. }
  156. void Body::applyAngularImpulse(float impulse, bool wake)
  157. {
  158. // Angular impulse is in kg*m^2/s, meaning it needs to be scaled twice
  159. body->ApplyAngularImpulse(Physics::scaleDown(Physics::scaleDown(impulse)), wake);
  160. }
  161. void Body::applyTorque(float t, bool wake)
  162. {
  163. // Torque is in N*m, or kg*m^2/s^2, meaning it also needs to be scaled twice
  164. body->ApplyTorque(Physics::scaleDown(Physics::scaleDown(t)), wake);
  165. }
  166. void Body::applyForce(float fx, float fy, float rx, float ry, bool wake)
  167. {
  168. body->ApplyForce(Physics::scaleDown(b2Vec2(fx, fy)), Physics::scaleDown(b2Vec2(rx, ry)), wake);
  169. }
  170. void Body::applyForce(float fx, float fy, bool wake)
  171. {
  172. body->ApplyForceToCenter(Physics::scaleDown(b2Vec2(fx, fy)), wake);
  173. }
  174. void Body::setX(float x)
  175. {
  176. body->SetTransform(Physics::scaleDown(b2Vec2(x, getY())), getAngle());
  177. }
  178. void Body::setY(float y)
  179. {
  180. body->SetTransform(Physics::scaleDown(b2Vec2(getX(), y)), getAngle());
  181. }
  182. void Body::setLinearVelocity(float x, float y)
  183. {
  184. body->SetLinearVelocity(Physics::scaleDown(b2Vec2(x, y)));
  185. }
  186. void Body::setAngle(float d)
  187. {
  188. body->SetTransform(body->GetPosition(), d);
  189. }
  190. void Body::setAngularVelocity(float r)
  191. {
  192. body->SetAngularVelocity(r);
  193. }
  194. void Body::setPosition(float x, float y)
  195. {
  196. body->SetTransform(Physics::scaleDown(b2Vec2(x, y)), body->GetAngle());
  197. }
  198. void Body::setAngularDamping(float d)
  199. {
  200. body->SetAngularDamping(d);
  201. }
  202. void Body::setLinearDamping(float d)
  203. {
  204. body->SetLinearDamping(d);
  205. }
  206. void Body::resetMassData()
  207. {
  208. body->ResetMassData();
  209. }
  210. void Body::setMassData(float x, float y, float m, float i)
  211. {
  212. b2MassData massData;
  213. massData.center = Physics::scaleDown(b2Vec2(x, y));
  214. massData.mass = m;
  215. massData.I = Physics::scaleDown(Physics::scaleDown(i));
  216. body->SetMassData(&massData);
  217. }
  218. void Body::setMass(float m)
  219. {
  220. b2MassData data;
  221. body->GetMassData(&data);
  222. data.mass = m;
  223. body->SetMassData(&data);
  224. }
  225. void Body::setInertia(float i)
  226. {
  227. b2MassData massData;
  228. massData.center = body->GetLocalCenter();
  229. massData.mass = body->GetMass();
  230. massData.I = Physics::scaleDown(Physics::scaleDown(i));
  231. body->SetMassData(&massData);
  232. }
  233. void Body::setGravityScale(float scale)
  234. {
  235. body->SetGravityScale(scale);
  236. }
  237. void Body::setType(Body::Type type)
  238. {
  239. switch (type)
  240. {
  241. case Body::BODY_STATIC:
  242. body->SetType(b2_staticBody);
  243. break;
  244. case Body::BODY_DYNAMIC:
  245. body->SetType(b2_dynamicBody);
  246. break;
  247. case Body::BODY_KINEMATIC:
  248. body->SetType(b2_kinematicBody);
  249. break;
  250. default:
  251. break;
  252. }
  253. }
  254. void Body::getWorldPoint(float x, float y, float &x_o, float &y_o)
  255. {
  256. b2Vec2 v = Physics::scaleUp(body->GetWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  257. x_o = v.x;
  258. y_o = v.y;
  259. }
  260. void Body::getWorldVector(float x, float y, float &x_o, float &y_o)
  261. {
  262. b2Vec2 v = Physics::scaleUp(body->GetWorldVector(Physics::scaleDown(b2Vec2(x, y))));
  263. x_o = v.x;
  264. y_o = v.y;
  265. }
  266. int Body::getWorldPoints(lua_State *L)
  267. {
  268. int argc = lua_gettop(L);
  269. int vcount = (int)argc/2;
  270. // at least one point
  271. love::luax_assert_argc(L, 2);
  272. for (int i = 0; i<vcount; i++)
  273. {
  274. float x = (float)lua_tonumber(L, 1);
  275. float y = (float)lua_tonumber(L, 2);
  276. // Remove them, so we don't run out of stack space
  277. lua_remove(L, 1);
  278. lua_remove(L, 1);
  279. // Time for scaling
  280. b2Vec2 point = Physics::scaleUp(body->GetWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  281. // And then we push the result
  282. lua_pushnumber(L, point.x);
  283. lua_pushnumber(L, point.y);
  284. }
  285. return argc;
  286. }
  287. void Body::getLocalPoint(float x, float y, float &x_o, float &y_o)
  288. {
  289. b2Vec2 v = Physics::scaleUp(body->GetLocalPoint(Physics::scaleDown(b2Vec2(x, y))));
  290. x_o = v.x;
  291. y_o = v.y;
  292. }
  293. void Body::getLocalVector(float x, float y, float &x_o, float &y_o)
  294. {
  295. b2Vec2 v = Physics::scaleUp(body->GetLocalVector(Physics::scaleDown(b2Vec2(x, y))));
  296. x_o = v.x;
  297. y_o = v.y;
  298. }
  299. void Body::getLinearVelocityFromWorldPoint(float x, float y, float &x_o, float &y_o)
  300. {
  301. b2Vec2 v = Physics::scaleUp(body->GetLinearVelocityFromWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  302. x_o = v.x;
  303. y_o = v.y;
  304. }
  305. void Body::getLinearVelocityFromLocalPoint(float x, float y, float &x_o, float &y_o)
  306. {
  307. b2Vec2 v = Physics::scaleUp(body->GetLinearVelocityFromLocalPoint(Physics::scaleDown(b2Vec2(x, y))));
  308. x_o = v.x;
  309. y_o = v.y;
  310. }
  311. bool Body::isBullet() const
  312. {
  313. return body->IsBullet();
  314. }
  315. void Body::setBullet(bool bullet)
  316. {
  317. return body->SetBullet(bullet);
  318. }
  319. bool Body::isActive() const
  320. {
  321. return body->IsActive();
  322. }
  323. bool Body::isAwake() const
  324. {
  325. return body->IsAwake();
  326. }
  327. void Body::setSleepingAllowed(bool allow)
  328. {
  329. body->SetSleepingAllowed(allow);
  330. }
  331. bool Body::isSleepingAllowed() const
  332. {
  333. return body->IsSleepingAllowed();
  334. }
  335. void Body::setActive(bool active)
  336. {
  337. body->SetActive(active);
  338. }
  339. void Body::setAwake(bool awake)
  340. {
  341. body->SetAwake(awake);
  342. }
  343. void Body::setFixedRotation(bool fixed)
  344. {
  345. body->SetFixedRotation(fixed);
  346. }
  347. bool Body::isFixedRotation() const
  348. {
  349. return body->IsFixedRotation();
  350. }
  351. World *Body::getWorld() const
  352. {
  353. return world;
  354. }
  355. int Body::getFixtureList(lua_State *L) const
  356. {
  357. lua_newtable(L);
  358. b2Fixture *f = body->GetFixtureList();
  359. int i = 1;
  360. do
  361. {
  362. if (!f)
  363. break;
  364. Fixture *fixture = (Fixture *)Memoizer::find(f);
  365. if (!fixture)
  366. throw love::Exception("A fixture has escaped Memoizer!");
  367. fixture->retain();
  368. luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture);
  369. lua_rawseti(L, -2, i);
  370. i++;
  371. }
  372. while ((f = f->GetNext()));
  373. return 1;
  374. }
  375. b2Vec2 Body::getVector(lua_State *L)
  376. {
  377. love::luax_assert_argc(L, 2, 2);
  378. b2Vec2 v((float)lua_tonumber(L, 1), (float)lua_tonumber(L, 2));
  379. lua_pop(L, 2);
  380. return v;
  381. }
  382. int Body::pushVector(lua_State *L, const b2Vec2 &v)
  383. {
  384. lua_pushnumber(L, v.x);
  385. lua_pushnumber(L, v.y);
  386. return 2;
  387. }
  388. void Body::destroy()
  389. {
  390. if (world->world->IsLocked())
  391. {
  392. // Called during time step. Save reference for destruction afterwards.
  393. this->retain();
  394. world->destructBodies.push_back(this);
  395. return;
  396. }
  397. world->world->DestroyBody(body);
  398. Memoizer::remove(body);
  399. body = NULL;
  400. // Box2D body destroyed. Release its reference to the love Body.
  401. this->release();
  402. }
  403. } // box2d
  404. } // physics
  405. } // love