您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

406 行
15 KiB

  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. #define IPT_CAM_RESET "Cam_Center"
  19. #define IPT_CAM_FORWARD "Cam_Forward"
  20. #define IPT_CAM_BACKWARD "Cam_Backward"
  21. #define IPT_CAM_ZOOM_OUT "Cam_Zoom_In"
  22. #define IPT_CAM_ZOOM_IN "Cam_Zoom_Out"
  23. #define IPT_MESH_UPDATE "Mesh_Update"
  24. #define IPT_MESH_RESET "Mesh_Reset"
  25. #define IPT_MESH_LEFT "Mesh_Left"
  26. #define IPT_MESH_RIGHT "Mesh_Right"
  27. #define IPT_MESH_UP "Mesh_Up"
  28. #define IPT_MESH_DOWN "Mesh_Down"
  29. #define IPT_MESH_SCALE_UP "Mesh_Scale_Up"
  30. #define IPT_MESH_SCALE_DOWN "Mesh_Scale_Down"
  31. #define IPT_MESH_OFFSET_UP "Mesh_Offset_Up"
  32. #define IPT_MESH_OFFSET_DOWN "Mesh_Offset_Down"
  33. #define IPT_MESH_ROT_LEFT "Mesh_Rot_Left"
  34. #define IPT_MESH_ROT_RIGHT "Mesh_Rot_Right"
  35. #define IPT_MESH_ROT_UP "Mesh_Rot_Up"
  36. #define IPT_MESH_ROT_DOWN "Mesh_Rot_Down"
  37. class MeshViewer : public WorldEntity
  38. {
  39. public:
  40. void SetFov(float new_fov=60.0f)
  41. {
  42. //FOV compensation doesn't work
  43. ivec2 video_size = Video::GetSize();
  44. float near = -video_size.x - video_size.y;
  45. float far = video_size.x + video_size.y;
  46. float t1 = tanf(new_fov / 2);
  47. float dist = video_size.x / (2.0f * t1);
  48. //m_fov_compensation = mat4::translate(-0.5f * video_size.x, -0.5f * video_size.y, -dist);
  49. m_fov_compensation = mat4::translate(vec3(.0f));
  50. if (new_fov > 0.1f)
  51. m_camera->SetPerspective(new_fov, (float)video_size.x, (float)video_size.y, .1f, 1000.f);
  52. else
  53. m_camera->SetOrtho((float)video_size.x, (float)video_size.y, .1f, 1000.f);
  54. }
  55. MeshViewer(char *file_buffer = "MeshViewerBuffer.txt")
  56. {
  57. //Input setup
  58. Input::LinkActionToKey(IPT_CAM_RESET, Key::Return);
  59. Input::LinkActionToKey(IPT_CAM_FORWARD, Key::PageUp);
  60. Input::LinkActionToKey(IPT_CAM_BACKWARD, Key::PageDown);
  61. Input::LinkActionToKey(IPT_CAM_ZOOM_IN, Key::Home);
  62. Input::LinkActionToKey(IPT_CAM_ZOOM_OUT, Key::End);
  63. Input::LinkActionToKey(IPT_MESH_LEFT, Key::Left);
  64. Input::LinkActionToKey(IPT_MESH_RIGHT, Key::Right);
  65. Input::LinkActionToKey(IPT_MESH_UP, Key::Up);
  66. Input::LinkActionToKey(IPT_MESH_DOWN, Key::Down);
  67. Input::LinkActionToKey(IPT_MESH_UPDATE, Key::Space);
  68. Input::LinkActionToKey(IPT_MESH_RESET, Key::KP0);
  69. Input::LinkActionToKey(IPT_MESH_OFFSET_DOWN, Key::KP1);
  70. Input::LinkActionToKey(IPT_MESH_OFFSET_UP, Key::KP3);
  71. Input::LinkActionToKey(IPT_MESH_SCALE_DOWN, Key::KP7);
  72. Input::LinkActionToKey(IPT_MESH_SCALE_UP, Key::KP9);
  73. Input::LinkActionToKey(IPT_MESH_ROT_LEFT, Key::KP4);
  74. Input::LinkActionToKey(IPT_MESH_ROT_RIGHT, Key::KP6);
  75. Input::LinkActionToKey(IPT_MESH_ROT_UP, Key::KP8);
  76. Input::LinkActionToKey(IPT_MESH_ROT_DOWN, Key::KP5);
  77. m_angle = 0;
  78. //Camera Setup
  79. m_fov_zoom_damp = .0f;
  80. m_fov_damp = 60.0f;
  81. m_fov = 60.0f;
  82. m_camera = new Camera(vec3(0.f, 600.f, 0.f),
  83. vec3(0.f, 0.f, 0.f),
  84. vec3(0, 1, 0));
  85. SetFov(m_fov_damp);
  86. m_camera->SetTarget(vec3(0.f, 0.f, 0.f));
  87. m_camera->SetPosition(vec3(0.f, 0.f, 10.f));
  88. m_camera->ForceSceneUpdate();
  89. Ticker::Ref(m_camera);
  90. //Lights setup
  91. m_lights << new Light();
  92. m_lights.Last()->SetPosition(vec4(4.f, -1.f, -4.f, 0.f));
  93. m_lights.Last()->SetColor(vec4(.0f, .2f, .5f, 1.f));
  94. Ticker::Ref(m_lights.Last());
  95. m_lights << new Light();
  96. m_lights.Last()->SetPosition(vec4(8.f, 2.f, 6.f, 1.f));
  97. m_lights.Last()->SetColor(vec4(.5f, .3f, .0f, 1.f));
  98. Ticker::Ref(m_lights.Last());
  99. //Speed damp
  100. m_mesh_rotate_damp = vec2(.0f);
  101. m_mesh_screen_move_damp = vec2(.0f);
  102. m_mesh_move_damp = vec2(.0f);
  103. //Actual values
  104. SetDefaultMeshTransform();
  105. //Actual values damp
  106. m_mesh_rotation_damp = vec2(.0f);
  107. m_mesh_screen_offset_damp = vec2(.0f);
  108. m_mesh_offset_damp = vec2(.0f);
  109. m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
  110. mat4::rotate(m_angle, vec3(0, 1, 0)) *
  111. mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
  112. //File management
  113. #ifdef HAVE_STDIO_H
  114. m_file_buffer = fopen("MeshViewerBuffer.txt", "r");
  115. if (!m_file_buffer)
  116. Ticker::Shutdown();
  117. #else //Full FAIL, kill the viewer
  118. Ticker::Shutdown();
  119. #endif
  120. m_last_stream_size = 0;
  121. m_last_stream_cmd << 0;
  122. m_stream_update_time = 0.0f;
  123. m_stream_update_timer = 1.0f;
  124. }
  125. ~MeshViewer()
  126. {
  127. Ticker::Unref(m_camera);
  128. for (int i = 0; i < m_lights.Count(); ++i)
  129. Ticker::Unref(m_lights[i]);
  130. #ifdef HAVE_STDIO_H
  131. fclose(m_file_buffer);
  132. #endif
  133. }
  134. void SetDefaultMeshTransform()
  135. {
  136. m_mesh_rotation = vec2(25.0f, .0f);
  137. m_mesh_screen_offset = vec2(.54f, .0f);
  138. m_mesh_offset = vec2(-.64f, .07f);
  139. }
  140. virtual void TickGame(float seconds)
  141. {
  142. WorldEntity::TickGame(seconds);
  143. //Shutdown logic
  144. if (Input::WasReleased(Key::Escape))
  145. Ticker::Shutdown();
  146. //Update Mesh BBox - Get the Min/Max needed
  147. vec3 min_max[2] = { vec3(FLT_MAX), vec3(-FLT_MAX) };
  148. int mesh_id = m_meshes.Count() - 1;
  149. for (; mesh_id >= 0; mesh_id--)
  150. if (m_meshes[mesh_id].m2)
  151. break;
  152. if (m_meshes.Count() && mesh_id >= 0)
  153. {
  154. for (int i = 0; i < m_meshes[mesh_id].m1.GetVertexCount(); i++)
  155. {
  156. vec3 vpos = m_meshes[mesh_id].m1.GetVertexLocation(i);
  157. min_max[0] = min(vpos.xyz, min_max[0]);
  158. min_max[1] = max(vpos.xyz, min_max[1]);
  159. }
  160. }
  161. else
  162. {
  163. min_max[0] = vec3(.0f);
  164. min_max[1] = vec3(.0f);
  165. }
  166. //[0] : center, [1] : size.
  167. vec3 BBox[2] = { vec3(.0f), vec3(.0f) };
  168. BBox[1] = min_max[1] - min_max[0];
  169. BBox[0] = min_max[0] + BBox[1] * .5f;
  170. vec3 BBox_mod = BBox[1];
  171. //--
  172. //Camera movement handling
  173. //--
  174. vec3 cam_move = BBox_mod * seconds *
  175. vec3(.0f, .0f, (float)(Input::GetStatus(IPT_CAM_BACKWARD) - Input::GetStatus(IPT_CAM_FORWARD)));
  176. if (Input::WasReleased(IPT_CAM_RESET))
  177. SetFov();
  178. float fov_zoom = (float)(Input::GetStatus(IPT_CAM_ZOOM_OUT) - Input::GetStatus(IPT_CAM_ZOOM_IN));
  179. m_fov_zoom_damp = damp(m_fov_zoom_damp, fov_zoom, (fov_zoom == .0f)?(.15f):(0.5f), seconds);
  180. m_fov = max(.0f, m_fov + seconds * 10.0f * m_fov_zoom_damp);
  181. m_fov_damp = damp(m_fov_damp, m_fov, .2f, seconds);
  182. SetFov(m_fov_damp);
  183. m_camera->SetPosition(m_camera->GetPosition() + cam_move);
  184. m_camera->SetTarget(m_camera->GetPosition() + vec3(0, 0, -5.0f));
  185. //--
  186. //Mesh movement handling
  187. //--
  188. if (Input::WasReleased(IPT_MESH_RESET))
  189. SetDefaultMeshTransform();
  190. vec2 new_move = vec2(.0f);
  191. new_move = vec2((float)(Input::GetStatus(IPT_MESH_RIGHT) - Input::GetStatus(IPT_MESH_LEFT)),
  192. (float)(Input::GetStatus(IPT_MESH_UP) - Input::GetStatus(IPT_MESH_DOWN)));
  193. m_mesh_screen_move_damp = vec2(damp(m_mesh_screen_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  194. damp(m_mesh_screen_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  195. new_move = vec2((float)(Input::GetStatus(IPT_MESH_OFFSET_UP) - Input::GetStatus(IPT_MESH_OFFSET_DOWN)),
  196. (float)(Input::GetStatus(IPT_MESH_SCALE_UP) - Input::GetStatus(IPT_MESH_SCALE_DOWN)));
  197. m_mesh_move_damp = vec2(damp(m_mesh_move_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  198. damp(m_mesh_move_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  199. new_move = vec2((float)(Input::GetStatus(IPT_MESH_ROT_UP) - Input::GetStatus(IPT_MESH_ROT_DOWN)),
  200. (float)(Input::GetStatus(IPT_MESH_ROT_RIGHT) - Input::GetStatus(IPT_MESH_ROT_LEFT)));
  201. m_mesh_rotate_damp = vec2(damp(m_mesh_rotate_damp.x, new_move.x, (new_move.x == .0f)?(.15f):(0.5f), seconds),
  202. damp(m_mesh_rotate_damp.y, new_move.y, (new_move.y == .0f)?(.15f):(0.5f), seconds));
  203. vec2 mesh_screen_move = seconds * 0.6f * m_mesh_screen_move_damp;
  204. vec2 mesh_offset_move = seconds * vec2(.6f, .2f) * m_mesh_move_damp;
  205. vec2 mesh_rotate = seconds * vec2(40.0f, 60.0f) * m_mesh_rotate_damp;
  206. //Add movement
  207. m_mesh_screen_offset += mesh_screen_move;
  208. m_mesh_offset += mesh_offset_move;
  209. m_mesh_rotation += mesh_rotate;
  210. //Compute damp
  211. m_mesh_rotation_damp = damp(m_mesh_rotation_damp, m_mesh_rotation, .2f, seconds);
  212. m_mesh_screen_offset_damp = damp(m_mesh_screen_offset_damp, m_mesh_screen_offset, .2f, seconds);
  213. m_mesh_offset_damp = damp(m_mesh_offset_damp, m_mesh_offset, .2f, seconds);
  214. //Clamp necessary
  215. m_mesh_rotation.x = clamp(m_mesh_rotation.x, -90.0f, 90.0f);
  216. m_mesh_offset.y = max(.0f, m_mesh_offset.y);
  217. //m_angle += seconds * 70.0f;
  218. m_mat = mat4::rotate(m_mesh_rotation.x, vec3(1, 0, 0)) *
  219. mat4::rotate(m_angle, vec3(0, 1, 0)) *
  220. mat4::rotate(m_mesh_rotation.y, vec3(0, 1, 0));
  221. //--
  222. //File management
  223. //--
  224. if (Input::WasReleased(IPT_MESH_UPDATE))
  225. m_stream_update_time = m_stream_update_timer + 1.0f;
  226. m_stream_update_time += seconds;
  227. #ifdef HAVE_STDIO_H
  228. // obtain file size:
  229. fseek(m_file_buffer, 0 , SEEK_END);
  230. long new_stream_size = ftell(m_file_buffer);
  231. rewind(m_file_buffer);
  232. #else
  233. long new_stream_size = 0;
  234. #endif
  235. if (new_stream_size && (new_stream_size != m_last_stream_size || m_stream_update_time > m_stream_update_timer))
  236. {
  237. Array<char> new_stream_cmd;
  238. m_stream_update_time = .0f;
  239. //Reserve the needed datas & read the file
  240. new_stream_cmd.Resize((int)new_stream_size);
  241. #ifdef HAVE_STDIO_H
  242. size_t result = fread(&new_stream_cmd[0], 1, new_stream_size, m_file_buffer);
  243. #else
  244. #endif
  245. //if the new cmd is different from the previous one
  246. if (new_stream_cmd.Count() != m_last_stream_cmd.Count() ||
  247. strcmp(&new_stream_cmd[0], &m_last_stream_cmd[0]))
  248. {
  249. //store the current datas
  250. m_last_stream_cmd = new_stream_cmd;
  251. m_last_stream_size = new_stream_size;
  252. //Create a new mesh
  253. m_meshes.Push(EasyMesh(), false, .0f, vec3(.0f));
  254. m_meshes.Last().m1.Compile(&new_stream_cmd[0]);
  255. }
  256. }
  257. }
  258. virtual void TickDraw(float seconds)
  259. {
  260. WorldEntity::TickDraw(seconds);
  261. for (int i = 0; i < m_meshes.Count(); i++)
  262. {
  263. if (!m_meshes[i].m2)
  264. {
  265. m_meshes[i].m1.MeshConvert();
  266. m_meshes[i].m2 = true;
  267. }
  268. }
  269. Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
  270. mat4 default_proj = Scene::GetDefault()->GetProjMatrix();
  271. for (int i = 0; i < m_meshes.Count(); i++)
  272. {
  273. float new_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (i + 1))));
  274. m_meshes[i].m3 = damp(m_meshes[i].m3, new_scale, .35f, seconds);
  275. if (m_meshes[i].m3 > .0f)
  276. {
  277. vec3 new_mesh_offset = vec3(.0f);
  278. for (int j = m_meshes.Count() - 1; j > i; j--)
  279. {
  280. float ofs_scale = max(.0f, 1.0f - (m_mesh_offset_damp.y * (float)(m_meshes.Count() - (j + 0))));
  281. new_mesh_offset = new_mesh_offset + vec3(m_meshes[j].m3 * ofs_scale * ofs_scale * m_mesh_offset_damp.x, .0f, .0f);
  282. }
  283. m_meshes[i].m4 = damp(m_meshes[i].m4, new_mesh_offset, .35f, seconds);
  284. Scene::GetDefault()->SetProjMatrix(mat4::translate(m_meshes[i].m4) *
  285. mat4::translate(vec3(m_mesh_screen_offset_damp, .0f)) *
  286. mat4::scale(vec3(vec2(m_meshes[i].m3), 1.0f)) *
  287. default_proj *
  288. m_fov_compensation);
  289. m_meshes[i].m1.Render(m_mat);
  290. Video::Clear(ClearMask::Depth);
  291. }
  292. }
  293. Scene::GetDefault()->SetProjMatrix(default_proj);
  294. }
  295. private:
  296. float m_angle;
  297. mat4 m_mat;
  298. //Mesh infos
  299. //Move damping
  300. vec2 m_mesh_rotate_damp;
  301. vec2 m_mesh_screen_move_damp;
  302. vec2 m_mesh_move_damp;
  303. //Move transform damping
  304. vec2 m_mesh_rotation_damp;
  305. vec2 m_mesh_screen_offset_damp;
  306. vec2 m_mesh_offset_damp;
  307. vec2 m_mesh_rotation; //Meshes rotation
  308. vec2 m_mesh_screen_offset;//Meshes screen offset
  309. vec2 m_mesh_offset; //Mesh Offset after first mesh (x: offset, y: scale)
  310. //File data
  311. #ifdef HAVE_STDIO_H
  312. FILE * m_file_buffer;
  313. #endif
  314. long m_last_stream_size;
  315. Array<char> m_last_stream_cmd;
  316. float m_stream_update_time;
  317. float m_stream_update_timer;
  318. //misc datas
  319. Array<EasyMesh, bool, float, vec3> m_meshes;
  320. Array<Light *> m_lights;
  321. Camera * m_camera;
  322. float m_fov;
  323. float m_fov_damp;
  324. float m_fov_zoom_damp;
  325. mat4 m_fov_compensation;
  326. };
  327. //The basic main :
  328. int main(int argc, char **argv)
  329. {
  330. System::Init(argc, argv);
  331. Application app("MeshViewer", ivec2(1600, 600), 60.0f);
  332. if (argc > 1)
  333. new MeshViewer(argv[1]);
  334. else
  335. new MeshViewer();
  336. app.Run();
  337. return EXIT_SUCCESS;
  338. }