Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

220 righe
9.4 KiB

  1. //
  2. // EasyMesh-Csg: The code belonging to CSG operations
  3. //
  4. // Copyright © 2010—2019 Sam Hocevar <sam@hocevar.net>
  5. // © 2009—2015 Cédric Lecacheur <jordx@free.fr>
  6. // © 2009—2015 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. #include <lol/engine-internal.h>
  15. namespace lol
  16. {
  17. //-----------------------------------------------------------------------------
  18. void EasyMesh::CsgUnion() { MeshCsg(CSGUsage::Union); }
  19. void EasyMesh::CsgSub() { MeshCsg(CSGUsage::Substract); }
  20. void EasyMesh::CsgSubL() { MeshCsg(CSGUsage::SubstractLoss); }
  21. void EasyMesh::CsgAnd() { MeshCsg(CSGUsage::And); }
  22. void EasyMesh::CsgXor() { MeshCsg(CSGUsage::Xor); }
  23. //-----------------------------------------------------------------------------
  24. void EasyMesh::MeshCsg(CSGUsage csg_operation)
  25. {
  26. if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
  27. {
  28. BD()->CmdStack().AddCmd(EasyMeshCmdType::MeshCsg);
  29. BD()->CmdStack() << csg_operation;
  30. return;
  31. }
  32. //A vertex dictionnary for vertices on the same spot.
  33. array< int, int > vertex_dict;
  34. //This list keeps track of the triangle that will need deletion at the end.
  35. array< int > triangle_to_kill;
  36. //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>>
  37. array< int, array< vec3, vec3, vec3 > > triangle_isec;
  38. //keep a track of the intersection point on the triangle. <pos, side_id>
  39. array< vec3, int > triangle_vertex;
  40. for (int k = 0; k < 10; k++)
  41. triangle_vertex.push(vec3(.0f), 0);
  42. //bsp infos
  43. CsgBsp mesh_bsp_0;
  44. CsgBsp mesh_bsp_1;
  45. if (m_cursors.count() == 0)
  46. return;
  47. //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]"
  48. int cursor_start = (m_cursors.count() < 2)?(0):(m_cursors[(m_cursors.count() - 2)].m2);
  49. for (int mesh_id = 0; mesh_id < 2; mesh_id++)
  50. {
  51. int start_point = (mesh_id == 0) ? (cursor_start) : (m_cursors.last().m2);
  52. int end_point = (mesh_id == 0) ? (m_cursors.last().m2) : (m_indices.count());
  53. CsgBsp &mesh_bsp = (mesh_id == 0) ? (mesh_bsp_0) : (mesh_bsp_1);
  54. for (int i = start_point; i < end_point; i += 3)
  55. mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord,
  56. m_vert[m_indices[i + 1]].m_coord,
  57. m_vert[m_indices[i + 2]].m_coord);
  58. }
  59. //BSP Usage : let's crunch all triangles on the correct BSP
  60. int indices_count = m_indices.count();
  61. for (int mesh_id = 0; mesh_id < 2; mesh_id++)
  62. {
  63. int start_point = (mesh_id == 0) ? (cursor_start) : (m_cursors.last().m2);
  64. int end_point = (mesh_id == 0) ? (m_cursors.last().m2) : (indices_count);
  65. CsgBsp &mesh_bsp = (mesh_id == 0) ? (mesh_bsp_1) : (mesh_bsp_0);
  66. array< vec3, int, int, float > vert_list;
  67. array< int, int, int, int > tri_list;
  68. vec3 n0(.0f); vec3 n1(.0f);
  69. vec4 c0(.0f); vec4 c1(.0f);
  70. //Reserve some memory
  71. vert_list.reserve(3);
  72. tri_list.reserve(3);
  73. for (int i = start_point; i < end_point; i += 3)
  74. {
  75. int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord,
  76. m_vert[m_indices[i + 1]].m_coord,
  77. m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list);
  78. int tri_base_idx = m_indices.count();
  79. //one split has been done, we need to had the new vertices & the new triangles.
  80. if (Result == 1)
  81. {
  82. triangle_to_kill.push(i);
  83. #if 1
  84. int base_idx = m_vert.count();
  85. for (int k = 3; k < vert_list.count(); k++)
  86. {
  87. int P0 = (vert_list[k].m2 < 3) ? (m_indices[i + vert_list[k].m2]) : (base_idx + vert_list[k].m2 - 3);
  88. int P1 = (vert_list[k].m3 < 3) ? (m_indices[i + vert_list[k].m3]) : (base_idx + vert_list[k].m3 - 3);
  89. AddVertex(vert_list[k].m1);
  90. //Normal : bad calculations there.
  91. n0 = m_vert[P0].m_normal;
  92. n1 = m_vert[P1].m_normal;
  93. SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4));
  94. #if 1
  95. //Color
  96. c0 = m_vert[P0].m_color;
  97. c1 = m_vert[P1].m_color;
  98. vec4 res = c0 + ((c1 - c0) * vert_list[k].m4);
  99. SetCurVertColor(res);
  100. #else
  101. if (mesh_id == 0)
  102. SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f));
  103. else
  104. SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f));
  105. #endif
  106. }
  107. for (int k = 0; k < tri_list.count(); k++)
  108. {
  109. int P0 = (tri_list[k].m2 < 3) ? (m_indices[i + tri_list[k].m2]) : (base_idx + (tri_list[k].m2 - 3));
  110. int P1 = (tri_list[k].m3 < 3) ? (m_indices[i + tri_list[k].m3]) : (base_idx + (tri_list[k].m3 - 3));
  111. int P2 = (tri_list[k].m4 < 3) ? (m_indices[i + tri_list[k].m4]) : (base_idx + (tri_list[k].m4 - 3));
  112. AddTriangle(P0, P1, P2, 0);
  113. }
  114. #endif
  115. }
  116. #if 1
  117. //Main case
  118. if (Result >= 0)
  119. {
  120. for (int k = 0; k < tri_list.count(); k++)
  121. {
  122. int tri_idx = (tri_list.count() == 1) ? (i) : (tri_base_idx + k * 3);
  123. //Triangle Kill Test
  124. if (//csgu : CSGUnion() -> m0_Outside + m1_Outside
  125. (csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) ||
  126. //csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
  127. (csg_operation == CSGUsage::Substract &&
  128. ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) ||
  129. (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) ||
  130. //csgs : CsgSubL() -> m0_Outside
  131. (csg_operation == CSGUsage::SubstractLoss &&
  132. ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) ||
  133. //csga : CSGAnd() -> m0_Inside + m1_Inside
  134. (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT))
  135. {
  136. triangle_to_kill.push(tri_idx);
  137. }
  138. //Triangle Invert Test
  139. if (//csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
  140. (csg_operation == CSGUsage::Substract && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) ||
  141. //csgx : CSGXor() -> m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted
  142. (csg_operation == CSGUsage::Xor && tri_list[k].m1 == LEAF_BACK))
  143. {
  144. //a Xor means we will share vertices with the outside, so duplicate the vertices.
  145. //TODO : This operation disconnect all triangle, in some cases, not a good thing.
  146. if (csg_operation == CSGUsage::Xor)
  147. {
  148. for (int l = 0; l < 3; l++)
  149. {
  150. AddDupVertex(m_indices[tri_idx + l]);
  151. m_indices[tri_idx + l] = (uint16_t)m_vert.count() - 1;
  152. }
  153. }
  154. m_indices[tri_idx + 1] += m_indices[tri_idx + 2];
  155. m_indices[tri_idx + 2] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
  156. m_indices[tri_idx + 1] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
  157. ComputeNormals(tri_idx, 3);
  158. }
  159. }
  160. }
  161. #endif
  162. vert_list.clear();
  163. tri_list.clear();
  164. }
  165. }
  166. // FIXME: what was this code for?
  167. // for (int i = 0; i < m_vert.count(); i++)
  168. // if (length(m_vert[i].m_normal) < 1.0f)
  169. // i = i;
  170. int dir = 1;
  171. for (int i = 0; i >= 0 && i < triangle_to_kill.count() - 1; i += dir)
  172. {
  173. if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0)
  174. dir = 1;
  175. if (triangle_to_kill[i] == triangle_to_kill[i + 1])
  176. {
  177. triangle_to_kill.remove(i);
  178. dir = -1;
  179. }
  180. if (triangle_to_kill[i] > triangle_to_kill[i + 1])
  181. {
  182. triangle_to_kill[i] += triangle_to_kill[i + 1];
  183. triangle_to_kill[i + 1] = triangle_to_kill[i] - triangle_to_kill[i + 1];
  184. triangle_to_kill[i] = triangle_to_kill[i] - triangle_to_kill[i + 1];
  185. dir = -1;
  186. }
  187. if (i == 0 && dir == -1)
  188. dir = 1;
  189. }
  190. for (int i = triangle_to_kill.count() - 1; i >= 0; i--)
  191. m_indices.remove(triangle_to_kill[i], 3);
  192. m_cursors.last().m1 = m_vert.count();
  193. m_cursors.last().m2 = m_indices.count();
  194. VerticesCleanup();
  195. //DONE for the splitting !
  196. }
  197. } /* namespace lol */