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.
 
 
 

217 lines
9.2 KiB

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