physics.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. #include "corange.h"
  2. typedef SDL_Event event;
  3. static renderer * dr = NULL;
  4. static bool gravity_enable = true;
  5. static bool running = true;
  6. static float max_po = 150.0;
  7. static float max_po_new = 150.0;
  8. static event event_common_event = { 0 };
  9. static bool event_common_state = false;
  10. /*see code bottom main() custom physics handlers becouse original code in wip long time :) */
  11. void physics_object_update_custom(physics_object * po,float ftime);
  12. void physics_object_collide_static_custom(physics_object * po,static_object * so,float ftime);
  13. void splash();
  14. vec2 mouse_get_position(void)
  15. {
  16. int x=0;
  17. int y=0;
  18. SDL_GetMouseState(&x,&y);
  19. return (vec2){(float)x,(float)y};
  20. }
  21. inline static event event_get()
  22. {
  23. return event_common_event;
  24. }
  25. bool event_update()
  26. {
  27. event_common_state = SDL_PollEvent(&event_common_event);
  28. return event_common_state;
  29. }
  30. void exit_callback(ui_button * btn,void * data)
  31. {
  32. running = false;
  33. }
  34. void random_callback(ui_button * btn, void * data)
  35. {
  36. ui_toast_popup("Drop balls random");
  37. for (int i = 0; i < max_po; i++)
  38. {
  39. physics_object * po = entity_get("po%i",i);
  40. po->velocity.x -=randf_range(-0.5,0.5);
  41. po->velocity.y +=randf_range(-1,1);
  42. po->velocity.z +=randf_range(-0.5,0.5);
  43. };
  44. }
  45. void drop_callback(ui_button * btn, void * data)
  46. {
  47. ui_toast_popup("Drop balls");
  48. vec3 * velocity = (vec3*)data;
  49. for (int i = 0; i < max_po; i++)
  50. {
  51. physics_object * po = entity_get("po%i",i);
  52. po->velocity = *velocity;
  53. };
  54. }
  55. void gravity_trigger(ui_button * btn, void * data)
  56. {
  57. gravity_enable =!gravity_enable;
  58. if(gravity_enable)
  59. {
  60. btn->up_color = vec4_green();
  61. ui_toast_popup("Gravity Enable");
  62. }else{
  63. btn->up_color = vec4_red();
  64. ui_toast_popup("Gravity Disable");
  65. };
  66. }
  67. void disable_dialog(ui_button * btn,void * data)
  68. {
  69. ui_elem_delete("help");
  70. }
  71. void respawn_callback(ui_button * btn,void * data)
  72. {
  73. ui_toast_popup("Respawn new balls");
  74. for (int i = 0; i < max_po; ++i)
  75. {
  76. entity_delete("po%i",i);
  77. entity_delete("poc%i",i);
  78. }
  79. if(max_po != max_po_new)
  80. {
  81. max_po = max_po_new;
  82. };
  83. for (int i = 0; i < max_po; i++)
  84. {
  85. physics_object * po = entity_new("po%i", physics_object,i);
  86. po->renderable = asset_hndl_new_load(P("./assets/po/sphere.obj"));
  87. po->position = vec3_new(0,i,0);
  88. po->scale = vec3_new(5,5,5);
  89. po->collision_body = asset_hndl_new_load(P("$CORANGE/objects/sphere.col"));
  90. /*duplicate objects for renderer becouse physic_object not implement*/
  91. static_object * poc = entity_new("poc%i", static_object,i);
  92. poc->renderable = asset_hndl_new_load(P("./assets/po/sphere.obj"));
  93. poc->position = vec3_new(0,i,0);
  94. poc->scale = vec3_new(5,i,5);
  95. renderable * pocr = asset_hndl_ptr(&poc->renderable);
  96. pocr->material = asset_hndl_new_load(P("./assets/po/material.mat"));
  97. }
  98. }
  99. int main(int argc, char *argv[])
  100. {
  101. corange_init("../../assets_core");
  102. graphics_viewport_set_size(1280,720);
  103. graphics_viewport_set_title("Physics Demo Experiment");
  104. folder_load_recursive(P("./assets/"));
  105. splash();
  106. extern ui_style * ui_style_current;
  107. ui_style_current->box_back_image = P("./assets/theme/ui.tga");
  108. dr = renderer_new(asset_hndl_new_load(P("./graphics.cfg")));
  109. dr->mesh_skydome = asset_hndl_new_load(P("./assets/po/sphere.obj"));
  110. entity_new("cam",camera);
  111. entity_get_as("cam",camera)->position = vec3_new(1.93,147.0,139.98);
  112. entity_get_as("cam",camera)->far_clip *=4;
  113. renderer_set_camera(dr,entity_get("cam"));
  114. renderer_set_skydome_enabled(dr,true);
  115. renderer_set_tod(dr,0.17,1);
  116. ui_elem_new("framerate",ui_button);
  117. ui_button_move(ui_elem_get("framerate"),vec2_new(10,10));
  118. ui_button_resize(ui_elem_get("framerate"),vec2_new(80,30));
  119. ui_elem_new("respawn",ui_button);
  120. ui_elem_new("drop up",ui_button);
  121. ui_elem_new("drop down",ui_button);
  122. ui_elem_new("drop left",ui_button);
  123. ui_elem_new("drop right",ui_button);
  124. ui_elem_new("drop forw",ui_button);
  125. ui_elem_new("drop back",ui_button);
  126. ui_button * gravity = ui_elem_new("gravity",ui_button);
  127. gravity->up_color = vec4_green();
  128. ui_button * exit_btn = ui_elem_new("exit",ui_button);
  129. exit_btn->up_color = vec4_red();
  130. ui_button_set_onclick(ui_elem_get("respawn"),respawn_callback);
  131. ui_button_set_onclick(ui_elem_get("drop up"),drop_callback);
  132. ui_button_set_onclick(ui_elem_get("drop down"),drop_callback);
  133. ui_button_set_onclick(ui_elem_get("drop left"),drop_callback);
  134. ui_button_set_onclick(ui_elem_get("drop right"),drop_callback);
  135. ui_button_set_onclick(ui_elem_get("drop forw"),drop_callback);
  136. ui_button_set_onclick(ui_elem_get("drop back"),drop_callback);
  137. ui_button_set_onclick(ui_elem_get("exit"),exit_callback);
  138. ui_button_set_onclick(ui_elem_get("gravity"),gravity_trigger);
  139. enum
  140. {
  141. veloc_top,
  142. veloc_down,
  143. veloc_left,
  144. veloc_right,
  145. veloc_forw,
  146. veloc_back
  147. };
  148. vec3 veloc[] =
  149. {
  150. [0] = {0,2,0},
  151. [1] = {0,0,0},
  152. [2] = {-2,0,0},
  153. [3] = {2,0,0},
  154. [4] = {0,0,-2},
  155. [5] = {0,0,2}
  156. };
  157. ui_button_set_onclick_data(ui_elem_get("drop up"),&veloc[0]);
  158. ui_button_set_onclick_data(ui_elem_get("drop down"),&veloc[1]);
  159. ui_button_set_onclick_data(ui_elem_get("drop left"),&veloc[2]);
  160. ui_button_set_onclick_data(ui_elem_get("drop right"),&veloc[3]);
  161. ui_button_set_onclick_data(ui_elem_get("drop forw"),&veloc[4]);
  162. ui_button_set_onclick_data(ui_elem_get("drop back"),&veloc[5]);
  163. ui_button_set_label(ui_elem_get("respawn"),"respawn [r]");
  164. ui_button_set_label(ui_elem_get("drop up"),"drop up");
  165. ui_button_set_label(ui_elem_get("drop down"),"drop down");
  166. ui_button_set_label(ui_elem_get("drop left"),"drop left");
  167. ui_button_set_label(ui_elem_get("drop right"),"drop right");
  168. ui_button_set_label(ui_elem_get("drop forw"),"drop forw");
  169. ui_button_set_label(ui_elem_get("drop back"),"drop back");
  170. ui_button_set_label(ui_elem_get("exit"),"exit");
  171. ui_button_set_label(ui_elem_get("gravity"),"gravity [e]");
  172. ui_button_resize(ui_elem_get("respawn"),vec2_new(100,30));
  173. ui_button_resize(ui_elem_get("drop up"),vec2_new(100,30));
  174. ui_button_resize(ui_elem_get("drop down"),vec2_new(100,30));
  175. ui_button_resize(ui_elem_get("drop left"),vec2_new(100,30));
  176. ui_button_resize(ui_elem_get("drop right"),vec2_new(100,30));
  177. ui_button_resize(ui_elem_get("drop forw"),vec2_new(100,30));
  178. ui_button_resize(ui_elem_get("drop back"),vec2_new(100,30));
  179. ui_button_resize(ui_elem_get("exit"),vec2_new(100,30));
  180. ui_button_resize(ui_elem_get("gravity"),vec2_new(100,30));
  181. ui_button_move(ui_elem_get("respawn"),vec2_new(100,10));
  182. ui_button_move(ui_elem_get("drop up"),vec2_new(210,10));
  183. ui_button_move(ui_elem_get("drop down"),vec2_new(320,10));
  184. ui_button_move(ui_elem_get("drop left"),vec2_new(430,10));
  185. ui_button_move(ui_elem_get("drop right"),vec2_new(540,10));
  186. ui_button_move(ui_elem_get("drop forw"),vec2_new(650,10));
  187. ui_button_move(ui_elem_get("drop back"),vec2_new(760,10));
  188. ui_button_move(ui_elem_get("exit"),vec2_new(1170,10));
  189. ui_button_move(ui_elem_get("gravity"),vec2_new(870,10));
  190. ui_slider * podium = ui_elem_new("podium",ui_slider);
  191. podium->active = true;
  192. podium->pressed = false;
  193. podium->bar->color = vec4_red();
  194. podium->slot->color = vec4_green();
  195. ui_slider_move(ui_elem_get("podium"),vec2_new(10,655));
  196. ui_slider_set_label(ui_elem_get("podium"),"podium y axis");
  197. ui_slider_set_amount(ui_elem_get("podium"),0);
  198. ui_slider * objects = ui_elem_new("objects",ui_slider);
  199. objects->active = true;
  200. objects->pressed = false;
  201. objects->bar->color = vec4_red();
  202. objects->slot->color = vec4_green();
  203. ui_slider_move(ui_elem_get("objects"),vec2_new(510,655));
  204. ui_slider_set_label(ui_elem_get("objects"),"balls num");
  205. ui_slider_set_amount(ui_elem_get("objects"),0.1);
  206. ui_elem_new("w",ui_button);
  207. ui_elem_new("a",ui_button);
  208. ui_elem_new("s",ui_button);
  209. ui_elem_new("d",ui_button);
  210. ui_elem_new("space",ui_button);
  211. ui_button_set_onclick(ui_elem_get("space"),random_callback);
  212. ui_button_set_onclick(ui_elem_get("w"),drop_callback);
  213. ui_button_set_onclick(ui_elem_get("s"),drop_callback);
  214. ui_button_set_onclick(ui_elem_get("a"),drop_callback);
  215. ui_button_set_onclick(ui_elem_get("d"),drop_callback);
  216. ui_button_set_onclick_data(ui_elem_get("w"),&veloc[4]);
  217. ui_button_set_onclick_data(ui_elem_get("s"),&veloc[5]);
  218. ui_button_set_onclick_data(ui_elem_get("a"),&veloc[2]);
  219. ui_button_set_onclick_data(ui_elem_get("d"),&veloc[3]);
  220. ui_button_set_label(ui_elem_get("w"),"u");
  221. ui_button_set_label(ui_elem_get("a"),"l");
  222. ui_button_set_label(ui_elem_get("s"),"d");
  223. ui_button_set_label(ui_elem_get("d"),"s");
  224. ui_button_set_label(ui_elem_get("space"),"space [random]");
  225. ui_button_resize(ui_elem_get("w"),vec2_new(30,30));
  226. ui_button_resize(ui_elem_get("a"),vec2_new(30,30));
  227. ui_button_resize(ui_elem_get("s"),vec2_new(30,30));
  228. ui_button_resize(ui_elem_get("d"),vec2_new(30,30));
  229. ui_button_resize(ui_elem_get("space"),vec2_new(150,30));
  230. ui_button_move(ui_elem_get("w"),vec2_new(1195,620));
  231. ui_button_move(ui_elem_get("a"),vec2_new(1160,655));
  232. ui_button_move(ui_elem_get("s"),vec2_new(1195,655));
  233. ui_button_move(ui_elem_get("d"),vec2_new(1230,655));
  234. ui_button_move(ui_elem_get("space"),vec2_new(1000,655));
  235. ui_dialog * help = ui_elem_new("help",ui_dialog);
  236. ui_rectangle_set_texture(help->back->back,asset_hndl_new_load(P("./assets/theme/help.tga")),0,0,false);
  237. help->contents->color = vec4_green();
  238. help->contents->scale = vec2_new(1.1,1.1);
  239. ui_dialog_set_single_button(ui_elem_get("help"),true);
  240. ui_dialog_set_title(ui_elem_get("help"),"");
  241. ui_dialog_set_contents(ui_elem_get("help"),
  242. "drop balls [up/down/left/right]\n"
  243. "drop balls random [space]\n"
  244. "on/off gravity [e]\n"
  245. "respawn balls [r]\n");
  246. ui_dialog_set_button_left(ui_elem_get("help"),"Ok",disable_dialog);
  247. //generate first objects
  248. for (int i = 0; i < max_po; i++)
  249. {
  250. physics_object * po = entity_new("po%i", physics_object,i);
  251. po->renderable = asset_hndl_new_load(P("./assets/po/sphere.obj"));
  252. po->position = vec3_new(0,i,0);
  253. po->scale = vec3_new(5,5,5);
  254. po->collision_body = asset_hndl_new_load(P("$CORANGE/objects/sphere.col"));
  255. static_object * poc = entity_new("poc%i", static_object,i);
  256. poc->renderable = asset_hndl_new_load(P("./assets/po/sphere.obj"));
  257. poc->position = vec3_new(0,i,0);
  258. poc->scale = vec3_new(5,5,5);
  259. renderable * pocr = asset_hndl_ptr(&poc->renderable);
  260. pocr->material = asset_hndl_new_load(P("./assets/po/material.mat"));
  261. }
  262. entity_new("so",static_object);
  263. entity_get_as("so",static_object)->renderable = asset_hndl_new_load(P("./assets/so/so.obj"));
  264. renderable * sor = asset_hndl_ptr(&entity_get_as("so",static_object)->renderable);
  265. sor->material = asset_hndl_new(P("./assets/so/so.mat"));
  266. entity_get_as("so",static_object)->collision_body = asset_hndl_new_load(P("./assets/so/so.col"));
  267. float tod = 0.17;
  268. int mpos_x;
  269. int mpos_y;
  270. while(running)
  271. {
  272. frame_begin();
  273. //frame_set_rate(60);
  274. ui_button_set_label(ui_elem_get("framerate"),frame_rate_string());
  275. //detect hover slider
  276. if(!ui_rectangle_contains_point(podium->bar,mouse_get_position()) &&
  277. !ui_rectangle_contains_point(objects->bar,mouse_get_position())){
  278. camera_control_freecam(entity_get("cam"),frame_time());};
  279. //rotate podium
  280. char buff[64];
  281. entity_get_as("so",static_object)->rotation = quat_rotation_z(ui_slider_get_amount(ui_elem_get("podium")));
  282. sprintf(buff,"podium axis %.3f",entity_get_as("so",static_object)->rotation.z);
  283. ui_slider_set_label(ui_elem_get("podium"),buff);
  284. //update num objects
  285. max_po_new = ui_slider_get_amount(ui_elem_get("objects")) * 1000;//get balls numbers
  286. max_po_new = (int)max_po_new;//rounding
  287. sprintf(buff,"objects %i",(int)max_po_new);
  288. ui_slider_set_label(ui_elem_get("objects"),buff);
  289. ui_update();
  290. while(event_update())
  291. {
  292. ui_event(event_get());
  293. if(event_get().type == SDL_KEYDOWN)
  294. {
  295. if(event_get().key.keysym.sym == SDLK_SPACE)
  296. {
  297. random_callback(NULL,NULL);
  298. };
  299. if(event_get().key.keysym.sym == SDLK_UP)
  300. {
  301. drop_callback(NULL,&veloc[veloc_forw]);
  302. };
  303. if(event_get().key.keysym.sym == SDLK_DOWN)
  304. {
  305. drop_callback(NULL,&veloc[veloc_back]);
  306. };
  307. if(event_get().key.keysym.sym == SDLK_LEFT)
  308. {
  309. drop_callback(NULL,&veloc[veloc_left]);
  310. };
  311. if(event_get().key.keysym.sym == SDLK_RIGHT)
  312. {
  313. drop_callback(NULL,&veloc[veloc_right]);
  314. };
  315. if(event_get().key.keysym.sym == SDLK_e)
  316. {
  317. gravity_trigger(ui_elem_get("gravity"),NULL);
  318. };
  319. if(event_get().key.keysym.sym == SDLK_r)
  320. {
  321. respawn_callback(NULL,NULL);
  322. };
  323. };
  324. }
  325. renderer_add(dr,render_object_static(entity_get("so")));
  326. for (int i = 0; i < max_po; i++)
  327. {
  328. physics_object * po = entity_get("po%i",i);
  329. static_object * poc = entity_get("poc%i",i);
  330. poc->position = po->position;
  331. poc->position.x +=6;
  332. poc->scale = po->scale;
  333. renderer_add(dr,render_object_static(poc));
  334. }
  335. for (int i = 0; i < max_po; ++i)
  336. {
  337. physics_object_update_custom(entity_get("po%i",i),frame_time());
  338. physics_object_collide_static_custom(entity_get("po%i",i),entity_get("so"),frame_time());
  339. }
  340. renderer_render(dr);
  341. ui_render();
  342. graphics_swap();
  343. frame_end();
  344. };
  345. corange_finish();
  346. return 0;
  347. }
  348. /*-----------------------------------------------------------------------*/
  349. /**
  350. *** custom physics handle, becouse need more implements in original code
  351. **/
  352. /*-----------------------------------------------------------------------*/
  353. /*origunal runction locate in physics.c*/
  354. void collision_response_slide_custom(vec3* position, vec3* velocity, collision (*colfunc)(void))
  355. {
  356. collision col = colfunc();
  357. int count = 0;
  358. while (col.collided)
  359. {
  360. *velocity = vec3_mul(*velocity,1.1);
  361. *velocity = vec3_reflect(*velocity, col.norm);
  362. *position = vec3_add(*position, *velocity);
  363. col = colfunc();
  364. if(count++ > 100){ break; }
  365. };
  366. *position = vec3_add(*position, *velocity);
  367. }
  368. mat4 physics_object_world(physics_object* p)
  369. {
  370. return mat4_world(p->position, p->scale, p->rotation);
  371. }
  372. mat3 physics_object_world_normal(physics_object* p)
  373. {
  374. return mat3_transpose(mat3_inverse(mat4_to_mat3(physics_object_world(p))));
  375. }
  376. /*original code locate in entities/physics_object.c*/
  377. void physics_object_update_custom(physics_object* po, float timestep)
  378. {
  379. /*this calculate from sea demo*/
  380. vec3 gravity_update = vec3_add(po->velocity, vec3_mul((gravity_enable)?vec3_new(0,-9.8,0):vec3_new(0,0,0),timestep));
  381. vec3 movement_update = vec3_lerp(po->velocity, vec3_mul(vec3_zero(), 0.5), saturate(5 *timestep));
  382. po->velocity = vec3_lerp(gravity_update, movement_update, 0.1);
  383. }
  384. /*original code locate in entities/physics_object.c*/
  385. void physics_object_collide_static_custom(physics_object* po, static_object* so, float timestep)
  386. {
  387. cmesh * po_col = asset_hndl_ptr(&po->collision_body);
  388. cmesh * so_col = asset_hndl_ptr(&so->collision_body);
  389. if ((po_col == NULL) || (so_col == NULL))
  390. {
  391. error("Cannot collide objects. One or more has no collision body - First: %p Second: %p).", po_col, so_col);
  392. }
  393. mat4 so_world = static_object_world(so);
  394. mat4 po_world = physics_object_world(po);
  395. mat3 so_normal = static_object_world_normal(so);
  396. ellipsoid po_ellipsoid = ellipsoid_transform(ellipsoid_new(vec3_one(),vec3_one()),po_world);
  397. collision collision_call()
  398. {
  399. return ellipsoid_collide_mesh(po_ellipsoid,po->velocity,so_col,so_world,so_normal);
  400. };
  401. collision_response_slide_custom(&po->position,&po->velocity, collision_call);
  402. }
  403. void splash()
  404. {
  405. float speed = 0.005;
  406. //create splash
  407. ui_rectangle * splash = ui_elem_new("_splash_",ui_rectangle);
  408. splash->top_left = vec2_new(0,0);
  409. ui_rectangle_resize(splash,vec2_new(graphics_viewport_width(),graphics_viewport_height()));
  410. //set texture and filtrating for splash
  411. texture * splash_texture = asset_get(P("./assets/splash/splash.tga"));
  412. texture_set_filtering_anisotropic(splash_texture);
  413. ui_rectangle_set_texture(splash,asset_hndl_new(P("./assets/splash/splash.tga")),0,0,false);
  414. //create and play splash sound
  415. asset_get_as(P("./assets/splash/splash.wav"),sound)->sample->volume = 50;
  416. audio_sound_play(asset_get(P("./assets/splash/splash.wav")),0);
  417. //render splash
  418. while(splash->active)
  419. {
  420. frame_begin();
  421. frame_end_at_rate(60);
  422. if(splash->color.w > 0 || splash->color.x > 0 || splash->color.y > 0 || splash->color.z > 0)
  423. { //splash colors down
  424. splash->color.w-=speed;
  425. splash->color.x-=speed;
  426. splash->color.y-=speed;
  427. splash->color.z-=speed;
  428. }else{
  429. //hide splash if alpha is 0
  430. splash->active = false;
  431. };
  432. ui_render();
  433. graphics_swap();
  434. frame_end();
  435. };
  436. //delete elements and exit
  437. ui_elem_delete("_splash_");
  438. };