Body.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /**
  2. * Copyright (c) 2006-2011 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 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, 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)
  149. {
  150. body->ApplyLinearImpulse(Physics::scaleDown(b2Vec2(jx, jy)), body->GetWorldCenter());
  151. }
  152. void Body::applyLinearImpulse(float jx, float jy, float rx, float ry)
  153. {
  154. body->ApplyLinearImpulse(Physics::scaleDown(b2Vec2(jx, jy)), Physics::scaleDown(b2Vec2(rx, ry)));
  155. }
  156. void Body::applyAngularImpulse(float impulse)
  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)));
  160. }
  161. void Body::applyTorque(float t)
  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)));
  165. }
  166. void Body::applyForce(float fx, float fy, float rx, float ry)
  167. {
  168. body->ApplyForce(Physics::scaleDown(b2Vec2(fx, fy)), Physics::scaleDown(b2Vec2(rx, ry)));
  169. }
  170. void Body::applyForce(float fx, float fy)
  171. {
  172. body->ApplyForce(Physics::scaleDown(b2Vec2(fx, fy)), body->GetWorldCenter());
  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 = i;
  216. body->SetMassData(&massData);
  217. }
  218. void Body::setInertia(float i)
  219. {
  220. b2MassData massData;
  221. massData.center = body->GetLocalCenter();
  222. massData.mass = body->GetMass();
  223. massData.I = i;
  224. body->SetMassData(&massData);
  225. }
  226. void Body::setGravityScale(float scale)
  227. {
  228. body->SetGravityScale(scale);
  229. }
  230. void Body::setType(Body::Type type)
  231. {
  232. switch (type)
  233. {
  234. case Body::BODY_STATIC:
  235. body->SetType(b2_staticBody);
  236. break;
  237. case Body::BODY_DYNAMIC:
  238. body->SetType(b2_dynamicBody);
  239. break;
  240. case Body::BODY_KINEMATIC:
  241. body->SetType(b2_kinematicBody);
  242. break;
  243. default:
  244. break;
  245. }
  246. }
  247. void Body::getWorldPoint(float x, float y, float & x_o, float & y_o)
  248. {
  249. b2Vec2 v = Physics::scaleUp(body->GetWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  250. x_o = v.x;
  251. y_o = v.y;
  252. }
  253. void Body::getWorldVector(float x, float y, float & x_o, float & y_o)
  254. {
  255. b2Vec2 v = Physics::scaleUp(body->GetWorldVector(Physics::scaleDown(b2Vec2(x, y))));
  256. x_o = v.x;
  257. y_o = v.y;
  258. }
  259. int Body::getWorldPoints(lua_State * L)
  260. {
  261. int argc = lua_gettop(L);
  262. int vcount = (int)argc/2;
  263. // at least one point
  264. love::luax_assert_argc(L, 2);
  265. for (int i = 0;i<vcount;i++)
  266. {
  267. float x = (float)lua_tonumber(L, i*2+1);
  268. float y = (float)lua_tonumber(L, i*2+2);
  269. b2Vec2 point = Physics::scaleUp(body->GetWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  270. lua_pushnumber(L, point.x);
  271. lua_pushnumber(L, point.y);
  272. }
  273. return argc;
  274. }
  275. void Body::getLocalPoint(float x, float y, float & x_o, float & y_o)
  276. {
  277. b2Vec2 v = Physics::scaleUp(body->GetLocalPoint(Physics::scaleDown(b2Vec2(x, y))));
  278. x_o = v.x;
  279. y_o = v.y;
  280. }
  281. void Body::getLocalVector(float x, float y, float & x_o, float & y_o)
  282. {
  283. b2Vec2 v = Physics::scaleUp(body->GetLocalVector(Physics::scaleDown(b2Vec2(x, y))));
  284. x_o = v.x;
  285. y_o = v.y;
  286. }
  287. void Body::getLinearVelocityFromWorldPoint(float x, float y, float & x_o, float & y_o)
  288. {
  289. b2Vec2 v = Physics::scaleUp(body->GetLinearVelocityFromWorldPoint(Physics::scaleDown(b2Vec2(x, y))));
  290. x_o = v.x;
  291. y_o = v.y;
  292. }
  293. void Body::getLinearVelocityFromLocalPoint(float x, float y, float & x_o, float & y_o)
  294. {
  295. b2Vec2 v = Physics::scaleUp(body->GetLinearVelocityFromLocalPoint(Physics::scaleDown(b2Vec2(x, y))));
  296. x_o = v.x;
  297. y_o = v.y;
  298. }
  299. bool Body::isBullet() const
  300. {
  301. return body->IsBullet();
  302. }
  303. void Body::setBullet(bool bullet)
  304. {
  305. return body->SetBullet(bullet);
  306. }
  307. bool Body::isActive() const
  308. {
  309. return body->IsActive();
  310. }
  311. bool Body::isAwake() const
  312. {
  313. return body->IsAwake();
  314. }
  315. void Body::setSleepingAllowed(bool allow)
  316. {
  317. body->SetSleepingAllowed(allow);
  318. }
  319. bool Body::isSleepingAllowed() const
  320. {
  321. return body->IsSleepingAllowed();
  322. }
  323. void Body::setActive(bool active)
  324. {
  325. body->SetActive(active);
  326. }
  327. void Body::setAwake(bool awake)
  328. {
  329. body->SetAwake(awake);
  330. }
  331. void Body::setFixedRotation(bool fixed)
  332. {
  333. body->SetFixedRotation(fixed);
  334. }
  335. bool Body::isFixedRotation() const
  336. {
  337. return body->IsFixedRotation();
  338. }
  339. World * Body::getWorld() const
  340. {
  341. return world;
  342. }
  343. int Body::getFixtureList(lua_State * L) const
  344. {
  345. lua_newtable(L);
  346. b2Fixture * f = body->GetFixtureList();
  347. int i = 1;
  348. do {
  349. if (!f)
  350. break;
  351. Fixture * fixture = (Fixture *)Memoizer::find(f);
  352. if (!fixture)
  353. throw love::Exception("A fixture has escaped Memoizer!");
  354. fixture->retain();
  355. luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)fixture);
  356. lua_rawseti(L, -2, i);
  357. i++;
  358. } while ((f = f->GetNext()));
  359. return 1;
  360. }
  361. b2Vec2 Body::getVector(lua_State * L)
  362. {
  363. love::luax_assert_argc(L, 2, 2);
  364. b2Vec2 v((float)lua_tonumber(L, 1), (float)lua_tonumber(L, 2));
  365. lua_pop(L, 2);
  366. return v;
  367. }
  368. int Body::pushVector(lua_State * L, const b2Vec2 & v)
  369. {
  370. lua_pushnumber(L, v.x);
  371. lua_pushnumber(L, v.y);
  372. return 2;
  373. }
  374. void Body::destroy()
  375. {
  376. if (world->world->IsLocked())
  377. {
  378. // Called during time step. Save reference for destruction afterwards.
  379. this->retain();
  380. world->destructBodies.push_back(this);
  381. return;
  382. }
  383. world->world->DestroyBody(body);
  384. Memoizer::remove(body);
  385. body = NULL;
  386. // Box2D body destroyed. Release its reference to the love Body.
  387. this->release();
  388. }
  389. } // box2d
  390. } // physics
  391. } // love