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.

easymeshinternal.cpp 17 KiB

пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
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 */