414 wiersze
14 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  5. // (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  6. // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
  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 __EASYMESHBUILD_EASYMESHBUILD_H__
  17. #define __EASYMESHBUILD_EASYMESHBUILD_H__
  18. namespace lol
  19. {
  20. struct MeshBuildOperation
  21. {
  22. DEF_VALUE
  23. //When this flag is up, negative scaling will not invert faces.
  24. ADD_VALUE_SET(ScaleWinding , (1 << 0))
  25. ADD_VALUE_SET(CommandRecording , (1 << 1))
  26. ADD_VALUE_SET(CommandExecution , (1 << 2))
  27. ADD_VALUE_SET(QuadWeighting , (1 << 3))
  28. ADD_VALUE_SET(IgnoreQuadWeighting , (1 << 4))
  29. ADD_VALUE_SET(PostBuildComputeNormals , (1 << 5))
  30. ADD_VALUE_SET(PreventVertCleanup , (1 << 6))
  31. ADD_VALUE_SET(All , 0xffff)
  32. END_E_VALUE
  33. LOL_DECLARE_ENUM_METHODS(MeshBuildOperation)
  34. };
  35. struct EasyMeshCmdType
  36. {
  37. DEF_VALUE
  38. ADD_VALUE(MeshCsg)
  39. ADD_VALUE(LoopStart)
  40. ADD_VALUE(LoopEnd)
  41. ADD_VALUE(OpenBrace)
  42. ADD_VALUE(CloseBrace)
  43. ADD_VALUE(ScaleWinding)
  44. ADD_VALUE(QuadWeighting)
  45. ADD_VALUE(PostBuildNormal)
  46. ADD_VALUE(PreventVertCleanup)
  47. ADD_VALUE(SetColorA)
  48. ADD_VALUE(SetColorB)
  49. ADD_VALUE(SetVertColor)
  50. ADD_VALUE(VerticesMerge)
  51. ADD_VALUE(VerticesSeparate)
  52. ADD_VALUE(Translate)
  53. ADD_VALUE(Rotate)
  54. ADD_VALUE(RadialJitter)
  55. ADD_VALUE(MeshTranform)
  56. ADD_VALUE(Scale)
  57. ADD_VALUE(DupAndScale)
  58. ADD_VALUE(Chamfer)
  59. ADD_VALUE(SplitTriangles)
  60. ADD_VALUE(SmoothMesh)
  61. ADD_VALUE(AppendCylinder)
  62. ADD_VALUE(AppendCapsule)
  63. ADD_VALUE(AppendTorus)
  64. ADD_VALUE(AppendBox)
  65. ADD_VALUE(AppendStar)
  66. ADD_VALUE(AppendExpandedStar)
  67. ADD_VALUE(AppendDisc)
  68. ADD_VALUE(AppendSimpleTriangle)
  69. ADD_VALUE(AppendSimpleQuad)
  70. ADD_VALUE(AppendCog)
  71. END_E_VALUE
  72. LOL_DECLARE_ENUM_METHODS(EasyMeshCmdType)
  73. };
  74. LOL_SAFE_ENUM(MeshType,
  75. Triangle,
  76. Quad,
  77. Box,
  78. Sphere,
  79. Capsule,
  80. Torus,
  81. Cylinder,
  82. Disc,
  83. Star,
  84. ExpandedStar,
  85. Cog,
  86. MAX
  87. );
  88. struct TexCoordBuildType
  89. {
  90. DEF_VALUE
  91. ADD_VALUE_SET(TriangleDefault , 0)
  92. ADD_VALUE_SET(QuadDefault , 0)
  93. ADD_VALUE_SET(BoxDefault , 0)
  94. ADD_VALUE_SET(SphereDefault , 0)
  95. ADD_VALUE_SET(CapsuleDefault , 0)
  96. ADD_VALUE_SET(TorusDefault , 0)
  97. ADD_VALUE_SET(CylinderDefault , 0)
  98. ADD_VALUE_SET(DiscDefault , 0)
  99. ADD_VALUE_SET(StarDefault , 0)
  100. ADD_VALUE_SET(ExpandedStarDefault , 0)
  101. ADD_VALUE_SET(CogDefault , 0)
  102. //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE
  103. ADD_VALUE_SET(Max , 1)
  104. END_E_VALUE
  105. LOL_DECLARE_ENUM_METHODS(TexCoordBuildType)
  106. };
  107. LOL_SAFE_ENUM(MeshFaceType,
  108. BoxFront = 0,
  109. QuadDefault = 0,
  110. BoxLeft = 1,
  111. BoxBack = 2,
  112. BoxRight = 3,
  113. BoxTop = 4,
  114. BoxBottom = 5,
  115. Max
  116. );
  117. LOL_SAFE_ENUM(TexCoordPos,
  118. BL, // Bottom Left
  119. BR, // Bottom Right
  120. TL, // Top Left
  121. TR // Top Right
  122. );
  123. class EasyMeshBuildData
  124. {
  125. public:
  126. EasyMeshBuildData()
  127. {
  128. m_color_a = vec4(0.f, 0.f, 0.f, 1.f);
  129. m_color_b = vec4(0.f, 0.f, 0.f, 1.f);
  130. m_texcoord_offset = vec2(0.f);
  131. m_texcoord_offset2 = vec2(0.f);
  132. m_texcoord_scale = vec2(1.f);
  133. m_texcoord_scale2 = vec2(1.f);
  134. m_build_flags = 0;
  135. m_i_cmd = 0;
  136. m_exec_nb = -1;
  137. for (int i = 0; i < MeshType::MAX; ++i)
  138. {
  139. m_texcoord_build_type[i] = TexCoordBuildType::TriangleDefault;
  140. m_texcoord_build_type2[i] = TexCoordBuildType::TriangleDefault;
  141. }
  142. }
  143. inline CommandStack &CmdStack() { return m_stack; }
  144. inline int &Cmdi() { return m_i_cmd; }
  145. inline int &CmdExecNb() { return m_exec_nb; }
  146. inline Array<int, int> &LoopStack(){ return m_loop_stack; }
  147. inline vec4 &ColorA() { return m_color_a; }
  148. inline vec4 &ColorB() { return m_color_b; }
  149. inline vec2 &TexCoordOffset() { return m_texcoord_offset; }
  150. inline vec2 &TexCoordScale() { return m_texcoord_scale; }
  151. inline vec2 &TexCoordOffset2() { return m_texcoord_offset2; }
  152. inline vec2 &TexCoordScale2() { return m_texcoord_scale2; }
  153. //UV1
  154. void SetTexCoordBuildType(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type[mt.ToScalar()] = (1 << (tcbt + 1)) | (m_texcoord_build_type[mt.ToScalar()] & 1); }
  155. TexCoordBuildType GetTexCoordBuildType(MeshType mt)
  156. {
  157. uint32_t flag = (uint32_t)((m_texcoord_build_type[mt.ToScalar()] & ~(1)) >> 1);
  158. int i = 0;
  159. while (flag >>= 1)
  160. i++;
  161. return TexCoordBuildType(i);
  162. }
  163. void SetTexCoordCustomBuild(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  164. {
  165. if (face.ToScalar() >= m_texcoord_custom_build[mt.ToScalar()].Count())
  166. m_texcoord_custom_build[mt.ToScalar()].Resize(face.ToScalar() + 1);
  167. m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m1 = BL;
  168. m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m2 = TR;
  169. m_texcoord_build_type[mt.ToScalar()] |= 1;
  170. }
  171. void ClearTexCoordCustomBuild(MeshType mt) { m_texcoord_build_type[mt.ToScalar()] &= ~1; }
  172. /* FIXME : Do something better ? */
  173. vec2 TexCoord(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  174. {
  175. vec2 BL = vec2(0.f);
  176. vec2 TR = vec2(0.f);
  177. if (m_texcoord_build_type[mt.ToScalar()] & 1
  178. && face.ToScalar() < m_texcoord_custom_build[mt.ToScalar()].Count())
  179. {
  180. BL = m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m1;
  181. TR = m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m2;
  182. }
  183. else
  184. {
  185. /* unused for now, but will be if new BuildType are added. */
  186. TexCoordBuildType tcbt = GetTexCoordBuildType(mt);
  187. UNUSED(tcbt);
  188. if (mt == MeshType::Triangle)
  189. mt = mt;
  190. else if (mt == MeshType::Quad)
  191. {
  192. // There's nothin' else than QuadDefault
  193. BL = vec2(0.f);
  194. TR = vec2(1.f);
  195. }
  196. else if (mt == MeshType::Box)
  197. {
  198. vec2 data[][2] =
  199. { // TexCoordBuildType::BoxDefault
  200. { vec2(0.f), vec2(.5f) },
  201. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  202. { vec2(0.f), vec2(.5f) },
  203. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  204. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  205. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  206. };
  207. BL = data[face.ToScalar()][0]; // [tcbt]
  208. TR = data[face.ToScalar()][1]; // [tcbt]
  209. }
  210. else if (mt == MeshType::Sphere)
  211. mt = mt;
  212. else if (mt == MeshType::Capsule)
  213. mt = mt;
  214. else if (mt == MeshType::Torus)
  215. mt = mt;
  216. else if (mt == MeshType::Cylinder)
  217. mt = mt;
  218. else if (mt == MeshType::Disc)
  219. mt = mt;
  220. else if (mt == MeshType::Star)
  221. mt = mt;
  222. else if (mt == MeshType::ExpandedStar)
  223. mt = mt;
  224. else if (mt == MeshType::Cog)
  225. mt = mt;
  226. }
  227. vec2 res = vec2(.0f);
  228. if (tcp == TexCoordPos::BL)
  229. res = BL;
  230. else if (tcp == TexCoordPos::BR)
  231. res = vec2(TR.x, BL.y);
  232. else if (tcp == TexCoordPos::TL)
  233. res = vec2(BL.x, TR.y);
  234. else if (tcp == TexCoordPos::TR)
  235. res = TR;
  236. return res * m_texcoord_scale + m_texcoord_offset2;
  237. }
  238. // UV2
  239. void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt.ToScalar()] = (1 << (tcbt + 1)) | (m_texcoord_build_type2[mt.ToScalar()] & 1); }
  240. TexCoordBuildType GetTexCoordBuildType2(MeshType mt)
  241. {
  242. uint32_t flag = ((m_texcoord_build_type2[mt.ToScalar()] & ~(1)) >> 1);
  243. int i = 0;
  244. while (flag >>= 1)
  245. i++;
  246. return TexCoordBuildType(i);
  247. }
  248. void SetTexCoordCustomBuild2(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  249. {
  250. if (face.ToScalar() >= m_texcoord_custom_build2[mt.ToScalar()].Count())
  251. m_texcoord_custom_build2[mt.ToScalar()].Resize(face.ToScalar() + 1);
  252. m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m1 = BL;
  253. m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m2 = TR;
  254. m_texcoord_build_type2[mt.ToScalar()] |= 1;
  255. }
  256. void ClearTexCoordCustomBuild2(MeshType mt) { m_texcoord_build_type2[mt.ToScalar()] &= ~1; }
  257. vec2 TexCoord2(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  258. {
  259. vec2 BL = vec2(0.f);
  260. vec2 TR = vec2(0.f);
  261. if (m_texcoord_build_type2[mt.ToScalar()] & 1
  262. && face.ToScalar() < m_texcoord_custom_build2[mt.ToScalar()].Count())
  263. {
  264. BL = m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m1;
  265. TR = m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m2;
  266. }
  267. else
  268. {
  269. TexCoordBuildType tcbt = GetTexCoordBuildType2(mt);
  270. UNUSED(tcbt);
  271. if (mt == MeshType::Triangle)
  272. mt = mt;
  273. else if (mt == MeshType::Quad)
  274. {
  275. // There's nothin' else than QuadDefault
  276. BL = vec2(0.f);
  277. TR = vec2(1.f);
  278. }
  279. else if (mt == MeshType::Box)
  280. {
  281. vec2 data[][2] =
  282. { // TexCoordBuildType::BoxDefault
  283. { vec2(0.f), vec2(.5f) },
  284. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  285. { vec2(0.f), vec2(.5f) },
  286. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  287. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  288. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  289. };
  290. BL = data[face.ToScalar()][0]; // [tcbt]
  291. TR = data[face.ToScalar()][1]; // [tcbt]
  292. }
  293. else if (mt == MeshType::Sphere)
  294. mt = mt;
  295. else if (mt == MeshType::Capsule)
  296. mt = mt;
  297. else if (mt == MeshType::Torus)
  298. mt = mt;
  299. else if (mt == MeshType::Cylinder)
  300. mt = mt;
  301. else if (mt == MeshType::Disc)
  302. mt = mt;
  303. else if (mt == MeshType::Star)
  304. mt = mt;
  305. else if (mt == MeshType::ExpandedStar)
  306. mt = mt;
  307. else if (mt == MeshType::Cog)
  308. mt = mt;
  309. }
  310. vec2 res = vec2(.0f);
  311. if (tcp == TexCoordPos::BL)
  312. res = BL;
  313. else if (tcp == TexCoordPos::BR)
  314. res = vec2(TR.x, BL.y);
  315. else if (tcp == TexCoordPos::TL)
  316. res = vec2(BL.x, TR.y);
  317. else if (tcp == TexCoordPos::TR)
  318. res = TR;
  319. return res * m_texcoord_scale + m_texcoord_offset2;
  320. }
  321. inline bool IsEnabled(MeshBuildOperation mbo) { return (m_build_flags & mbo) != 0; }
  322. inline void Enable(MeshBuildOperation mbo) { m_build_flags |= mbo; }
  323. inline void Disable(MeshBuildOperation mbo) { m_build_flags &= ~mbo; }
  324. inline void Toggle(MeshBuildOperation mbo) { m_build_flags ^= mbo; }
  325. inline void Set(MeshBuildOperation mbo, bool value) { if (value) Enable(mbo); else Disable(mbo); }
  326. public:
  327. CommandStack m_stack;
  328. int m_i_cmd;
  329. int m_exec_nb;
  330. Array<int, int> m_loop_stack;
  331. vec4 m_color_a;
  332. vec4 m_color_b;
  333. vec2 m_texcoord_offset;
  334. vec2 m_texcoord_offset2;
  335. vec2 m_texcoord_scale;
  336. vec2 m_texcoord_scale2;
  337. Array<vec2, vec2> m_texcoord_custom_build[MeshType::MAX];
  338. Array<vec2, vec2> m_texcoord_custom_build2[MeshType::MAX];
  339. uint32_t m_texcoord_build_type[MeshType::MAX];
  340. uint32_t m_texcoord_build_type2[MeshType::MAX];
  341. uint32_t m_build_flags;
  342. };
  343. /* A safe enum for VertexDictionnary operations. */
  344. struct VDictType
  345. {
  346. DEF_VALUE
  347. ADD_VALUE_SET(DoesNotExist , -3)
  348. ADD_VALUE_SET(Alone , -2)
  349. ADD_VALUE_SET(Master , -1)
  350. END_E_VALUE
  351. LOL_DECLARE_ENUM_METHODS(VDictType)
  352. };
  353. /* TODO : replace VDict by a proper Half-edge system */
  354. //a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes
  355. class VertexDictionnary
  356. {
  357. public:
  358. int FindVertexMaster(const int search_idx);
  359. bool FindMatchingVertices(const int search_idx, Array<int> &matching_ids);
  360. 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);
  361. 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);
  362. 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);
  363. 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);
  364. void AddVertex(int vert_id, vec3 vert_coord);
  365. void RemoveVertex(int vert_id);
  366. bool GetMasterList(Array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.Count() > 0; }
  367. void Clear() { vertex_list.Empty(); }
  368. private:
  369. //<VertexId, VertexLocation, VertexMasterId>
  370. Array<int, vec3, int> vertex_list;
  371. //List of the master_ vertices
  372. Array<int> master_list;
  373. };
  374. } /* namespace lol */
  375. #endif /* __EASYMESHBUILD_EASYMESHBUILD_H__ */