1011 Zeilen
35 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the Do What The Fuck You Want To
  9. // Public License, Version 2, as published by Sam Hocevar. See
  10. // http://www.wtfpl.net/ for more details.
  11. //
  12. //
  13. // The EasyMesh class
  14. // ------------------
  15. //
  16. #if !defined __EASYMESH_EASYMESH_H__
  17. #define __EASYMESH_EASYMESH_H__
  18. namespace lol
  19. {
  20. //Utility struct to convert command code to pseudo-bytecode
  21. struct CommandStack
  22. {
  23. private:
  24. Array<int, int, int> m_commands;
  25. Array<float> m_floats;
  26. Array<int> m_ints;
  27. int m_f_cur;
  28. int m_i_cur;
  29. public:
  30. //cmd storage
  31. void AddCmd(int cmd) { m_commands.Push(cmd, m_floats.Count(), m_ints.Count()); }
  32. int GetCmdNb() { return m_commands.Count(); }
  33. int GetCmd(int i)
  34. {
  35. ASSERT(0 <= i && i < m_commands.Count());
  36. m_f_cur = m_commands[i].m2;
  37. m_i_cur = m_commands[i].m3;
  38. return m_commands[i].m1;
  39. }
  40. //GETTER
  41. inline float F() { return m_floats[m_f_cur++]; }
  42. inline int I() { return m_ints[m_i_cur++]; }
  43. inline int E() { return I(); }
  44. inline bool B() { return !!I(); }
  45. inline vec2 V2() { vec2 v(F()); v.y = F(); return v; }
  46. inline vec3 V3() { vec3 v(V2(), 0.f); v.z = F(); return v; }
  47. inline vec4 V4() { vec4 v(V3(), 0.f); v.w = F(); return v; }
  48. inline ivec2 IV2() { ivec2 v(I()); v.y = I(); return v; }
  49. inline ivec3 IV3() { ivec3 v(IV2(), 0); v.z = I(); return v; }
  50. inline ivec4 IV4() { ivec4 v(IV3(), 0); v.w = I(); return v; }
  51. //Alternate getters
  52. inline void GetValue(float &f) { f = F(); }
  53. inline void GetValue(int &i) { i = I(); }
  54. inline void GetValue(bool &b) { b = B(); }
  55. inline void GetValue(vec2 &v2) { v2 = V2(); }
  56. inline void GetValue(vec3 &v3) { v3 = V3(); }
  57. inline void GetValue(vec4 &v4) { v4 = V4(); }
  58. inline void GetValue(ivec2 &iv2) { iv2 = IV2(); }
  59. inline void GetValue(ivec3 &iv3) { iv3 = IV3(); }
  60. inline void GetValue(ivec4 &iv4) { iv4 = IV4(); }
  61. //For Safe Enum
  62. template< class T > inline
  63. void GetValue(T &i) { i = T((typename T::Value)I()); }
  64. //SETTER
  65. CommandStack &operator<<(int i) { m_ints << i; return *this; }
  66. CommandStack &operator<<(float f) { m_floats << f; return *this; }
  67. CommandStack &operator<<(bool b) { return (*this << (int)b); }
  68. CommandStack &operator<<(vec2 v) { return (*this << v.x << v.y); }
  69. CommandStack &operator<<(vec3 v) { return (*this << v.xy << v.z); }
  70. CommandStack &operator<<(vec4 v) { return (*this << v.xyz << v.w); }
  71. CommandStack &operator<<(ivec2 iv) { return (*this << iv.x << iv.y); }
  72. CommandStack &operator<<(ivec3 iv) { return (*this << iv.xy << iv.z); }
  73. CommandStack &operator<<(ivec4 iv) { return (*this << iv.xyz << iv.w); }
  74. };
  75. //Utility enum for renderers
  76. struct MeshRender
  77. {
  78. enum Value
  79. {
  80. NeedData,
  81. NeedConvert,
  82. CanRender,
  83. IgnoreRender,
  84. Max
  85. }
  86. m_value;
  87. inline MeshRender(Value v) : m_value(v) {}
  88. inline MeshRender() : m_value(NeedData) {}
  89. inline operator Value() { return m_value; }
  90. };
  91. //Vertex datas for easymesh vertex list.
  92. //TODO : <COORD, NORM, COLOR, UV>
  93. struct VertexData
  94. {
  95. vec3 m_coord;
  96. vec3 m_normal;
  97. vec4 m_color;
  98. vec4 m_texcoord;
  99. ivec4 m_bone_id;
  100. vec4 m_bone_weight;
  101. VertexData(vec3 new_coord = vec3(0.f),
  102. vec3 new_normal = vec3(0.f, 1.f, 0.f),
  103. vec4 new_color = vec4(0.f),
  104. vec4 new_texcoord = vec4(0.f),
  105. ivec4 new_bone_id = ivec4(0),
  106. vec4 new_bone_weight= vec4(0.f))
  107. {
  108. m_coord = new_coord;
  109. m_normal = new_normal;
  110. m_color = new_color;
  111. m_texcoord = new_texcoord;
  112. m_bone_id = new_bone_id;
  113. m_bone_weight = new_bone_weight;
  114. }
  115. };
  116. //Base class to declare shader datas
  117. class GpuShaderData
  118. {
  119. friend class GpuEasyMeshData;
  120. protected:
  121. GpuShaderData();
  122. public:
  123. //--
  124. GpuShaderData(uint16_t vert_decl_flags, Shader* shader, DebugRenderMode render_mode);
  125. virtual ~GpuShaderData();
  126. //--
  127. void AddUniform(const lol::String &new_uniform);
  128. void AddAttribute(VertexUsage usage, int index);
  129. ShaderUniform const *GetUniform(const lol::String &uniform);
  130. ShaderAttrib const *GetAttribute(VertexUsage usage, int index);
  131. //--
  132. virtual void SetupShaderDatas(mat4 const &model) { UNUSED(model); }
  133. //--
  134. protected:
  135. uint16_t m_vert_decl_flags;
  136. Shader* m_shader;
  137. DebugRenderMode m_render_mode;
  138. Array<lol::String, ShaderUniform> m_shader_uniform;
  139. Array<ShaderAttrib> m_shader_attrib;
  140. };
  141. class DefaultShaderData : public GpuShaderData
  142. {
  143. public:
  144. //---
  145. DefaultShaderData(DebugRenderMode render_mode);
  146. DefaultShaderData(uint16_t vert_decl_flags, Shader* shader, bool with_UV);
  147. virtual ~DefaultShaderData() {}
  148. void StoreUniformNames();
  149. //---
  150. void SetupDefaultData(bool with_UV);
  151. virtual void SetupShaderDatas(mat4 const &model);
  152. //--
  153. Array<String> m_uniform_names;
  154. };
  155. class GpuEasyMeshData
  156. {
  157. friend class EasyMesh;
  158. public:
  159. //---
  160. GpuEasyMeshData();
  161. ~GpuEasyMeshData();
  162. //---
  163. void AddGpuData(GpuShaderData* gpudata, class EasyMesh* src_mesh);
  164. void RenderMeshData(mat4 const &model);
  165. private:
  166. void SetupVertexData(uint16_t vdecl_flags, EasyMesh* src_mesh);
  167. Array<GpuShaderData*> m_gpudatas;
  168. //uint16_t are the vdecl/vbo flags to avoid copy same vdecl several times.
  169. Array<uint16_t, VertexDeclaration*,
  170. VertexBuffer*> m_vdatas;
  171. int m_vertexcount;
  172. //We only need only one ibo for the whole mesh
  173. IndexBuffer * m_ibo;
  174. int m_indexcount;
  175. };
  176. struct MeshBuildOperation
  177. {
  178. enum Value
  179. {
  180. //When this flag is up, negative scaling will not invert faces.
  181. ScaleWinding = (1 << 0),
  182. CommandRecording = (1 << 1),
  183. CommandExecution = (1 << 2),
  184. QuadWeighting = (1 << 3),
  185. IgnoreQuadWeighting = (1 << 4),
  186. All = 0xffffffff
  187. }
  188. m_value;
  189. inline MeshBuildOperation(Value v) : m_value(v) {}
  190. inline MeshBuildOperation(uint64_t i) : m_value((Value)i) {}
  191. inline operator Value() { return m_value; }
  192. };
  193. struct EasyMeshCmdType
  194. {
  195. enum Value
  196. {
  197. MeshCsg = 0,
  198. LoopStart,
  199. LoopEnd,
  200. OpenBrace,
  201. CloseBrace,
  202. ScaleWinding,
  203. QuadWeighting,
  204. SetColorA,
  205. SetColorB,
  206. SetVertColor,
  207. Translate,
  208. Rotate,
  209. RadialJitter,
  210. MeshTranform,
  211. Scale,
  212. DupAndScale,
  213. Chamfer,
  214. SplitTriangles,
  215. SmoothMesh,
  216. AppendCylinder,
  217. AppendCapsule,
  218. AppendTorus,
  219. AppendBox,
  220. AppendStar,
  221. AppendExpandedStar,
  222. AppendDisc,
  223. AppendSimpleTriangle,
  224. AppendSimpleQuad,
  225. AppendCog,
  226. Max
  227. }
  228. m_value;
  229. inline EasyMeshCmdType(Value v) : m_value(v) {}
  230. inline operator Value() { return m_value; }
  231. inline int Value() { return m_value; }
  232. };
  233. struct MeshType
  234. {
  235. enum Value
  236. {
  237. Triangle = 0,
  238. Quad,
  239. Box,
  240. Sphere,
  241. Capsule,
  242. Torus,
  243. Cylinder,
  244. Disc,
  245. Star,
  246. ExpandedStar,
  247. Cog,
  248. Max
  249. }
  250. m_value;
  251. inline MeshType(Value v) : m_value(v) {}
  252. inline operator Value() { return m_value; }
  253. };
  254. //TODO : Add other Build type
  255. struct TexCoordBuildType
  256. {
  257. enum Value
  258. {
  259. TriangleDefault = 0,
  260. QuadDefault = 0,
  261. BoxDefault = 0,
  262. SphereDefault = 0,
  263. CapsuleDefault = 0,
  264. TorusDefault = 0,
  265. CylinderDefault = 0,
  266. DiscDefault = 0,
  267. StarDefault = 0,
  268. ExpandedStarDefault = 0,
  269. CogDefault = 0,
  270. //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE
  271. Max = 1
  272. }
  273. m_value;
  274. inline TexCoordBuildType() : m_value(TriangleDefault) {}
  275. inline TexCoordBuildType(Value v) : m_value(v) {}
  276. inline TexCoordBuildType(int v) : m_value((Value)v) {}
  277. inline operator Value() { return m_value; }
  278. };
  279. struct MeshFaceType
  280. {
  281. enum Value
  282. {
  283. BoxFront = 0,
  284. BoxLeft = 1,
  285. BoxBack = 2,
  286. BoxRight = 3,
  287. BoxTop = 4,
  288. BoxBottom = 5,
  289. QuadDefault = 0,
  290. //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE
  291. Max = 6
  292. }
  293. m_value;
  294. inline MeshFaceType(Value v) : m_value(v) {}
  295. inline operator Value() { return m_value; }
  296. };
  297. struct TexCoordPos
  298. {
  299. enum Value
  300. {
  301. BL, //BottomLeft
  302. BR, //BottomRight
  303. TL, //TopLeft
  304. TR //TopRight
  305. }
  306. m_value;
  307. inline TexCoordPos(Value v) : m_value(v) {}
  308. inline operator Value() { return m_value; }
  309. };
  310. class EasyMeshBuildData
  311. {
  312. public:
  313. EasyMeshBuildData()
  314. {
  315. m_color_a = vec4(0.f, 0.f, 0.f, 1.f);
  316. m_color_b = vec4(0.f, 0.f, 0.f, 1.f);
  317. m_texcoord_offset = vec2(0.f);
  318. m_texcoord_offset2 = vec2(0.f);
  319. m_texcoord_scale = vec2(1.f);
  320. m_texcoord_scale2 = vec2(1.f);
  321. m_build_flags = 0;
  322. for (int i = 0; i < MeshType::Max; ++i)
  323. {
  324. m_texcoord_build_type[i] = TexCoordBuildType::TriangleDefault;
  325. m_texcoord_build_type2[i] = TexCoordBuildType::TriangleDefault;
  326. }
  327. }
  328. inline CommandStack &CmdStack() { return m_stack; }
  329. inline int &Cmdi() { return m_cmd_i; }
  330. inline Array<int, int> &LoopStack(){ return m_loop_stack; }
  331. inline vec4 &ColorA() { return m_color_a; }
  332. inline vec4 &ColorB() { return m_color_b; }
  333. inline vec2 &TexCoordOffset() { return m_texcoord_offset; }
  334. inline vec2 &TexCoordScale() { return m_texcoord_scale; }
  335. inline vec2 &TexCoordOffset2() { return m_texcoord_offset2; }
  336. inline vec2 &TexCoordScale2() { return m_texcoord_scale2; }
  337. //UV1
  338. void SetTexCoordBuildType(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type[mt] = (1 << (tcbt + 1)) | (m_texcoord_build_type[mt] & 1); }
  339. TexCoordBuildType GetTexCoordBuildType(MeshType mt)
  340. {
  341. uint32_t flag = (uint32_t)((m_texcoord_build_type[mt] & ~(1)) >> 1);
  342. int i = 0;
  343. while (flag >>= 1)
  344. i++;
  345. return TexCoordBuildType(i);
  346. }
  347. void SetTexCoordCustomBuild(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  348. {
  349. if (face >= m_texcoord_custom_build[mt].Count())
  350. m_texcoord_custom_build[mt].Resize(face + 1);
  351. m_texcoord_custom_build[mt][face].m1 = BL;
  352. m_texcoord_custom_build[mt][face].m2 = TR;
  353. m_texcoord_build_type[mt] |= 1;
  354. }
  355. void ClearTexCoordCustomBuild(MeshType mt) { m_texcoord_build_type[mt] &= ~1; }
  356. /* FIXME : Do something better ? */
  357. vec2 TexCoord(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  358. {
  359. vec2 BL = vec2(0.f);
  360. vec2 TR = vec2(0.f);
  361. if (m_texcoord_build_type[mt] & 1 && face < m_texcoord_custom_build[mt].Count())
  362. {
  363. BL = m_texcoord_custom_build[mt][face].m1;
  364. TR = m_texcoord_custom_build[mt][face].m2;
  365. }
  366. else
  367. {
  368. /* unused for now, but will be if new BuildType are added. */
  369. TexCoordBuildType tcbt = GetTexCoordBuildType(mt);
  370. UNUSED(tcbt);
  371. if (mt == MeshType::Triangle)
  372. mt = mt;
  373. else if (mt == MeshType::Quad)
  374. {
  375. //There's nothin' else than QuadDefault
  376. BL = vec2(0.f);
  377. TR = vec2(1.f);
  378. }
  379. else if (mt == MeshType::Box)
  380. {
  381. vec2 data[][2] =
  382. { //TexCoordBuildType::BoxDefault
  383. { vec2(0.f), vec2(.5f) },
  384. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  385. { vec2(0.f), vec2(.5f) },
  386. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  387. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  388. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  389. };
  390. BL = data[face][0]; //[tcbt]
  391. TR = data[face][1]; //[tcbt]
  392. }
  393. else if (mt == MeshType::Sphere)
  394. mt = mt;
  395. else if (mt == MeshType::Capsule)
  396. mt = mt;
  397. else if (mt == MeshType::Torus)
  398. mt = mt;
  399. else if (mt == MeshType::Cylinder)
  400. mt = mt;
  401. else if (mt == MeshType::Disc)
  402. mt = mt;
  403. else if (mt == MeshType::Star)
  404. mt = mt;
  405. else if (mt == MeshType::ExpandedStar)
  406. mt = mt;
  407. else if (mt == MeshType::Cog)
  408. mt = mt;
  409. }
  410. vec2 res = vec2(.0f);
  411. if (tcp == TexCoordPos::BL)
  412. res = BL;
  413. else if (tcp == TexCoordPos::BR)
  414. res = vec2(TR.x, BL.y);
  415. else if (tcp == TexCoordPos::TL)
  416. res = vec2(BL.x, TR.y);
  417. else if (tcp == TexCoordPos::TR)
  418. res = TR;
  419. return res * m_texcoord_scale + m_texcoord_offset2;
  420. }
  421. //UV2
  422. void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt] = (1 << (tcbt + 1)) | (m_texcoord_build_type2[mt] & 1); }
  423. TexCoordBuildType GetTexCoordBuildType2(MeshType mt)
  424. {
  425. uint32_t flag = ((m_texcoord_build_type2[mt] & ~(1)) >> 1);
  426. int i = 0;
  427. while (flag >>= 1)
  428. i++;
  429. return TexCoordBuildType(i);
  430. }
  431. void SetTexCoordCustomBuild2(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  432. {
  433. if (face >= m_texcoord_custom_build2[mt].Count())
  434. m_texcoord_custom_build2[mt].Resize(face + 1);
  435. m_texcoord_custom_build2[mt][face].m1 = BL;
  436. m_texcoord_custom_build2[mt][face].m2 = TR;
  437. m_texcoord_build_type2[mt] |= 1;
  438. }
  439. void ClearTexCoordCustomBuild2(MeshType mt) { m_texcoord_build_type2[mt] &= ~1; }
  440. vec2 TexCoord2(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  441. {
  442. vec2 BL = vec2(0.f);
  443. vec2 TR = vec2(0.f);
  444. if (m_texcoord_build_type2[mt] & 1 && face < m_texcoord_custom_build2[mt].Count())
  445. {
  446. BL = m_texcoord_custom_build2[mt][face].m1;
  447. TR = m_texcoord_custom_build2[mt][face].m2;
  448. }
  449. else
  450. {
  451. TexCoordBuildType tcbt = GetTexCoordBuildType2(mt);
  452. UNUSED(tcbt);
  453. if (mt == MeshType::Triangle)
  454. mt = mt;
  455. else if (mt == MeshType::Quad)
  456. {
  457. //There's nothin' else than QuadDefault
  458. BL = vec2(0.f);
  459. TR = vec2(1.f);
  460. }
  461. else if (mt == MeshType::Box)
  462. {
  463. vec2 data[][2] =
  464. { //TexCoordBuildType::BoxDefault
  465. { vec2(0.f), vec2(.5f) },
  466. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  467. { vec2(0.f), vec2(.5f) },
  468. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  469. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  470. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  471. };
  472. BL = data[face][0]; //[tcbt]
  473. TR = data[face][1]; //[tcbt]
  474. }
  475. else if (mt == MeshType::Sphere)
  476. mt = mt;
  477. else if (mt == MeshType::Capsule)
  478. mt = mt;
  479. else if (mt == MeshType::Torus)
  480. mt = mt;
  481. else if (mt == MeshType::Cylinder)
  482. mt = mt;
  483. else if (mt == MeshType::Disc)
  484. mt = mt;
  485. else if (mt == MeshType::Star)
  486. mt = mt;
  487. else if (mt == MeshType::ExpandedStar)
  488. mt = mt;
  489. else if (mt == MeshType::Cog)
  490. mt = mt;
  491. }
  492. vec2 res = vec2(.0f);
  493. if (tcp == TexCoordPos::BL)
  494. res = BL;
  495. else if (tcp == TexCoordPos::BR)
  496. res = vec2(TR.x, BL.y);
  497. else if (tcp == TexCoordPos::TL)
  498. res = vec2(BL.x, TR.y);
  499. else if (tcp == TexCoordPos::TR)
  500. res = TR;
  501. return res * m_texcoord_scale + m_texcoord_offset2;
  502. }
  503. inline bool IsEnabled(MeshBuildOperation mbo) { return (m_build_flags & mbo) != 0; }
  504. inline void Enable(MeshBuildOperation mbo) { m_build_flags |= mbo; }
  505. inline void Disable(MeshBuildOperation mbo) { m_build_flags &= ~mbo; }
  506. inline void Toggle(MeshBuildOperation mbo) { m_build_flags ^= mbo; }
  507. inline void Set(MeshBuildOperation mbo, bool value) { if (value) Enable(mbo); else Disable(mbo); }
  508. public:
  509. CommandStack m_stack;
  510. int m_cmd_i;
  511. Array<int, int> m_loop_stack;
  512. vec4 m_color_a;
  513. vec4 m_color_b;
  514. vec2 m_texcoord_offset;
  515. vec2 m_texcoord_offset2;
  516. vec2 m_texcoord_scale;
  517. vec2 m_texcoord_scale2;
  518. Array<vec2, vec2> m_texcoord_custom_build[MeshType::Max];
  519. Array<vec2, vec2> m_texcoord_custom_build2[MeshType::Max];
  520. uint32_t m_texcoord_build_type[MeshType::Max];
  521. uint32_t m_texcoord_build_type2[MeshType::Max];
  522. uint32_t m_build_flags;
  523. };
  524. /* A safe enum for MeshCSG operations. */
  525. struct CSGUsage
  526. {
  527. enum Value
  528. {
  529. Union = 0,
  530. Substract,
  531. SubstractLoss, //will remove B from A, but not add inverted B
  532. And,
  533. Xor,
  534. Max
  535. }
  536. m_value;
  537. inline CSGUsage() : m_value(Union) {}
  538. inline CSGUsage(Value v) : m_value(v) {}
  539. inline CSGUsage(int v) : m_value((Value)v) {}
  540. inline operator Value() { return m_value; }
  541. };
  542. /* A safe enum for VertexDictionnary operations. */
  543. struct VDictType
  544. {
  545. enum Value
  546. {
  547. DoesNotExist=-3,
  548. Alone=-2,
  549. Master=-1
  550. }
  551. m_value;
  552. inline VDictType(Value v) : m_value(v) {}
  553. inline operator Value() { return m_value; }
  554. };
  555. /* TODO : replace VDict by a proper Half-edge system */
  556. //a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes
  557. class VertexDictionnary
  558. {
  559. public:
  560. int FindVertexMaster(const int search_idx);
  561. bool FindMatchingVertices(const int search_idx, Array<int> &matching_ids);
  562. bool FindConnectedVertices(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_vert, Array<int> const *ignored_tri = nullptr);
  563. bool FindConnectedTriangles(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = nullptr);
  564. bool FindConnectedTriangles(const ivec2 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = nullptr);
  565. bool FindConnectedTriangles(const ivec3 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = nullptr);
  566. void AddVertex(int vert_id, vec3 vert_coord);
  567. bool GetMasterList(Array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.Count() > 0; }
  568. void Clear() { vertex_list.Empty(); }
  569. private:
  570. //<VertexId, VertexLocation, VertexMasterId>
  571. Array<int, vec3, int> vertex_list;
  572. //List of the master_ vertices
  573. Array<int> master_list;
  574. };
  575. struct Axis
  576. {
  577. enum Value
  578. {
  579. X,
  580. Y,
  581. Z
  582. }
  583. m_value;
  584. inline Axis() : m_value(X) {}
  585. inline Axis(Value v) : m_value(v) {}
  586. inline operator Value() { return m_value; }
  587. };
  588. class EasyMesh
  589. {
  590. friend class EasyMeshParser;
  591. friend class GpuEasyMeshData;
  592. public:
  593. EasyMesh();
  594. EasyMesh(const EasyMesh& em);
  595. bool Compile(char const *command);
  596. void ExecuteCmdStack();
  597. void MeshConvert(GpuShaderData* new_gpu_sdata);
  598. void MeshConvert(Shader* ProvidedShader = nullptr);
  599. bool Render(mat4 const &model);
  600. MeshRender GetMeshState() { return m_state; }
  601. bool SetRender(bool should_render);
  602. private:
  603. void UpdateVertexDict(Array< int, int > &vertex_dict);
  604. //-------------------------------------------------------------------------
  605. //Mesh CSG operations
  606. //-------------------------------------------------------------------------
  607. private:
  608. void MeshCsg(CSGUsage csg_operation);
  609. public:
  610. /* [cmd:csgu] Performs a Union operation as (mesh0_Outside + mesh1_Outside) */
  611. void CsgUnion() { MeshCsg(CSGUsage::Union); }
  612. /* [cmd:csgs] Performs a Substract operation as (mesh0_Outside + mesh1_Inside-inverted) */
  613. void CsgSub() { MeshCsg(CSGUsage::Substract); }
  614. /* [cmd:csgsl] Performs a Substract operation without keeping the mesh1 part */
  615. void CsgSubL() { MeshCsg(CSGUsage::SubstractLoss); }
  616. /* [cmd:csga] Performs an And operation as (mesh0_Inside + mesh1_Inside) */
  617. void CsgAnd() { MeshCsg(CSGUsage::And); }
  618. /* [cmd:csgx] Performs a Xor operation as (m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted) */
  619. void CsgXor() { MeshCsg(CSGUsage::Xor); }
  620. //-------------------------------------------------------------------------
  621. //Mesh Base operations
  622. //-------------------------------------------------------------------------
  623. public:
  624. /* [cmd:lp[ ]] will perform a loop of loopnb */
  625. void LoopStart(int loopnb);
  626. /* No cmd, implicit ] */
  627. void LoopEnd();
  628. /* [cmd:[] from this point onward, any operation will not be performed on previous vertices */
  629. void OpenBrace();
  630. /* [cmd:]] Merge current vertices with previous context */
  631. void CloseBrace();
  632. /* [cmd:tsw] When active, on negative-scaling, normal-vector correction will not occur */
  633. void ToggleScaleWinding();
  634. /* [cmd:tqw] When active, quad will have a fifth center vertex */
  635. void ToggleQuadWeighting();
  636. /* [cmd:sc] Set both color */
  637. void SetCurColor(vec4 const &color);
  638. /* [cmd:sca] Set base color A */
  639. void SetCurColorA(vec4 const &color);
  640. /* [cmd:scb] Set base color B */
  641. void SetCurColorB(vec4 const &color);
  642. /* [cmd:scv] Sets all vertices in this scope color. */
  643. void SetVertColor(vec4 const &color);
  644. //-------------------------------------------------------------------------
  645. //Internal : Basic triangle/vertex operations
  646. //-------------------------------------------------------------------------
  647. private:
  648. void AddVertex(vec3 const &coord);
  649. void AddDuplicateVertex(int i);
  650. void AddLerpVertex(int i, int j, float alpha);
  651. void AddLerpVertex(VertexData const &vi, VertexData const &vj, float alpha);
  652. VertexData GetLerpVertex(int i, int j, float alpha);
  653. VertexData GetLerpVertex(VertexData const &vi, VertexData const &vj, float alpha);
  654. void AppendQuad(int i1, int i2, int i3, int i4, int base);
  655. void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base);
  656. void AppendTriangle(int i1, int i2, int i3, int base);
  657. void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base);
  658. void ComputeNormals(int start, int vcount);
  659. public: //DEBUG
  660. void ComputeTexCoord(float uv_scale, int uv_offset);
  661. //-------------------------------------------------------------------------
  662. //Internal : Vertices operations
  663. //-------------------------------------------------------------------------
  664. private:
  665. void SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale);
  666. void SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale);
  667. void SetCurVertNormal(vec3 const &normal);
  668. void SetCurVertColor(vec4 const &color);
  669. void SetCurVertTexCoord(vec2 const &texcoord);
  670. void SetCurVertTexCoord2(vec2 const &texcoord);
  671. public:
  672. //-------------------------------------------------------------------------
  673. //Mesh transform operations
  674. //-------------------------------------------------------------------------
  675. /* [cmd:t/tx/ty/tz] Translate vertices
  676. - v : Translation quantity.
  677. */
  678. void Translate(vec3 const &v);
  679. /* See Rotate */
  680. void RotateX(float angle);
  681. /* See Rotate */
  682. void RotateY(float angle);
  683. /* See Rotate */
  684. void RotateZ(float angle);
  685. /* [cmd:r/rx/ry/rz] Rotate vertices
  686. - angle : rotation quantity.
  687. - axis : rotation axis.
  688. */
  689. void Rotate(float angle, vec3 const &axis);
  690. /* [cmd:rj] Randomly move vertices along Origin-to-vertex as f(vtx) = vtx + o2v * (1.0 + rand(r))
  691. - r : jitter maximum value.
  692. */
  693. void RadialJitter(float r);
  694. /* [cmd:tax] multiply axis y&z by x as f(y) = y * (1.0 + (ny * x + xoff))
  695. - ny : value of n for y.
  696. - nz : value of n for z.
  697. - xoff : value of xoff.
  698. - absolute (def:true) : if (true) Multiply will use an absolute x.
  699. */
  700. void TaperX(float ny, float nz, float xoff=0.f, bool absolute=true);
  701. /* [cmd:tay] Same as TaperX, with Y */
  702. void TaperY(float nx, float nz, float yoff=0.f, bool absolute=true);
  703. /* [cmd:taz] Same as TaperX, with Z */
  704. void TaperZ(float nx, float ny, float zoff=0.f, bool absolute=true);
  705. /* [cmd:twx] Twist vertices around x axis with x as rotation value as f(p) = (RotateX(x * t + toff) * p)
  706. - t : Angle multiplier.
  707. - toff : Applied offset.
  708. */
  709. void TwistX(float t, float toff=0.f);
  710. /* [cmd:twy] Same as TwistX, with Y */
  711. void TwistY(float t, float toff=0.f);
  712. /* [cmd:twz] Same as TwistX, with Z */
  713. void TwistZ(float t, float toff=0.f);
  714. /* [cmd:shx] Shear vertices using x value as shear quantity as f(y) = y + (ny * x + xoff)
  715. - ny : Value of n for y.
  716. - nz : Value of n for z.
  717. - xoff : Value of xoff.
  718. - absolute (def:true) : if (true) Multiply will use an absolute x.
  719. */
  720. void ShearX(float ny, float nz, float xoff=0.f, bool absolute=true);
  721. /* [cmd:shy] Same as ShearX, with Y */
  722. void ShearY(float nx, float nz, float yoff=0.f, bool absolute=true);
  723. /* [cmd:shz] Same as ShearX, with Z */
  724. void ShearZ(float nx, float ny, float zoff=0.f, bool absolute=true);
  725. /* [cmd:stx] Stretch vertices using x value as stretch quantity as f(y) = y + (pow(x, ny) + xoff)
  726. - ny : Value of n for y.
  727. - nz : Value of n for z.
  728. - xoff : Value of xoff.
  729. */
  730. void StretchX(float ny, float nz, float xoff=0.f);
  731. /* [cmd:sty] Same as StretchX, with Y */
  732. void StretchY(float nx, float nz, float yoff=0.f);
  733. /* [cmd:stz] Same as StretchX, with Z */
  734. void StretchZ(float nx, float ny, float zoff=0.f);
  735. /* [cmd:bdxy] Bend vertices using x as bend quantity along y axis using f(p) = (RotateY(x * t + toff) * p)
  736. - t : Angle multiplier.
  737. - xoff : Applied offset.
  738. */
  739. void BendXY(float t, float toff=0.f);
  740. /* [cmd:bdxz] Same as BendXY, with X & Z */
  741. void BendXZ(float t, float toff=0.f);
  742. /* [cmd:bdyx] Same as BendXY, with Y & X */
  743. void BendYX(float t, float toff=0.f);
  744. /* [cmd:bdyz] Same as BendXY, with Y & Z */
  745. void BendYZ(float t, float toff=0.f);
  746. /* [cmd:bdzx] Same as BendXY, with Z & X */
  747. void BendZX(float t, float toff=0.f);
  748. /* [cmd:bdzy] Same as BendXY, with Z & Y */
  749. void BendZY(float t, float toff=0.f);
  750. private:
  751. struct MeshTransform
  752. {
  753. enum Value
  754. {
  755. Taper,
  756. Twist,
  757. Bend,
  758. Stretch,
  759. Shear
  760. }
  761. m_value;
  762. inline MeshTransform() : m_value(Taper) {}
  763. inline MeshTransform(Value v) : m_value(v) {}
  764. inline operator Value() { return m_value; }
  765. };
  766. void DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, bool absolute=false);
  767. public:
  768. /* [cmd:s/sx/sy/sz] Scale vertices
  769. - s : scale quantity.
  770. */
  771. void Scale(vec3 const &s);
  772. void Scale(float s) { Scale(vec3(s)); }
  773. /* [cmd:mx] Mirror vertices through X-plane
  774. Acts as an OpenBrace
  775. */
  776. void MirrorX();
  777. /* [cmd:my] Mirror vertices through Y-plane
  778. Acts as an OpenBrace
  779. */
  780. void MirrorY();
  781. /* [cmd:mz] Mirror vertices through Z-plane
  782. Acts as an OpenBrace
  783. */
  784. void MirrorZ();
  785. /* [no-cmd] Duplicates vertices and scale duplicate
  786. Acts as an OpenBrace
  787. */
  788. void DupAndScale(vec3 const &s, bool open_brace=false);
  789. /* [cmd:ch] Performs a chamfer operation //TODO : Make it work
  790. - f : Chamfer quantity.
  791. */
  792. void Chamfer(float f);
  793. /* [cmd:splt] split triangles in 4 smaller ones
  794. - pass : Number of pass applied.
  795. */
  796. void SplitTriangles(int pass);
  797. private:
  798. void SplitTriangles(int pass, VertexDictionnary *vert_dict);
  799. public:
  800. /* [cmd:smth] Smooth the mesh by subdivising it.
  801. - pass : a pass is made of (n0 split then n1 smooth) repeat.
  802. - split_per_pass : n0 value in above explanation.
  803. - smooth_per_pass : n1 value in above explanation.
  804. */
  805. void SmoothMesh(int pass, int split_per_pass, int smooth_per_pass);
  806. //-------------------------------------------------------------------------
  807. //Mesh shape operations
  808. //-------------------------------------------------------------------------
  809. /* [cmd:ac] Cylinder centered on (0,0,0) with BBox [-.5*max(d1, d2), -.5*h, -.5*max(d1, d2)]
  810. - nbsides : Number of sides. [+.5*max(d1, d2), +.5*h, +.5*max(d1, d2)]
  811. - h : Height of the cylinder.
  812. - d1 : Lower diameter.
  813. - d2 : Upper diameter.
  814. - dualside : if (true) will also create inner sides : TOOD:TOREMOVE?? : needed ?
  815. - smooth : if (true) will smooth normals : TOOD:TOREMOVE : smooth should be handled elsewhere
  816. - close : if (true) will add discs to close the cylinder
  817. */
  818. void AppendCylinder(int nsides, float h, float d1, float d2,
  819. bool dualside=false, bool smooth=false, bool close=false);
  820. /* [cmd:asph] Sphere centered on (0,0,0) with BBox [-.5*d][.5*d]
  821. - ndivisions : number of subdivisions each Sphere triangle will sustain.
  822. - d : Diameter.
  823. */
  824. void AppendSphere(int ndivisions, float d);
  825. /* [cmd:acap] Capsule centered on (0,0,0) with BBox [-.5*d, -(.5*d+h), -.5*d][.5*d, (.5*d+h), .5*d]
  826. - ndivisions : number of subdivisions each Sphere triangle will sustain.
  827. - h : Inner height.
  828. - d : Diameter.
  829. */
  830. void AppendCapsule(int ndivisions, float h, float d);
  831. /* [cmd:ato] Torus centered on (0,0,0) with BBox [-.5*d2][.5*d2]
  832. - ndivisions : number of subdivisions of the torus.
  833. - d1 : Inner diameter.
  834. - d2 : Outer diameter.
  835. */
  836. void AppendTorus(int ndivisions, float d1, float d2);
  837. /* [cmd:ab] Box centered on (0,0,0) with BBox [-.5 * size][.5 * size]
  838. - size : size of the box.
  839. - chamf : size of the chamfer.
  840. */
  841. void AppendBox(vec3 const &size, float chamf=0.f);
  842. //Same as AppendBox
  843. void AppendSmoothChamfBox(vec3 const &size, float chamf);
  844. //Same as AppendBox
  845. void AppendFlatChamfBox(vec3 const &size, float chamf);
  846. //Same as AppendBox
  847. void AppendBox(vec3 const &size, float chamf, bool smooth);
  848. /* [cmd:as]
  849. Append a Star centered on (0,0,0) contained within a disc of "max(d1, d2)" diameter.
  850. - nbranches : Number of branches.
  851. - d1 : double Length of the branches.
  852. - d2 : double Length of the "branch" located between d1-branches.
  853. - fade : if (true) in-between branches use ColorB.
  854. - fade2 : if (true) Star branches use ColorB.
  855. */
  856. void AppendStar(int nbranches, float d1, float d2,
  857. bool fade=false, bool fade2=false);
  858. /* [cmd:aes] Star centered on (0,0,0) contained within a disc of "max(max(d1, d2), max(d1 + extrad, d2 + extrad))" diameter.
  859. Expanded star branches use ColorB.
  860. - nbranches : Number of branches.
  861. - d1 : Double Length of the branches.
  862. - d2 : Double Length of the "branch" located between r1-branches.
  863. - extrad : Extra length added to expand all branches.
  864. */
  865. void AppendExpandedStar(int nbranches, float d1, float d2, float extrad=0.f);
  866. /* [cmd:ad] Disc centered on (0,0,0) with d diameter.
  867. - nbsides : Number of sides.
  868. - d : Diameter.
  869. - fade : if (true) Outer vertices will use ColorB
  870. */
  871. void AppendDisc(int nsides, float d, bool fade=false);
  872. /* [cmd:at] Triangle centered on (0,0,0) contained within a disc of "d" diameter.
  873. - d : diameter of the containing disc..
  874. - fade : if (true) 2nd & 3rd Vertices will use ColorB
  875. */
  876. void AppendSimpleTriangle(float d, bool fade=false);
  877. /* [cmd:aq] Quad centered on (0,0,0) contained within BBox [-size*.5f, 0, -size*.5f][size*.5f, 0, size*.5f]
  878. - size : Size of quad.
  879. - fade : if (true) 3rd & 4th Vertices will use ColorB
  880. */
  881. void AppendSimpleQuad(float size, bool fade=false);
  882. private:
  883. //complex version of above one
  884. void AppendSimpleQuad(vec2 p1, vec2 p2, float z=0.f, bool fade=false);
  885. public:
  886. /* [cmd:acg] Gear centered on (0,0,0) contained within BBox [-.5*max(d1,d2), -.5*h, -.5*max(d1, d2)]
  887. - h : Height of the Gear. [+.5*max(d1,d2), +.5*h, +.5*max(d1, d2)]
  888. - d10 : Upper Inner diameter.
  889. - d20 : Lower Inner diameter.
  890. - d1 : Upper Outer diameter.
  891. - d2 : Lower Outer diameter.
  892. - d12 : Upper Cog diameter.
  893. - d22 : Lower Cog diameter.
  894. - sidemul : multiplier for the size of the cogs.
  895. - offset : useless
  896. */
  897. void AppendCog(int nbsides, float h, float d10, float d20, float d11,
  898. float d21, float d12, float d22, float sidemul=0.f, bool offset=false);
  899. //-------------------------------------------------------------------------
  900. //TODO : Mesh Bone operations
  901. //-------------------------------------------------------------------------
  902. //void AddBone(int parent_id) {}
  903. //Convenience functions
  904. public:
  905. int GetVertexCount() { return m_vert.Count(); }
  906. vec3 const &GetVertexLocation(int i) { return m_vert[i].m_coord; }
  907. private:
  908. Array<uint16_t> m_indices;
  909. Array<VertexData> m_vert;
  910. //<vert count, indices count>
  911. Array<int, int> m_cursors;
  912. MeshRender m_state;
  913. GpuEasyMeshData m_gpu_data;
  914. public:
  915. inline EasyMeshBuildData* BD()
  916. {
  917. if (!m_build_data)
  918. m_build_data = new EasyMeshBuildData();
  919. return m_build_data;
  920. };
  921. private:
  922. class EasyMeshBuildData* m_build_data;
  923. };
  924. } /* namespace lol */
  925. #endif /* __EASYMESH_EASYMESH_H__ */