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.
 
 
 
 
 
 

559 lines
19 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. // © 2009—2013 Cédric Lecacheur <jordx@free.fr>
  6. // © 2009—2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  7. //
  8. // Lol Engine is free software. It comes without any warranty, to
  9. // the extent permitted by applicable law. You can redistribute it
  10. // and/or modify it under the terms of the Do What the Fuck You Want
  11. // to Public License, Version 2, as published by the WTFPL Task Force.
  12. // See http://www.wtfpl.net/ for more details.
  13. //
  14. #pragma once
  15. #include <map>
  16. // Vertex building operations
  17. namespace lol
  18. {
  19. //MeshBuildOperation ----------------------------------------------------------
  20. struct MeshBuildOperationBase : public StructSafeEnum
  21. {
  22. enum Type
  23. {
  24. //When this flag is up, negative scaling will not invert faces.
  25. ScaleWinding = (1 << 0),
  26. CommandRecording = (1 << 1),
  27. CommandExecution = (1 << 2),
  28. QuadWeighting = (1 << 3),
  29. IgnoreQuadWeighting = (1 << 4),
  30. PostBuildComputeNormals = (1 << 5),
  31. PreventVertCleanup = (1 << 6),
  32. All = 0xffff,
  33. };
  34. protected:
  35. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  36. {
  37. enum_map[ScaleWinding] = "ScaleWinding";
  38. enum_map[CommandRecording] = "CommandRecording";
  39. enum_map[CommandExecution] = "CommandExecution";
  40. enum_map[QuadWeighting] = "QuadWeighting";
  41. enum_map[IgnoreQuadWeighting] = "IgnoreQuadWeighting";
  42. enum_map[PostBuildComputeNormals] = "PostBuildComputeNormals";
  43. enum_map[PreventVertCleanup] = "PreventVertCleanup";
  44. enum_map[All] = "All";
  45. return true;
  46. }
  47. };
  48. typedef SafeEnum<MeshBuildOperationBase> MeshBuildOperation;
  49. //EasyMeshCmdType -------------------------------------------------------------
  50. struct EasyMeshCmdTypeBase : public StructSafeEnum
  51. {
  52. enum Type
  53. {
  54. MeshCsg,
  55. LoopStart,
  56. LoopEnd,
  57. OpenBrace,
  58. CloseBrace,
  59. ScaleWinding,
  60. QuadWeighting,
  61. PostBuildNormal,
  62. PreventVertCleanup,
  63. SetColorA,
  64. SetColorB,
  65. SetVertColor,
  66. VerticesMerge,
  67. VerticesSeparate,
  68. Translate,
  69. Rotate,
  70. RadialJitter,
  71. MeshTranform,
  72. Scale,
  73. DupAndScale,
  74. Chamfer,
  75. SplitTriangles,
  76. SmoothMesh,
  77. AppendCylinder,
  78. AppendCapsule,
  79. AppendTorus,
  80. AppendBox,
  81. AppendStar,
  82. AppendExpandedStar,
  83. AppendDisc,
  84. AppendSimpleTriangle,
  85. AppendSimpleQuad,
  86. AppendCog,
  87. };
  88. protected:
  89. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  90. {
  91. enum_map[MeshCsg] = "MeshCsg";
  92. enum_map[LoopStart] = "LoopStart";
  93. enum_map[LoopEnd] = "LoopEnd";
  94. enum_map[OpenBrace] = "OpenBrace";
  95. enum_map[CloseBrace] = "CloseBrace";
  96. enum_map[ScaleWinding] = "ScaleWinding";
  97. enum_map[QuadWeighting] = "QuadWeighting";
  98. enum_map[PostBuildNormal] = "PostBuildNormal";
  99. enum_map[PreventVertCleanup] = "PreventVertCleanup";
  100. enum_map[SetColorA] = "SetColorA";
  101. enum_map[SetColorB] = "SetColorB";
  102. enum_map[SetVertColor] = "SetVertColor";
  103. enum_map[VerticesMerge] = "VerticesMerge";
  104. enum_map[VerticesSeparate] = "VerticesSeparate";
  105. enum_map[Translate] = "Translate";
  106. enum_map[Rotate] = "Rotate";
  107. enum_map[RadialJitter] = "RadialJitter";
  108. enum_map[MeshTranform] = "MeshTranform";
  109. enum_map[Scale] = "Scale";
  110. enum_map[DupAndScale] = "DupAndScale";
  111. enum_map[Chamfer] = "Chamfer";
  112. enum_map[SplitTriangles] = "SplitTriangles";
  113. enum_map[SmoothMesh] = "SmoothMesh";
  114. enum_map[AppendCylinder] = "AppendCylinder";
  115. enum_map[AppendCapsule] = "AppendCapsule";
  116. enum_map[AppendTorus] = "AppendTorus";
  117. enum_map[AppendBox] = "AppendBox";
  118. enum_map[AppendStar] = "AppendStar";
  119. enum_map[AppendExpandedStar] = "AppendExpandedStar";
  120. enum_map[AppendDisc] = "AppendDisc";
  121. enum_map[AppendSimpleTriangle] = "AppendSimpleTriangle";
  122. enum_map[AppendSimpleQuad] = "AppendSimpleQuad";
  123. enum_map[AppendCog] = "AppendCog";
  124. return true;
  125. }
  126. };
  127. typedef SafeEnum<EasyMeshCmdTypeBase> EasyMeshCmdType;
  128. //MeshTypeBase ----------------------------------------------------------------
  129. struct MeshTypeBase : public StructSafeEnum
  130. {
  131. /* A safe enum for Primitive edge face. */
  132. enum Type
  133. {
  134. Triangle,
  135. Quad,
  136. Box,
  137. Sphere,
  138. Capsule,
  139. Torus,
  140. Cylinder,
  141. Disc,
  142. Star,
  143. ExpandedStar,
  144. Cog,
  145. MAX
  146. };
  147. protected:
  148. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  149. {
  150. enum_map[Triangle] = "Triangle";
  151. enum_map[Quad] = "Quad";
  152. enum_map[Box] = "Box";
  153. enum_map[Sphere] = "Sphere";
  154. enum_map[Capsule] = "Capsule";
  155. enum_map[Torus] = "Torus";
  156. enum_map[Cylinder] = "Cylinder";
  157. enum_map[Disc] = "Disc";
  158. enum_map[Star] = "Star";
  159. enum_map[ExpandedStar] = "ExpandedStar";
  160. enum_map[Cog] = "Cog";
  161. enum_map[MAX] = "MAX";
  162. return true;
  163. }
  164. };
  165. typedef SafeEnum<MeshTypeBase> MeshType;
  166. //TexCoordBuildType -----------------------------------------------------------
  167. struct TexCoordBuildTypeBase : public StructSafeEnum
  168. {
  169. enum Type
  170. {
  171. TriangleDefault,
  172. QuadDefault,
  173. BoxDefault,
  174. SphereDefault,
  175. CapsuleDefault,
  176. TorusDefault,
  177. CylinderDefault,
  178. DiscDefault,
  179. StarDefault,
  180. ExpandedStarDefault,
  181. CogDefault,
  182. //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE
  183. Max
  184. };
  185. protected:
  186. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  187. {
  188. enum_map[TriangleDefault] = "TriangleDefault";
  189. enum_map[QuadDefault] = "QuadDefault";
  190. enum_map[BoxDefault] = "BoxDefault";
  191. enum_map[SphereDefault] = "SphereDefault";
  192. enum_map[CapsuleDefault] = "CapsuleDefault";
  193. enum_map[TorusDefault] = "TorusDefault";
  194. enum_map[CylinderDefault] = "CylinderDefault";
  195. enum_map[DiscDefault] = "DiscDefault";
  196. enum_map[StarDefault] = "StarDefault";
  197. enum_map[ExpandedStarDefault] = "ExpandedStarDefault";
  198. enum_map[CogDefault] = "CogDefault";
  199. enum_map[Max] = "Max";
  200. return true;
  201. }
  202. };
  203. typedef SafeEnum<TexCoordBuildTypeBase> TexCoordBuildType;
  204. //MeshFaceType ----------------------------------------------------------------
  205. struct MeshFaceTypeBase : public StructSafeEnum
  206. {
  207. enum Type
  208. {
  209. BoxFront = 0,
  210. QuadDefault = 0,
  211. BoxLeft = 1,
  212. BoxBack = 2,
  213. BoxRight = 3,
  214. BoxTop = 4,
  215. BoxBottom = 5,
  216. MAX
  217. };
  218. protected:
  219. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  220. {
  221. enum_map[BoxFront] = "BoxFront";
  222. enum_map[QuadDefault] = "QuadDefault";
  223. enum_map[BoxLeft] = "BoxLeft";
  224. enum_map[BoxBack] = "BoxBack";
  225. enum_map[BoxRight] = "BoxRight";
  226. enum_map[BoxTop] = "BoxTop";
  227. enum_map[BoxBottom] = "BoxBottom";
  228. enum_map[MAX] = "MAX";
  229. return true;
  230. }
  231. };
  232. typedef SafeEnum<MeshFaceTypeBase> MeshFaceType;
  233. //TexCoordPos -----------------------------------------------------------------
  234. struct TexCoordPosBase : public StructSafeEnum
  235. {
  236. enum Type
  237. {
  238. BL, // Bottom Left
  239. BR, // Bottom Right
  240. TL, // Top Left
  241. TR // Top Right
  242. };
  243. protected:
  244. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  245. {
  246. enum_map[BL] = "BL";
  247. enum_map[BR] = "BR";
  248. enum_map[TL] = "TL";
  249. enum_map[TR] = "TR";
  250. return true;
  251. }
  252. };
  253. typedef SafeEnum<TexCoordPosBase> TexCoordPos;
  254. class EasyMeshBuildData
  255. {
  256. public:
  257. EasyMeshBuildData()
  258. {
  259. m_color_a = vec4(0.f, 0.f, 0.f, 1.f);
  260. m_color_b = vec4(0.f, 0.f, 0.f, 1.f);
  261. m_texcoord_offset = vec2(0.f);
  262. m_texcoord_offset2 = vec2(0.f);
  263. m_texcoord_scale = vec2(1.f);
  264. m_texcoord_scale2 = vec2(1.f);
  265. m_build_flags = 0;
  266. m_i_cmd = 0;
  267. m_exec_nb = -1;
  268. for (int i = 0; i < MeshType::MAX; ++i)
  269. {
  270. m_texcoord_build_type[i] = TexCoordBuildType::TriangleDefault;
  271. m_texcoord_build_type2[i] = TexCoordBuildType::TriangleDefault;
  272. }
  273. }
  274. inline CommandStack &CmdStack() { return m_stack; }
  275. inline int &Cmdi() { return m_i_cmd; }
  276. inline int &CmdExecNb() { return m_exec_nb; }
  277. inline easy_array<int, int> &LoopStack(){ return m_loop_stack; }
  278. inline vec4 &ColorA() { return m_color_a; }
  279. inline vec4 &ColorB() { return m_color_b; }
  280. inline vec2 &TexCoordOffset() { return m_texcoord_offset; }
  281. inline vec2 &TexCoordScale() { return m_texcoord_scale; }
  282. inline vec2 &TexCoordOffset2() { return m_texcoord_offset2; }
  283. inline vec2 &TexCoordScale2() { return m_texcoord_scale2; }
  284. //UV1
  285. void SetTexCoordBuildType(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type[mt.ToScalar()] = (1 << (tcbt.ToScalar() + 1)) | (m_texcoord_build_type[mt.ToScalar()] & 1); }
  286. TexCoordBuildType GetTexCoordBuildType(MeshType mt)
  287. {
  288. uint32_t flag = (uint32_t)((m_texcoord_build_type[mt.ToScalar()] & ~(1)) >> 1);
  289. int i = 0;
  290. while (flag >>= 1)
  291. i++;
  292. return TexCoordBuildType(i);
  293. }
  294. void SetTexCoordCustomBuild(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  295. {
  296. if (face.ToScalar() >= m_texcoord_custom_build[mt.ToScalar()].count())
  297. m_texcoord_custom_build[mt.ToScalar()].resize(face.ToScalar() + 1);
  298. std::get<0>(m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()]) = BL;
  299. std::get<1>(m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()]) = TR;
  300. m_texcoord_build_type[mt.ToScalar()] |= 1;
  301. }
  302. void ClearTexCoordCustomBuild(MeshType mt) { m_texcoord_build_type[mt.ToScalar()] &= ~1; }
  303. /* FIXME : Do something better ? */
  304. vec2 TexCoord(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  305. {
  306. vec2 BL = vec2(0.f);
  307. vec2 TR = vec2(0.f);
  308. if (m_texcoord_build_type[mt.ToScalar()] & 1
  309. && face.ToScalar() < m_texcoord_custom_build[mt.ToScalar()].count())
  310. {
  311. BL = std::get<0>(m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()]);
  312. TR = std::get<1>(m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()]);
  313. }
  314. else
  315. {
  316. /* unused for now, but will be if new BuildType are added. */
  317. TexCoordBuildType tcbt = GetTexCoordBuildType(mt);
  318. (void)tcbt;
  319. if (mt == MeshType::Quad)
  320. {
  321. // There's nothin' else than QuadDefault
  322. BL = vec2(0.f);
  323. TR = vec2(1.f);
  324. }
  325. #if 0
  326. else if (mt == MeshType::Triangle)
  327. mt = mt;
  328. #endif
  329. else if (mt == MeshType::Box)
  330. {
  331. vec2 data[][2] =
  332. { // TexCoordBuildType::BoxDefault
  333. { vec2(0.f), vec2(.5f) },
  334. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  335. { vec2(0.f), vec2(.5f) },
  336. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  337. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  338. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  339. };
  340. BL = data[face.ToScalar()][0]; // [tcbt]
  341. TR = data[face.ToScalar()][1]; // [tcbt]
  342. }
  343. #if 0
  344. else if (mt == MeshType::Sphere)
  345. mt = mt;
  346. else if (mt == MeshType::Capsule)
  347. mt = mt;
  348. else if (mt == MeshType::Torus)
  349. mt = mt;
  350. else if (mt == MeshType::Cylinder)
  351. mt = mt;
  352. else if (mt == MeshType::Disc)
  353. mt = mt;
  354. else if (mt == MeshType::Star)
  355. mt = mt;
  356. else if (mt == MeshType::ExpandedStar)
  357. mt = mt;
  358. else if (mt == MeshType::Cog)
  359. mt = mt;
  360. #endif
  361. }
  362. vec2 res = vec2(.0f);
  363. if (tcp == TexCoordPos::BL)
  364. res = BL;
  365. else if (tcp == TexCoordPos::BR)
  366. res = vec2(TR.x, BL.y);
  367. else if (tcp == TexCoordPos::TL)
  368. res = vec2(BL.x, TR.y);
  369. else if (tcp == TexCoordPos::TR)
  370. res = TR;
  371. return res * m_texcoord_scale + m_texcoord_offset2;
  372. }
  373. // UV2
  374. void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt.ToScalar()] = (1 << (tcbt.ToScalar() + 1)) | (m_texcoord_build_type2[mt.ToScalar()] & 1); }
  375. TexCoordBuildType GetTexCoordBuildType2(MeshType mt)
  376. {
  377. uint32_t flag = ((m_texcoord_build_type2[mt.ToScalar()] & ~(1)) >> 1);
  378. int i = 0;
  379. while (flag >>= 1)
  380. i++;
  381. return TexCoordBuildType(i);
  382. }
  383. void SetTexCoordCustomBuild2(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
  384. {
  385. if (face.ToScalar() >= m_texcoord_custom_build2[mt.ToScalar()].count())
  386. m_texcoord_custom_build2[mt.ToScalar()].resize(face.ToScalar() + 1);
  387. std::get<0>(m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()]) = BL;
  388. std::get<1>(m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()]) = TR;
  389. m_texcoord_build_type2[mt.ToScalar()] |= 1;
  390. }
  391. void ClearTexCoordCustomBuild2(MeshType mt) { m_texcoord_build_type2[mt.ToScalar()] &= ~1; }
  392. vec2 TexCoord2(MeshType mt, TexCoordPos tcp, MeshFaceType face)
  393. {
  394. vec2 BL = vec2(0.f);
  395. vec2 TR = vec2(0.f);
  396. if (m_texcoord_build_type2[mt.ToScalar()] & 1
  397. && face.ToScalar() < m_texcoord_custom_build2[mt.ToScalar()].count())
  398. {
  399. BL = std::get<0>(m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()]);
  400. TR = std::get<1>(m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()]);
  401. }
  402. else
  403. {
  404. TexCoordBuildType tcbt = GetTexCoordBuildType2(mt);
  405. (void)tcbt;
  406. if (mt == MeshType::Quad)
  407. {
  408. // There's nothin' else than QuadDefault
  409. BL = vec2(0.f);
  410. TR = vec2(1.f);
  411. }
  412. #if 0
  413. else if (mt == MeshType::Triangle)
  414. mt = mt;
  415. #endif
  416. else if (mt == MeshType::Box)
  417. {
  418. vec2 data[][2] =
  419. { // TexCoordBuildType::BoxDefault
  420. { vec2(0.f), vec2(.5f) },
  421. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  422. { vec2(0.f), vec2(.5f) },
  423. { vec2(.5f, 0.f), vec2(1.f, .5f) },
  424. { vec2(0.f, .5f), vec2(.5f, 1.f) },
  425. { vec2(.5f, .5f), vec2(1.f, 1.f) }
  426. };
  427. BL = data[face.ToScalar()][0]; // [tcbt]
  428. TR = data[face.ToScalar()][1]; // [tcbt]
  429. }
  430. #if 0
  431. else if (mt == MeshType::Sphere)
  432. mt = mt;
  433. else if (mt == MeshType::Capsule)
  434. mt = mt;
  435. else if (mt == MeshType::Torus)
  436. mt = mt;
  437. else if (mt == MeshType::Cylinder)
  438. mt = mt;
  439. else if (mt == MeshType::Disc)
  440. mt = mt;
  441. else if (mt == MeshType::Star)
  442. mt = mt;
  443. else if (mt == MeshType::ExpandedStar)
  444. mt = mt;
  445. else if (mt == MeshType::Cog)
  446. mt = mt;
  447. #endif
  448. }
  449. vec2 res = vec2(.0f);
  450. if (tcp == TexCoordPos::BL)
  451. res = BL;
  452. else if (tcp == TexCoordPos::BR)
  453. res = vec2(TR.x, BL.y);
  454. else if (tcp == TexCoordPos::TL)
  455. res = vec2(BL.x, TR.y);
  456. else if (tcp == TexCoordPos::TR)
  457. res = TR;
  458. return res * m_texcoord_scale + m_texcoord_offset2;
  459. }
  460. inline bool IsEnabled(MeshBuildOperation mbo) { return (m_build_flags & mbo.ToScalar()) != 0; }
  461. inline void Enable(MeshBuildOperation mbo) { m_build_flags |= mbo.ToScalar(); }
  462. inline void Disable(MeshBuildOperation mbo) { m_build_flags &= ~mbo.ToScalar(); }
  463. inline void Toggle(MeshBuildOperation mbo) { m_build_flags ^= mbo.ToScalar(); }
  464. inline void Set(MeshBuildOperation mbo, bool value) { if (value) Enable(mbo); else Disable(mbo); }
  465. public:
  466. CommandStack m_stack;
  467. int m_i_cmd;
  468. int m_exec_nb;
  469. easy_array<int, int> m_loop_stack;
  470. vec4 m_color_a;
  471. vec4 m_color_b;
  472. vec2 m_texcoord_offset;
  473. vec2 m_texcoord_offset2;
  474. vec2 m_texcoord_scale;
  475. vec2 m_texcoord_scale2;
  476. easy_array<vec2, vec2> m_texcoord_custom_build[MeshType::MAX];
  477. easy_array<vec2, vec2> m_texcoord_custom_build2[MeshType::MAX];
  478. uint32_t m_texcoord_build_type[MeshType::MAX];
  479. uint32_t m_texcoord_build_type2[MeshType::MAX];
  480. uint32_t m_build_flags = MeshBuildOperation::PreventVertCleanup;
  481. };
  482. //VDictType -- A safe enum for VertexDictionnary operations. ------------------
  483. struct VDictTypeBase : public StructSafeEnum
  484. {
  485. enum Type
  486. {
  487. DoesNotExist = -3,
  488. Alone = -2,
  489. Master = -1,
  490. };
  491. protected:
  492. virtual bool BuildEnumMap(std::map<int64_t, std::string>& enum_map)
  493. {
  494. enum_map[DoesNotExist] = "DoesNotExist";
  495. enum_map[Alone] = "Alone";
  496. enum_map[Master] = "Master";
  497. return true;
  498. }
  499. };
  500. typedef SafeEnum<VDictTypeBase> VDictType;
  501. /* TODO : replace VDict by a proper Half-edge system */
  502. //a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes
  503. class VertexDictionnary
  504. {
  505. public:
  506. int FindVertexMaster(const int search_idx);
  507. bool FindMatchingVertices(const int search_idx, easy_array<int> &matching_ids);
  508. bool FindConnectedVertices(const int search_idx, const easy_array<uint16_t> &tri_list, const int tri0, easy_array<int> &connected_vert, easy_array<int> const *ignored_tri = nullptr);
  509. bool FindConnectedTriangles(const int search_idx, const easy_array<uint16_t> &tri_list, const int tri0, easy_array<int> &connected_tri, easy_array<int> const *ignored_tri = nullptr);
  510. bool FindConnectedTriangles(const ivec2 &search_idx, const easy_array<uint16_t> &tri_list, const int tri0, easy_array<int> &connected_tri, easy_array<int> const *ignored_tri = nullptr);
  511. bool FindConnectedTriangles(const ivec3 &search_idx, const easy_array<uint16_t> &tri_list, const int tri0, easy_array<int> &connected_tri, easy_array<int> const *ignored_tri = nullptr);
  512. void RegisterVertex(int vert_id, vec3 vert_coord);
  513. void RemoveVertex(int vert_id);
  514. bool GetMasterList(easy_array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.count() > 0; }
  515. void Clear() { vertex_list.clear(); }
  516. private:
  517. //<VertexId, VertexLocation, VertexMasterId>
  518. easy_array<int, vec3, int> vertex_list;
  519. //List of the master_ vertices
  520. easy_array<int> master_list;
  521. };
  522. } /* namespace lol */