body_2d_sw.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /*************************************************************************/
  2. /* body_2d_sw.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "body_2d_sw.h"
  30. #include "space_2d_sw.h"
  31. #include "area_2d_sw.h"
  32. void Body2DSW::_update_inertia() {
  33. if (get_space() && !inertia_update_list.in_list())
  34. get_space()->body_add_to_inertia_update_list(&inertia_update_list);
  35. }
  36. void Body2DSW::update_inertias() {
  37. //update shapes and motions
  38. switch(mode) {
  39. case Physics2DServer::BODY_MODE_RIGID: {
  40. //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
  41. float total_area=0;
  42. for (int i=0;i<get_shape_count();i++) {
  43. total_area+=get_shape_aabb(i).get_area();
  44. }
  45. real_t _inertia=0;
  46. for (int i=0;i<get_shape_count();i++) {
  47. const Shape2DSW* shape=get_shape(i);
  48. float area=get_shape_aabb(i).get_area();
  49. float mass = area * this->mass / total_area;
  50. Matrix32 mtx = get_shape_transform(i);
  51. Vector2 scale = mtx.get_scale();
  52. _inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared();
  53. //Rect2 ab = get_shape_aabb(i);
  54. //_inertia+=mass*ab.size.dot(ab.size)/12.0f;
  55. }
  56. if (_inertia!=0)
  57. _inv_inertia=1.0/_inertia;
  58. else
  59. _inv_inertia=0.0; //wathever
  60. if (mass)
  61. _inv_mass=1.0/mass;
  62. else
  63. _inv_mass=0;
  64. } break;
  65. case Physics2DServer::BODY_MODE_KINEMATIC:
  66. case Physics2DServer::BODY_MODE_STATIC: {
  67. _inv_inertia=0;
  68. _inv_mass=0;
  69. } break;
  70. case Physics2DServer::BODY_MODE_CHARACTER: {
  71. _inv_inertia=0;
  72. _inv_mass=1.0/mass;
  73. } break;
  74. }
  75. //_update_inertia_tensor();
  76. //_update_shapes();
  77. }
  78. void Body2DSW::set_active(bool p_active) {
  79. if (active==p_active)
  80. return;
  81. active=p_active;
  82. if (!p_active) {
  83. if (get_space())
  84. get_space()->body_remove_from_active_list(&active_list);
  85. } else {
  86. if (mode==Physics2DServer::BODY_MODE_STATIC)
  87. return; //static bodies can't become active
  88. if (get_space())
  89. get_space()->body_add_to_active_list(&active_list);
  90. //still_time=0;
  91. }
  92. /*
  93. if (!space)
  94. return;
  95. for(int i=0;i<get_shape_count();i++) {
  96. Shape &s=shapes[i];
  97. if (s.bpid>0) {
  98. get_space()->get_broadphase()->set_active(s.bpid,active);
  99. }
  100. }
  101. */
  102. }
  103. void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) {
  104. switch(p_param) {
  105. case Physics2DServer::BODY_PARAM_BOUNCE: {
  106. bounce=p_value;
  107. } break;
  108. case Physics2DServer::BODY_PARAM_FRICTION: {
  109. friction=p_value;
  110. } break;
  111. case Physics2DServer::BODY_PARAM_MASS: {
  112. ERR_FAIL_COND(p_value<=0);
  113. mass=p_value;
  114. _update_inertia();
  115. } break;
  116. case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: {
  117. gravity_scale=p_value;
  118. } break;
  119. case Physics2DServer::BODY_PARAM_LINEAR_DAMP: {
  120. linear_damp=p_value;
  121. } break;
  122. case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: {
  123. angular_damp=p_value;
  124. } break;
  125. default:{}
  126. }
  127. }
  128. float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
  129. switch(p_param) {
  130. case Physics2DServer::BODY_PARAM_BOUNCE: {
  131. return bounce;
  132. } break;
  133. case Physics2DServer::BODY_PARAM_FRICTION: {
  134. return friction;
  135. } break;
  136. case Physics2DServer::BODY_PARAM_MASS: {
  137. return mass;
  138. } break;
  139. case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: {
  140. return gravity_scale;
  141. } break;
  142. case Physics2DServer::BODY_PARAM_LINEAR_DAMP: {
  143. return linear_damp;
  144. } break;
  145. case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: {
  146. return angular_damp;
  147. } break;
  148. default:{}
  149. }
  150. return 0;
  151. }
  152. void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
  153. Physics2DServer::BodyMode prev=mode;
  154. mode=p_mode;
  155. switch(p_mode) {
  156. //CLEAR UP EVERYTHING IN CASE IT NOT WORKS!
  157. case Physics2DServer::BODY_MODE_STATIC:
  158. case Physics2DServer::BODY_MODE_KINEMATIC: {
  159. _set_inv_transform(get_transform().affine_inverse());
  160. _inv_mass=0;
  161. _set_static(p_mode==Physics2DServer::BODY_MODE_STATIC);
  162. set_active(p_mode==Physics2DServer::BODY_MODE_KINEMATIC && contacts.size());
  163. linear_velocity=Vector2();
  164. angular_velocity=0;
  165. if (mode==Physics2DServer::BODY_MODE_KINEMATIC && prev!=mode) {
  166. first_time_kinematic=true;
  167. }
  168. } break;
  169. case Physics2DServer::BODY_MODE_RIGID: {
  170. _inv_mass=mass>0?(1.0/mass):0;
  171. _set_static(false);
  172. } break;
  173. case Physics2DServer::BODY_MODE_CHARACTER: {
  174. _inv_mass=mass>0?(1.0/mass):0;
  175. _set_static(false);
  176. } break;
  177. }
  178. _update_inertia();
  179. //if (get_space())
  180. // _update_queries();
  181. }
  182. Physics2DServer::BodyMode Body2DSW::get_mode() const {
  183. return mode;
  184. }
  185. void Body2DSW::_shapes_changed() {
  186. _update_inertia();
  187. wakeup_neighbours();
  188. }
  189. void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_variant) {
  190. switch(p_state) {
  191. case Physics2DServer::BODY_STATE_TRANSFORM: {
  192. if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
  193. new_transform=p_variant;
  194. //wakeup_neighbours();
  195. set_active(true);
  196. if (first_time_kinematic) {
  197. _set_transform(p_variant);
  198. _set_inv_transform(get_transform().affine_inverse());
  199. first_time_kinematic=false;
  200. }
  201. } else if (mode==Physics2DServer::BODY_MODE_STATIC) {
  202. _set_transform(p_variant);
  203. _set_inv_transform(get_transform().affine_inverse());
  204. wakeup_neighbours();
  205. } else {
  206. Matrix32 t = p_variant;
  207. t.orthonormalize();
  208. new_transform=get_transform(); //used as old to compute motion
  209. if (t==new_transform)
  210. break;
  211. _set_transform(t);
  212. _set_inv_transform(get_transform().inverse());
  213. }
  214. wakeup();
  215. } break;
  216. case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: {
  217. //if (mode==Physics2DServer::BODY_MODE_STATIC)
  218. // break;
  219. linear_velocity=p_variant;
  220. wakeup();
  221. } break;
  222. case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: {
  223. //if (mode!=Physics2DServer::BODY_MODE_RIGID)
  224. // break;
  225. angular_velocity=p_variant;
  226. wakeup();
  227. } break;
  228. case Physics2DServer::BODY_STATE_SLEEPING: {
  229. //?
  230. if (mode==Physics2DServer::BODY_MODE_STATIC || mode==Physics2DServer::BODY_MODE_KINEMATIC)
  231. break;
  232. bool do_sleep=p_variant;
  233. if (do_sleep) {
  234. linear_velocity=Vector2();
  235. //biased_linear_velocity=Vector3();
  236. angular_velocity=0;
  237. //biased_angular_velocity=Vector3();
  238. set_active(false);
  239. } else {
  240. if (mode!=Physics2DServer::BODY_MODE_STATIC)
  241. set_active(true);
  242. }
  243. } break;
  244. case Physics2DServer::BODY_STATE_CAN_SLEEP: {
  245. can_sleep=p_variant;
  246. if (mode==Physics2DServer::BODY_MODE_RIGID && !active && !can_sleep)
  247. set_active(true);
  248. } break;
  249. }
  250. }
  251. Variant Body2DSW::get_state(Physics2DServer::BodyState p_state) const {
  252. switch(p_state) {
  253. case Physics2DServer::BODY_STATE_TRANSFORM: {
  254. return get_transform();
  255. } break;
  256. case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: {
  257. return linear_velocity;
  258. } break;
  259. case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: {
  260. return angular_velocity;
  261. } break;
  262. case Physics2DServer::BODY_STATE_SLEEPING: {
  263. return !is_active();
  264. } break;
  265. case Physics2DServer::BODY_STATE_CAN_SLEEP: {
  266. return can_sleep;
  267. } break;
  268. }
  269. return Variant();
  270. }
  271. void Body2DSW::set_space(Space2DSW *p_space){
  272. if (get_space()) {
  273. wakeup_neighbours();
  274. if (inertia_update_list.in_list())
  275. get_space()->body_remove_from_inertia_update_list(&inertia_update_list);
  276. if (active_list.in_list())
  277. get_space()->body_remove_from_active_list(&active_list);
  278. if (direct_state_query_list.in_list())
  279. get_space()->body_remove_from_state_query_list(&direct_state_query_list);
  280. }
  281. _set_space(p_space);
  282. if (get_space()) {
  283. _update_inertia();
  284. if (active)
  285. get_space()->body_add_to_active_list(&active_list);
  286. // _update_queries();
  287. //if (is_active()) {
  288. // active=false;
  289. // set_active(true);
  290. //}
  291. }
  292. }
  293. void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) {
  294. if (p_area->is_gravity_point()) {
  295. gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity();
  296. } else {
  297. gravity += p_area->get_gravity_vector() * p_area->get_gravity();
  298. }
  299. }
  300. void Body2DSW::integrate_forces(real_t p_step) {
  301. if (mode==Physics2DServer::BODY_MODE_STATIC)
  302. return;
  303. Area2DSW *def_area = get_space()->get_default_area();
  304. Area2DSW *damp_area = def_area;
  305. ERR_FAIL_COND(!def_area);
  306. int ac = areas.size();
  307. bool replace = false;
  308. gravity=Vector2(0,0);
  309. if (ac) {
  310. areas.sort();
  311. const AreaCMP *aa = &areas[0];
  312. damp_area = aa[ac-1].area;
  313. for(int i=ac-1;i>=0;i--) {
  314. _compute_area_gravity(aa[i].area);
  315. if (aa[i].area->get_space_override_mode() == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE) {
  316. replace = true;
  317. break;
  318. }
  319. }
  320. }
  321. if( !replace ) {
  322. _compute_area_gravity(def_area);
  323. }
  324. gravity*=gravity_scale;
  325. if (angular_damp>=0)
  326. area_angular_damp=angular_damp;
  327. else
  328. area_angular_damp=damp_area->get_angular_damp();
  329. if (linear_damp>=0)
  330. area_linear_damp=linear_damp;
  331. else
  332. area_linear_damp=damp_area->get_linear_damp();
  333. Vector2 motion;
  334. bool do_motion=false;
  335. if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
  336. //compute motion, angular and etc. velocities from prev transform
  337. linear_velocity = (new_transform.elements[2] - get_transform().elements[2])/p_step;
  338. real_t rot = new_transform.affine_inverse().basis_xform(get_transform().elements[1]).atan2();
  339. angular_velocity = rot / p_step;
  340. motion = new_transform.elements[2] - get_transform().elements[2];
  341. do_motion=true;
  342. //for(int i=0;i<get_shape_count();i++) {
  343. // set_shape_kinematic_advance(i,Vector2());
  344. // set_shape_kinematic_retreat(i,0);
  345. //}
  346. } else {
  347. if (!omit_force_integration) {
  348. //overriden by direct state query
  349. Vector2 force=gravity*mass;
  350. force+=applied_force;
  351. real_t torque=applied_torque;
  352. real_t damp = 1.0 - p_step * area_linear_damp;
  353. if (damp<0) // reached zero in the given time
  354. damp=0;
  355. real_t angular_damp = 1.0 - p_step * area_angular_damp;
  356. if (angular_damp<0) // reached zero in the given time
  357. angular_damp=0;
  358. linear_velocity*=damp;
  359. angular_velocity*=angular_damp;
  360. linear_velocity+=_inv_mass * force * p_step;
  361. angular_velocity+=_inv_inertia * torque * p_step;
  362. }
  363. if (continuous_cd_mode!=Physics2DServer::CCD_MODE_DISABLED) {
  364. motion = new_transform.get_origin() - get_transform().get_origin();
  365. //linear_velocity*p_step;
  366. do_motion=true;
  367. }
  368. }
  369. //motion=linear_velocity*p_step;
  370. biased_angular_velocity=0;
  371. biased_linear_velocity=Vector2();
  372. if (do_motion) {//shapes temporarily extend for raycast
  373. _update_shapes_with_motion(motion);
  374. }
  375. damp_area=NULL; // clear the area, so it is set in the next frame
  376. def_area=NULL; // clear the area, so it is set in the next frame
  377. contact_count=0;
  378. }
  379. void Body2DSW::integrate_velocities(real_t p_step) {
  380. if (mode==Physics2DServer::BODY_MODE_STATIC)
  381. return;
  382. if (fi_callback)
  383. get_space()->body_add_to_state_query_list(&direct_state_query_list);
  384. if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
  385. _set_transform(new_transform,false);
  386. _set_inv_transform(new_transform.affine_inverse());
  387. if (contacts.size()==0 && linear_velocity==Vector2() && angular_velocity==0)
  388. set_active(false); //stopped moving, deactivate
  389. return;
  390. }
  391. real_t total_angular_velocity = angular_velocity+biased_angular_velocity;
  392. Vector2 total_linear_velocity=linear_velocity+biased_linear_velocity;
  393. real_t angle = get_transform().get_rotation() - total_angular_velocity * p_step;
  394. Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;
  395. _set_transform(Matrix32(angle,pos),continuous_cd_mode==Physics2DServer::CCD_MODE_DISABLED);
  396. _set_inv_transform(get_transform().inverse());
  397. if (continuous_cd_mode!=Physics2DServer::CCD_MODE_DISABLED)
  398. new_transform=get_transform();
  399. //_update_inertia_tensor();
  400. }
  401. void Body2DSW::wakeup_neighbours() {
  402. for(Map<Constraint2DSW*,int>::Element *E=constraint_map.front();E;E=E->next()) {
  403. const Constraint2DSW *c=E->key();
  404. Body2DSW **n = c->get_body_ptr();
  405. int bc=c->get_body_count();
  406. for(int i=0;i<bc;i++) {
  407. if (i==E->get())
  408. continue;
  409. Body2DSW *b = n[i];
  410. if (b->mode!=Physics2DServer::BODY_MODE_RIGID)
  411. continue;
  412. if (!b->is_active())
  413. b->set_active(true);
  414. }
  415. }
  416. }
  417. void Body2DSW::call_queries() {
  418. if (fi_callback) {
  419. Physics2DDirectBodyStateSW *dbs = Physics2DDirectBodyStateSW::singleton;
  420. dbs->body=this;
  421. Variant v=dbs;
  422. const Variant *vp[2]={&v,&fi_callback->callback_udata};
  423. Object *obj = ObjectDB::get_instance(fi_callback->id);
  424. if (!obj) {
  425. set_force_integration_callback(0,StringName());
  426. } else {
  427. Variant::CallError ce;
  428. if (fi_callback->callback_udata.get_type()) {
  429. obj->call(fi_callback->method,vp,2,ce);
  430. } else {
  431. obj->call(fi_callback->method,vp,1,ce);
  432. }
  433. }
  434. }
  435. }
  436. bool Body2DSW::sleep_test(real_t p_step) {
  437. if (mode==Physics2DServer::BODY_MODE_STATIC || mode==Physics2DServer::BODY_MODE_KINEMATIC)
  438. return true; //
  439. else if (mode==Physics2DServer::BODY_MODE_CHARACTER)
  440. return !active; // characters and kinematic bodies don't sleep unless asked to sleep
  441. else if (!can_sleep)
  442. return false;
  443. if (Math::abs(angular_velocity)<get_space()->get_body_angular_velocity_sleep_treshold() && Math::abs(linear_velocity.length_squared()) < get_space()->get_body_linear_velocity_sleep_treshold()*get_space()->get_body_linear_velocity_sleep_treshold()) {
  444. still_time+=p_step;
  445. return still_time > get_space()->get_body_time_to_sleep();
  446. } else {
  447. still_time=0; //maybe this should be set to 0 on set_active?
  448. return false;
  449. }
  450. }
  451. void Body2DSW::set_force_integration_callback(ObjectID p_id,const StringName& p_method,const Variant& p_udata) {
  452. if (fi_callback) {
  453. memdelete(fi_callback);
  454. fi_callback=NULL;
  455. }
  456. if (p_id!=0) {
  457. fi_callback=memnew(ForceIntegrationCallback);
  458. fi_callback->id=p_id;
  459. fi_callback->method=p_method;
  460. fi_callback->callback_udata=p_udata;
  461. }
  462. }
  463. Body2DSW::Body2DSW() : CollisionObject2DSW(TYPE_BODY), active_list(this), inertia_update_list(this), direct_state_query_list(this) {
  464. mode=Physics2DServer::BODY_MODE_RIGID;
  465. active=true;
  466. angular_velocity=0;
  467. biased_angular_velocity=0;
  468. mass=1;
  469. _inv_inertia=0;
  470. _inv_mass=1;
  471. bounce=0;
  472. friction=1;
  473. omit_force_integration=false;
  474. applied_torque=0;
  475. island_step=0;
  476. island_next=NULL;
  477. island_list_next=NULL;
  478. _set_static(false);
  479. first_time_kinematic=false;
  480. linear_damp=-1;
  481. angular_damp=-1;
  482. area_angular_damp=0;
  483. area_linear_damp=0;
  484. contact_count=0;
  485. gravity_scale=1.0;
  486. using_one_way_cache=false;
  487. one_way_collision_max_depth=0.1;
  488. still_time=0;
  489. continuous_cd_mode=Physics2DServer::CCD_MODE_DISABLED;
  490. can_sleep=false;
  491. fi_callback=NULL;
  492. }
  493. Body2DSW::~Body2DSW() {
  494. if (fi_callback)
  495. memdelete(fi_callback);
  496. }
  497. Physics2DDirectBodyStateSW *Physics2DDirectBodyStateSW::singleton=NULL;
  498. Physics2DDirectSpaceState* Physics2DDirectBodyStateSW::get_space_state() {
  499. return body->get_space()->get_direct_state();
  500. }