您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

easymeshinternal.cpp 17 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. //
  2. // EasyMesh-Internal— Internal operations
  3. //
  4. // Copyright © 2012—2020 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::AddVertex(vec3 const &coord)
  19. {
  20. m_vert.push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->ColorA()));
  21. m_state = MeshRender::NeedConvert;
  22. }
  23. //-----------------------------------------------------------------------------
  24. void EasyMesh::AddDupVertex(int i)
  25. {
  26. m_vert << m_vert[i];
  27. m_state = MeshRender::NeedConvert;
  28. }
  29. //-----------------------------------------------------------------------------
  30. void EasyMesh::AddLerpVertex(int i, int j, float alpha) { AddLerpVertex(m_vert[i], m_vert[j], alpha); }
  31. void EasyMesh::AddLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
  32. {
  33. m_vert.push(GetLerpVertex(vi, vj, alpha));
  34. m_state = MeshRender::NeedConvert;
  35. }
  36. //-----------------------------------------------------------------------------
  37. VertexData EasyMesh::GetLerpVertex(int i, int j, float alpha) { return GetLerpVertex(m_vert[i], m_vert[j], alpha); }
  38. VertexData EasyMesh::GetLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
  39. {
  40. return VertexData(
  41. lol::lerp(vi.m_coord, vj.m_coord, alpha),
  42. lol::lerp(vi.m_normal, vj.m_normal, alpha),
  43. lol::lerp(vi.m_color, vj.m_color, alpha),
  44. lol::lerp(vi.m_texcoord, vj.m_texcoord, alpha),
  45. ((alpha < .5f) ? (vi.m_bone_id) : (vj.m_bone_id)), /* FIXME ? */
  46. lol::lerp(vi.m_bone_weight, vj.m_bone_weight, alpha));
  47. }
  48. //-----------------------------------------------------------------------------
  49. void EasyMesh::AddQuad(int i1, int i2, int i3, int i4, int base, bool duplicate)
  50. {
  51. if (duplicate)
  52. {
  53. int vbase = m_vert.count();
  54. AddDupVertex(base + i1);
  55. AddDupVertex(base + i2);
  56. AddDupVertex(base + i3);
  57. AddDupVertex(base + i4);
  58. AddQuad(0, 1, 2, 3, vbase);
  59. }
  60. else
  61. {
  62. if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) &&
  63. !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting))
  64. {
  65. int i5 = m_vert.count();
  66. AddLerpVertex(GetLerpVertex(base + i1, base + i3, .5f),
  67. GetLerpVertex(base + i2, base + i4, .5f), .5f);
  68. m_indices << i1 + base;
  69. m_indices << i2 + base;
  70. m_indices << i5;
  71. m_indices << i2 + base;
  72. m_indices << i3 + base;
  73. m_indices << i5;
  74. m_indices << i4 + base;
  75. m_indices << i1 + base;
  76. m_indices << i5;
  77. m_indices << i5;
  78. m_indices << i3 + base;
  79. m_indices << i4 + base;
  80. }
  81. else
  82. {
  83. m_indices << i1 + base;
  84. m_indices << i2 + base;
  85. m_indices << i3 + base;
  86. m_indices << i4 + base;
  87. m_indices << i1 + base;
  88. m_indices << i3 + base;
  89. }
  90. }
  91. }
  92. //-----------------------------------------------------------------------------
  93. void EasyMesh::AddTriangle(int i1, int i2, int i3, int base, bool duplicate)
  94. {
  95. if (duplicate)
  96. {
  97. m_indices << (uint16_t)m_vert.count(); AddDupVertex(base + i1);
  98. m_indices << (uint16_t)m_vert.count(); AddDupVertex(base + i2);
  99. m_indices << (uint16_t)m_vert.count(); AddDupVertex(base + i3);
  100. }
  101. else
  102. {
  103. m_indices << base + i1;
  104. m_indices << base + i2;
  105. m_indices << base + i3;
  106. }
  107. }
  108. //-----------------------------------------------------------------------------
  109. void EasyMesh::ComputeNormals(int start, int vcount)
  110. {
  111. if (BD()->IsEnabled(MeshBuildOperation::CommandExecution) &&
  112. BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
  113. return;
  114. easy_array< easy_array<vec3> > normals;
  115. normals.resize(m_vert.count());
  116. for (int i = 0; i < vcount; i += 3)
  117. {
  118. vec3 v0 = m_vert[m_indices[start + i + 2]].m_coord
  119. - m_vert[m_indices[start + i + 0]].m_coord;
  120. vec3 v1 = m_vert[m_indices[start + i + 1]].m_coord
  121. - m_vert[m_indices[start + i + 0]].m_coord;
  122. vec3 n = normalize(cross(v1, v0));
  123. for (int j = 0; j < 3; j++)
  124. normals[m_indices[start + i + j]] << n;
  125. }
  126. for (int i = 0; i < normals.count(); i++)
  127. {
  128. if (normals[i].count() > 0)
  129. {
  130. //remove doubles
  131. for (int j = 0; j < normals[i].count(); ++j)
  132. for (int k = j + 1; k < normals[i].count(); ++k)
  133. if (1.f - dot(normals[i][k], normals[i][j]) < .00001f)
  134. normals[i].remove(k--);
  135. vec3 newv = vec3::zero;
  136. for (int j = 0; j < normals[i].count(); ++j)
  137. newv += normals[i][j];
  138. m_vert[i].m_normal = normalize(newv / (float)normals[i].count());
  139. }
  140. }
  141. }
  142. //-----------------------------------------------------------------------------
  143. void EasyMesh::VerticesCleanup()
  144. {
  145. easy_array<int> vert_ids;
  146. vert_ids.resize(m_vert.count(), 0);
  147. //1: Remove triangles with two vertices on each other
  148. for (int i = 0; i < m_indices.count(); i += 3)
  149. {
  150. bool remove = false;
  151. for (int j = 0; !remove && j < 3; ++j)
  152. if (length(m_vert[m_indices[i + j]].m_coord - m_vert[m_indices[i + (j + 1) % 3]].m_coord) < .00001f)
  153. remove = true;
  154. if (remove)
  155. {
  156. m_indices.remove_swap(i, 3);
  157. i -= 3;
  158. }
  159. else
  160. {
  161. //1.5: Mark all used vertices
  162. for (int j = 0; j < 3; ++j)
  163. vert_ids[m_indices[i + j]] = 1;
  164. }
  165. }
  166. //2: Remove all unused vertices
  167. easy_array<VertexData> old_vert = m_vert;
  168. int shift = 0;
  169. m_vert.clear();
  170. for (int i = 0; i < vert_ids.count(); ++i)
  171. {
  172. //Unused vertex, update the shift quantity instead of keeping it.
  173. if (vert_ids[i] == 0)
  174. shift++;
  175. else
  176. m_vert << old_vert[i];
  177. //Always mark it with the shift quantity
  178. vert_ids[i] = shift;
  179. }
  180. //3: Update the indices
  181. for (int i = 0; i < m_indices.count(); ++i)
  182. m_indices[i] -= vert_ids[m_indices[i]];
  183. }
  184. //-----------------------------------------------------------------------------
  185. void EasyMesh::VerticesMerge()
  186. {
  187. if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
  188. {
  189. BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesMerge);
  190. return;
  191. }
  192. //1: Crunch all vertices in the dictionnary
  193. VertexDictionnary vert_dict;
  194. for (int i = std::get<0>(m_cursors.last()); i < m_vert.count(); i++)
  195. vert_dict.RegisterVertex(i, m_vert[i].m_coord);
  196. //2: Update the indices
  197. for (int i = 0; i < m_indices.count(); ++i)
  198. {
  199. int master = vert_dict.FindVertexMaster(m_indices[i]);
  200. if (master >= 0)
  201. m_indices[i] = master;
  202. }
  203. //2: Cleanup
  204. VerticesCleanup();
  205. }
  206. //-----------------------------------------------------------------------------
  207. void EasyMesh::VerticesSeparate()
  208. {
  209. if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
  210. {
  211. BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesSeparate);
  212. return;
  213. }
  214. easy_array< easy_array<int> > new_ids;
  215. easy_array<int> vert_ids;
  216. vert_ids.resize(m_vert.count(), 0);
  217. //1: Mark all used vertices
  218. for (int i = 0; i < m_indices.count(); ++i)
  219. vert_ids[m_indices[i]]++;
  220. //2: Update the vertices
  221. int vbase = std::get<0>(m_cursors.last());
  222. int vcount = m_vert.count();
  223. new_ids.resize(vcount);
  224. for (int i = vbase; i < vcount; i++)
  225. {
  226. while (vert_ids[i] > 1)
  227. {
  228. //Add duplicate
  229. new_ids[i] << m_vert.count();
  230. AddDupVertex(i);
  231. vert_ids[i]--;
  232. }
  233. }
  234. //3: Update the indices
  235. for (int i = 0; i < m_indices.count(); ++i)
  236. {
  237. if (new_ids[m_indices[i]].count())
  238. {
  239. int j = new_ids[m_indices[i]].pop();
  240. m_indices[i] = j;
  241. }
  242. }
  243. //4: Cleanup
  244. VerticesCleanup();
  245. }
  246. //-----------------------------------------------------------------------------
  247. void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset)
  248. {
  249. (void)uv_scale; (void)uv_offset;
  250. #if 0
  251. VertexDictionnary vert_dict;
  252. easy_array<int> tri_list;
  253. tri_list.Reserve(m_indices.count() - std::get<1>(m_cursors.last()));
  254. for (int i = std::get<1>(m_cursors.last()); i < m_indices.count(); i++)
  255. {
  256. vert_dict.RegisterVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
  257. tri_list << m_indices[i];
  258. }
  259. //full triangle count
  260. easy_array<int> tri_done;
  261. easy_array<int> tri_check;
  262. int tri_count = (m_indices.count() - std::get<1>(m_cursors.last())) / 3;
  263. tri_check << tri_list[0];
  264. while (tri_check.count())
  265. {
  266. int cur_tri = tri_check[0];
  267. int v[3] = { tri_list[cur_tri + uv_offset % 3], tri_list[cur_tri + (1 + uv_offset) % 3], tri_list[cur_tri + (2 + uv_offset) % 3] };
  268. vec2 uv[3] = { m_vert[tri_list[cur_tri]].m_texcoord.xy, m_vert[tri_list[cur_tri + 1]].m_texcoord.xy, m_vert[tri_list[cur_tri + 2]].m_texcoord.xy };
  269. for (int j = 0; j < 3; j++)
  270. {
  271. if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3])
  272. {
  273. uv[0] = vec2(-1.0f);
  274. uv[1] = vec2(-1.0f);
  275. uv[2] = vec2(-1.0f);
  276. break;
  277. }
  278. }
  279. int uv_set = 0;
  280. for (int j = 0; j < 3; j++)
  281. uv_set += (uv[j].x < 0.f)?(0):(1);
  282. //this case shouldn't happen.
  283. if (uv_set == 1)
  284. {
  285. /*
  286. for (int j = 0; j < 3; j++)
  287. {
  288. if (uv[j] != vec2(-1.0f))
  289. {
  290. uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(std::get<0>(m_vert[v[j]]) - std::get<0>(m_vert[v[(j + 1) % 3]])));
  291. uv_set = 2;
  292. break;
  293. }
  294. }
  295. */
  296. }
  297. //No UV is set, let's do the arbitrary set and use the basic method.
  298. if (uv_set == 0)
  299. {
  300. float new_dot = FLT_MAX;
  301. int base_i = 0;
  302. for (int j = 0; j < 3; j++)
  303. {
  304. float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m_coord - m_vert[v[j]].m_coord),
  305. normalize(m_vert[v[(j + 2) % 3]].m_coord - m_vert[v[j]].m_coord)));
  306. if (tmp_dot < new_dot)
  307. {
  308. base_i = j;
  309. new_dot = tmp_dot;
  310. }
  311. }
  312. uv[base_i] = vec2(.0f);
  313. uv[(base_i + 1) % 3] = vec2(.0f, uv_scale * length(m_vert[v[base_i]].m_coord - m_vert[v[(base_i + 1) % 3]].m_coord));
  314. uv_set = 2;
  315. }
  316. //2 points have been set, let's figure the third
  317. if (uv_set == 2)
  318. {
  319. {
  320. //invert values so the two set uv are in [0, 1] slots.
  321. int new_v[3];
  322. vec2 new_uv[3];
  323. bool ignore_set = false;
  324. if (uv[0].x >= 0.f && uv[1].x < 0.f)
  325. {
  326. new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1];
  327. new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1];
  328. }
  329. else if (uv[0].x < 0.f && uv[1].x >= 0.f)
  330. {
  331. new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0];
  332. new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0];
  333. }
  334. else
  335. ignore_set = true;
  336. if (!ignore_set)
  337. {
  338. v[0] = new_v[0]; v[1] = new_v[1]; v[2] = new_v[2];
  339. uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2];
  340. }
  341. }
  342. //Do this to be sure the normal is OK.
  343. ComputeNormals(cur_tri, 3);
  344. vec3 v01 = normalize(m_vert[v[1]].m_coord - m_vert[v[0]].m_coord);
  345. vec3 v02 = m_vert[v[2]].m_coord - m_vert[v[0]].m_coord;
  346. vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m_normal, v01));
  347. vec2 texu_dir = uv[1] - uv[0];
  348. vec2 texv_dir = vec2(texu_dir.y, texu_dir.x);
  349. //Final calculations
  350. uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02);
  351. //Set UV on ALL matching vertices!
  352. easy_array<int> matching_vert;
  353. for (int i = 0; i < 3; i++)
  354. {
  355. #if 1
  356. //This marks all same position UV to the same values
  357. //Deactivation is a test.
  358. matching_vert << v[i];
  359. vert_dict.FindMatchingVertices(v[i], matching_vert);
  360. for (int j = 0; j < matching_vert.count(); j++)
  361. if (m_vert[matching_vert[j]].m_texcoord.xy == vec2(-1.0f))
  362. m_vert[matching_vert[j]].m_texcoord = vec4(abs(uv[i]), m_vert[matching_vert[j]].m_texcoord.zw);
  363. #else
  364. m_vert[v[i]].m_texcoord = abs(uv[i]);
  365. #endif
  366. }
  367. tri_done << cur_tri;
  368. tri_check.remove(0);
  369. //Get connected triangles and go from there.
  370. for (int j = 0; j < 3; j++)
  371. {
  372. #if 1
  373. //This finds triangle that are connected to this triangle
  374. vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done);
  375. #else
  376. //This finds triangle that are connected to the vertices of this triangle
  377. vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done);
  378. #endif
  379. }
  380. }
  381. else if (uv_set == 3)
  382. {
  383. for (int j = 0; j < 3; j++)
  384. {
  385. m_vert[tri_list[cur_tri]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri]].m_texcoord.zw);
  386. m_vert[tri_list[cur_tri + 1]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 1]].m_texcoord.zw);
  387. m_vert[tri_list[cur_tri + 2]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 2]].m_texcoord.zw);
  388. }
  389. //uv[0] = vec2(-1.0f);
  390. //uv[1] = vec2(-1.0f);
  391. //uv[2] = vec2(-1.0f);
  392. /*
  393. bool tri_present = false;
  394. for (int j = 0; j < tri_done.count(); j++)
  395. if (cur_tri == tri_done[j])
  396. tri_present = true;
  397. if (!tri_present)
  398. tri_done << cur_tri;
  399. tri_check.remove(0);
  400. */
  401. }
  402. if (tri_check.count() == 0 && tri_done.count() != tri_count)
  403. {
  404. //look for unset triangle
  405. for (int i = 0; !tri_check.count() && i < tri_list.count(); i += 3)
  406. {
  407. bool tri_present = false;
  408. for (int j = 0; j < tri_done.count(); j++)
  409. if (i == tri_done[j])
  410. tri_present = true;
  411. if (!tri_present)
  412. tri_check << i;
  413. }
  414. }
  415. }
  416. #endif
  417. }
  418. //-----------------------------------------------------------------------------
  419. void EasyMesh::SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale)
  420. {
  421. BD()->TexCoordOffset() = new_offset;
  422. BD()->TexCoordScale() = new_scale;
  423. }
  424. //-----------------------------------------------------------------------------
  425. void EasyMesh::SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale)
  426. {
  427. BD()->TexCoordOffset2() = new_offset;
  428. BD()->TexCoordScale2() = new_scale;
  429. }
  430. //-----------------------------------------------------------------------------
  431. void EasyMesh::SetCurVertNormal(vec3 const &normal)
  432. {
  433. m_vert.last().m_normal = normal;
  434. }
  435. //-----------------------------------------------------------------------------
  436. void EasyMesh::SetCurVertColor(vec4 const &col)
  437. {
  438. m_vert.last().m_color = col;
  439. }
  440. //-----------------------------------------------------------------------------
  441. void EasyMesh::SetCurVertTexCoord(vec2 const &texcoord)
  442. {
  443. m_vert.last().m_texcoord = vec4(texcoord, m_vert.last().m_texcoord.zw);
  444. }
  445. //-----------------------------------------------------------------------------
  446. void EasyMesh::SetCurVertTexCoord2(vec2 const &texcoord)
  447. {
  448. m_vert.last().m_texcoord = vec4(m_vert.last().m_texcoord.xy, texcoord);
  449. }
  450. } /* namespace lol */