Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

501 рядки
16 KiB

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