You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MeshViewer.cpp 16 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. //
  2. // Lol Engine - EasyMesh tutorial
  3. //
  4. // Copyright: (c) 2011-2013 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2012-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  6. // This program is free software; you can redistribute it and/or
  7. // modify it under the terms of the Do What The Fuck You Want To
  8. // Public License, Version 2, as published by Sam Hocevar. See
  9. // http://www.wtfpl.net/ for more details.
  10. //
  11. #if defined HAVE_CONFIG_H
  12. # include "config.h"
  13. #endif
  14. #include <cfloat> /* for FLT_MAX */
  15. #include "core.h"
  16. using namespace std;
  17. using namespace lol;
  18. LOLFX_RESOURCE_DECLARE(shinyfur);
  19. #define IPT_CAM_RESET "Cam_Center"
  20. #define IPT_CAM_FORWARD "Cam_Forward"
  21. #define IPT_CAM_BACKWARD "Cam_Backward"
  22. #define IPT_CAM_ZOOM_OUT "Cam_Zoom_In"
  23. #define IPT_CAM_ZOOM_IN "Cam_Zoom_Out"
  24. #define IPT_MESH_UPDATE "Mesh_Update"
  25. #define IPT_MESH_RESET "Mesh_Reset"
  26. #define IPT_MESH_LEFT "Mesh_Left"
  27. #define IPT_MESH_RIGHT "Mesh_Right"
  28. #define IPT_MESH_UP "Mesh_Up"
  29. #define IPT_MESH_DOWN "Mesh_Down"
  30. #define IPT_MESH_SCALE_UP "Mesh_Scale_Up"
  31. #define IPT_MESH_SCALE_DOWN "Mesh_Scale_Down"
  32. #define IPT_MESH_OFFSET_UP "Mesh_Offset_Up"
  33. #define IPT_MESH_OFFSET_DOWN "Mesh_Offset_Down"
  34. #define IPT_MESH_ROT_LEFT "Mesh_Rot_Left"
  35. #define IPT_MESH_ROT_RIGHT "Mesh_Rot_Right"
  36. #define IPT_MESH_ROT_UP "Mesh_Rot_Up"
  37. #define IPT_MESH_ROT_DOWN "Mesh_Rot_Down"
  38. #define WITH_FUR 0
  39. class MeshViewer : public WorldEntity
  40. {
  41. public:
  42. void SetFov(float new_fov=60.0f)
  43. {
  44. //FOV compensation doesn't work
  45. ivec2 video_size = Video::GetSize();
  46. float near = (float)-video_size.x - video_size.y;
  47. float far = (float)video_size.x + video_size.y;
  48. float t1 = tanf(new_fov / 2);
  49. float dist = (float)video_size.x / (2.0f * t1);
  50. //m_fov_compensation = mat4::translate(-0.5f * video_size.x, -0.5f * video_size.y, -dist);
  51. m_fov_compensation = mat4::translate(vec3(.0f));
  52. if (new_fov > 0.1f)
  53. m_camera->SetPerspective(new_fov, (float)video_size.x, (float)video_size.y, .1f, 1000.f);
  54. else
  55. m_camera->SetOrtho((float)video_size.x, (float)video_size.y, .1f, 1000.f);
  56. }
  57. MeshViewer(char const *file_name = "MeshViewerBuffer.txt")
  58. : m_file_name(file_name)
  59. {
  60. //Input setup
  61. Input::LinkActionToKey(IPT_CAM_RESET, Key::Return);
  62. Input::LinkActionToKey(IPT_CAM_FORWARD, Key::PageUp);
  63. Input::LinkActionToKey(IPT_CAM_BACKWARD, Key::PageDown);
  64. Input::LinkActionToKey(IPT_CAM_ZOOM_IN, Key::Home);
  65. Input::LinkActionToKey(IPT_CAM_ZOOM_OUT, Key::End);
  66. Input::LinkActionToKey(IPT_MESH_LEFT, Key::Left);
  67. Input::LinkActionToKey(IPT_MESH_RIGHT, Key::Right);
  68. Input::LinkActionToKey(IPT_MESH_UP, Key::Up);
  69. Input::LinkActionToKey(IPT_MESH_DOWN, Key::Down);
  70. Input::LinkActionToKey(IPT_MESH_UPDATE, Key::Space);
  71. Input::LinkActionToKey(IPT_MESH_RESET, Key::KP0);
  72. Input::LinkActionToKey(IPT_MESH_OFFSET_DOWN, Key::KP1);
  73. Input::LinkActionToKey(IPT_MESH_OFFSET_UP, Key::KP3);
  74. Input::LinkActionToKey(IPT_MESH_SCALE_DOWN, Key::KP7);
  75. Input::LinkActionToKey(IPT_MESH_SCALE_UP, Key::KP9);
  76. Input::LinkActionToKey(IPT_MESH_ROT_LEFT, Key::KP4);
  77. Input::LinkActionToKey(IPT_MESH_ROT_RIGHT, Key::KP6);
  78. Input::LinkActionToKey(IPT_MESH_ROT_UP, Key::KP8);
  79. Input::LinkActionToKey(IPT_MESH_ROT_DOWN, Key::KP5);
  80. m_angle = 0;
  81. //Camera Setup
  82. m_fov_zoom_damp = .0f;
  83. m_fov_damp = 60.0f;
  84. m_fov = 60.0f;
  85. m_camera = new Camera(vec3(0.f, 600.f, 0.f),
  86. vec3(0.f, 0.f, 0.f),
  87. vec3(0, 1, 0));
  88. SetFov(m_fov_damp);
  89. m_camera->SetTarget(vec3(0.f, 0.f, 0.f));
  90. m_camera->SetPosition(vec3(0.f, 0.f, 10.f));
  91. m_camera->ForceSceneUpdate();
  92. Ticker::Ref(m_camera);
  93. //Lights setup
  94. m_lights << new Light();
  95. m_lights.Last()->SetPosition(vec4(4.f, -1.f, -4.f, 0.f));
  96. m_lights.Last()->SetColor(vec4(.0f, .2f, .5f, 1.f));
  97. Ticker::Ref(m_lights.Last());
  98. m_lights << new Light();
  99. m_lights.Last()->SetPosition(vec4(8.f, 2.f, 6.f, 1.f));
  100. m_lights.Last()->SetColor(vec4(.5f, .3f, .0f, 1.f));
  101. Ticker::Ref(m_lights.Last());
  102. //Speed damp
  103. m_mesh_rotate_damp = vec2(.0f);
  104. m_mesh_screen_move_damp = vec2(.0f);
  105. m_mesh_move_damp = vec2(.0f);
  106. //Actual values
  107. SetDefaultMeshTransform();
  108. //Actual values damp
  109. m_mesh_rotation_damp = vec2(.0f);
  110. m_mesh_screen_offset_damp = vec2(.0f);
  111. m_mesh_offset_damp = vec2(.0f);
  112. m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
  113. mat4::rotate(m_angle, vec3(0, 1, 0)) *
  114. mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
  115. m_stream_update_time = 2.0f;
  116. m_stream_update_timer = 1.0f;
  117. }
  118. ~MeshViewer()
  119. {
  120. Ticker::Unref(m_camera);
  121. for (int i = 0; i < m_lights.Count(); ++i)
  122. Ticker::Unref(m_lights[i]);
  123. }
  124. void SetDefaultMeshTransform()
  125. {
  126. m_mesh_rotation = vec2(25.0f, .0f);
  127. m_mesh_screen_offset = vec2(.54f, .0f);
  128. m_mesh_offset = vec2(-.64f, .07f);
  129. }
  130. virtual void TickGame(float seconds)
  131. {
  132. WorldEntity::TickGame(seconds);
  133. //TODO : This should probably be "standard LoL behaviour"
  134. {
  135. //Shutdown logic
  136. if (Input::WasReleased(Key::Escape))
  137. Ticker::Shutdown();
  138. }
  139. //Update Mesh BBox - Get the Min/Max needed
  140. vec3 min_max[2] = { vec3(FLT_MAX), vec3(-FLT_MAX) };
  141. int mesh_id = m_meshes.Count() - 1;
  142. for (; mesh_id >= 0; mesh_id--)
  143. if (m_meshes[mesh_id].m2)
  144. break;
  145. if (m_meshes.Count() && mesh_id >= 0)
  146. {
  147. for (int i = 0; i < m_meshes[mesh_id].m1.GetVertexCount(); i++)
  148. {
  149. vec3 vpos = m_meshes[mesh_id].m1.GetVertexLocation(i);
  150. min_max[0] = min(vpos.xyz, min_max[0]);
  151. min_max[1] = max(vpos.xyz, min_max[1]);
  152. }
  153. }
  154. else
  155. {
  156. min_max[0] = vec3(.0f);
  157. min_max[1] = vec3(.0f);
  158. }
  159. //[0] : center, [1] : size.
  160. vec3 BBox[2] = { vec3(.0f), vec3(.0f) };
  161. BBox[1] = min_max[1] - min_max[0];
  162. BBox[0] = min_max[0] + BBox[1] * .5f;
  163. vec3 BBox_mod = BBox[1];
  164. //--
  165. //Camera movement handling
  166. //--
  167. vec3 cam_move = BBox_mod * seconds *
  168. vec3(.0f, .0f, (float)(Input::GetStatus(IPT_CAM_BACKWARD) - Input::GetStatus(IPT_CAM_FORWARD)));
  169. if (Input::WasReleased(IPT_CAM_RESET))
  170. SetFov();
  171. float fov_zoom = (float)(Input::GetStatus(IPT_CAM_ZOOM_OUT) - Input::GetStatus(IPT_CAM_ZOOM_IN));
  172. m_fov_zoom_damp = damp(m_fov_zoom_damp, fov_zoom, (fov_zoom == .0f)?(.15f):(0.5f), seconds);
  173. m_fov = max(.0f, m_fov + seconds * 10.0f * m_fov_zoom_damp);
  174. m_fov_damp = damp(m_fov_damp, m_fov, .2f, seconds);
  175. SetFov(m_fov_damp);
  176. m_camera->SetPosition(m_camera->GetPosition() + cam_move);
  177. m_camera->SetTarget(m_camera->GetPosition() + vec3(0, 0, -5.0f));
  178. //--
  179. //Mesh movement handling
  180. //--
  181. if (Input::WasReleased(IPT_MESH_RESET))
  182. SetDefaultMeshTransform();
  183. vec2 new_move = vec2(.0f);
  184. new_move = vec2((float)(Input::GetStatus(IPT_MESH_RIGHT) - Input::GetStatus(IPT_MESH_LEFT)),
  185. (float)(Input::GetStatus(IPT_MESH_UP) - Input::GetStatus(IPT_MESH_DOWN)));
  186. m_mesh_screen_move_damp = vec2(damp(m_mesh_screen_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  187. damp(m_mesh_screen_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  188. new_move = vec2((float)(Input::GetStatus(IPT_MESH_OFFSET_UP) - Input::GetStatus(IPT_MESH_OFFSET_DOWN)),
  189. (float)(Input::GetStatus(IPT_MESH_SCALE_UP) - Input::GetStatus(IPT_MESH_SCALE_DOWN)));
  190. m_mesh_move_damp = vec2(damp(m_mesh_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  191. damp(m_mesh_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  192. new_move = vec2((float)(Input::GetStatus(IPT_MESH_ROT_UP) - Input::GetStatus(IPT_MESH_ROT_DOWN)),
  193. (float)(Input::GetStatus(IPT_MESH_ROT_RIGHT) - Input::GetStatus(IPT_MESH_ROT_LEFT)));
  194. m_mesh_rotate_damp = vec2(damp(m_mesh_rotate_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  195. damp(m_mesh_rotate_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  196. vec2 mesh_screen_move = seconds * 0.6f * m_mesh_screen_move_damp;
  197. vec2 mesh_offset_move = seconds * vec2(.6f, .2f) * m_mesh_move_damp;
  198. vec2 mesh_rotate = seconds * vec2(40.0f, 60.0f) * m_mesh_rotate_damp;
  199. //Add movement
  200. m_mesh_screen_offset += mesh_screen_move;
  201. m_mesh_offset += mesh_offset_move;
  202. m_mesh_rotation += mesh_rotate;
  203. //Compute damp
  204. m_mesh_rotation_damp = damp(m_mesh_rotation_damp, m_mesh_rotation, .2f, seconds);
  205. m_mesh_screen_offset_damp = damp(m_mesh_screen_offset_damp, m_mesh_screen_offset, .2f, seconds);
  206. m_mesh_offset_damp = damp(m_mesh_offset_damp, m_mesh_offset, .2f, seconds);
  207. //Clamp necessary
  208. m_mesh_rotation.x = clamp(m_mesh_rotation.x, -90.0f, 90.0f);
  209. m_mesh_offset.y = max(.0f, m_mesh_offset.y);
  210. //m_angle += seconds * 70.0f;
  211. m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
  212. mat4::rotate(m_angle, vec3(0, 1, 0)) *
  213. mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
  214. //--
  215. //File management
  216. //--
  217. if (Input::WasReleased(IPT_MESH_UPDATE))
  218. m_stream_update_time = m_stream_update_timer + 1.0f;
  219. m_stream_update_time += seconds;
  220. if (m_stream_update_time > m_stream_update_timer)
  221. {
  222. m_stream_update_time = 0.f;
  223. File f;
  224. f.Open(m_file_name.C(), FileAccess::Read);
  225. String cmd = f.ReadString();
  226. f.Close();
  227. for (int i = 0; i < cmd.Count() - 1; i++)
  228. {
  229. if (cmd[i] == '/' && cmd[i + 1] == '/')
  230. {
  231. int j = i;
  232. for (; j < cmd.Count(); j++)
  233. {
  234. if (cmd[j] == '\r' || cmd[j] == '\n')
  235. break;
  236. }
  237. String new_cmd = cmd.Sub(0, i);
  238. if (j < cmd.Count())
  239. new_cmd += cmd.Sub(j, cmd.Count() - j);
  240. cmd = new_cmd;
  241. i--;
  242. }
  243. }
  244. if (cmd.Count()
  245. && (!m_cmdlist.Count() || cmd != m_cmdlist.Last()))
  246. {
  247. m_cmdlist << cmd;
  248. //Create a new mesh
  249. m_meshes.Push(EasyMesh(), false, .0f, vec3(.0f));
  250. if (!m_meshes.Last().m1.Compile(cmd.C()))
  251. m_meshes.Pop();
  252. else
  253. m_meshes.Last().m1.ComputeTexCoord(0.2f, 2);
  254. }
  255. }
  256. }
  257. virtual void TickDraw(float seconds)
  258. {
  259. WorldEntity::TickDraw(seconds);
  260. //TODO : This should probably be "standard LoL behaviour"
  261. {
  262. if (Input::WasReleased(Key::F1))
  263. Video::SetDebugRenderMode(DebugRenderMode::Default);
  264. if (Input::WasReleased(Key::F2))
  265. Video::SetDebugRenderMode(DebugRenderMode::Wireframe);
  266. if (Input::WasReleased(Key::F3))
  267. Video::SetDebugRenderMode(DebugRenderMode::Lighting);
  268. if (Input::WasReleased(Key::F4))
  269. Video::SetDebugRenderMode(DebugRenderMode::Normal);
  270. if (Input::WasReleased(Key::F5))
  271. Video::SetDebugRenderMode(DebugRenderMode::UV);
  272. }
  273. for (int i = 0; i < m_meshes.Count(); i++)
  274. {
  275. if (!m_meshes[i].m2)
  276. {
  277. //Fur support
  278. #if WITH_FUR
  279. m_meshes[i].m1.MeshConvert(Shader::Create(LOLFX_RESOURCE_NAME(shinyfur)));
  280. #else
  281. m_meshes[i].m1.MeshConvert();
  282. #endif
  283. m_meshes[i].m2 = true;
  284. }
  285. }
  286. Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
  287. mat4 default_proj = Scene::GetDefault()->GetProjMatrix();
  288. for (int i = 0; i < m_meshes.Count(); i++)
  289. {
  290. float new_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (i + 1))));
  291. m_meshes[i].m3 = damp(m_meshes[i].m3, new_scale, .35f, seconds);
  292. if (m_meshes[i].m3 > .0f)
  293. {
  294. vec3 new_mesh_offset = vec3(.0f);
  295. for (int j = m_meshes.Count() - 1; j > i; j--)
  296. {
  297. float ofs_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (j + 0))));
  298. new_mesh_offset = new_mesh_offset + vec3(m_meshes[j].m3 * ofs_scale * ofs_scale * m_mesh_offset_damp.x, .0f, .0f);
  299. }
  300. m_meshes[i].m4 = damp(m_meshes[i].m4, new_mesh_offset, .35f, seconds);
  301. Scene::GetDefault()->SetProjMatrix(mat4::translate(m_meshes[i].m4) *
  302. mat4::translate(vec3(m_mesh_screen_offset_damp, .0f)) *
  303. mat4::scale(vec3(vec2(m_meshes[i].m3), 1.0f)) *
  304. default_proj *
  305. m_fov_compensation);
  306. #if WITH_FUR
  307. for (int j=0; j < 40; j++)
  308. m_meshes[i].m1.Render(m_mat, 0.1 * j);
  309. #else
  310. m_meshes[i].m1.Render(m_mat);
  311. #endif
  312. Video::Clear(ClearMask::Depth);
  313. }
  314. }
  315. Scene::GetDefault()->SetProjMatrix(default_proj);
  316. }
  317. private:
  318. float m_angle;
  319. mat4 m_mat;
  320. //Mesh infos
  321. //Move damping
  322. vec2 m_mesh_rotate_damp;
  323. vec2 m_mesh_screen_move_damp;
  324. vec2 m_mesh_move_damp;
  325. //Move transform damping
  326. vec2 m_mesh_rotation_damp;
  327. vec2 m_mesh_screen_offset_damp;
  328. vec2 m_mesh_offset_damp;
  329. vec2 m_mesh_rotation; //Meshes rotation
  330. vec2 m_mesh_screen_offset;//Meshes screen offset
  331. vec2 m_mesh_offset; //Mesh Offset after first mesh (x: offset, y: scale)
  332. //File data
  333. String m_file_name;
  334. Array<String> m_cmdlist;
  335. float m_stream_update_time;
  336. float m_stream_update_timer;
  337. //misc datas
  338. Array<EasyMesh, bool, float, vec3> m_meshes;
  339. Array<Light *> m_lights;
  340. Camera * m_camera;
  341. float m_fov;
  342. float m_fov_damp;
  343. float m_fov_zoom_damp;
  344. mat4 m_fov_compensation;
  345. };
  346. //The basic main :
  347. int main(int argc, char **argv)
  348. {
  349. System::Init(argc, argv);
  350. Application app("MeshViewer", ivec2(1600, 600), 60.0f);
  351. if (argc > 1)
  352. new MeshViewer(argv[1]);
  353. else
  354. new MeshViewer();
  355. app.Run();
  356. return EXIT_SUCCESS;
  357. }