Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

543 Zeilen
19 KiB

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