2352 lines
86 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2013 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. //
  13. // The EasyMesh class
  14. // ------------------
  15. //
  16. #if defined HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #if defined _XBOX
  20. # define _USE_MATH_DEFINES /* for M_PI */
  21. # include <xtl.h>
  22. # undef near /* Fuck Microsoft */
  23. # undef far /* Fuck Microsoft again */
  24. #elif defined _WIN32
  25. # define _USE_MATH_DEFINES /* for M_PI */
  26. # define WIN32_LEAN_AND_MEAN
  27. # include <windows.h>
  28. # undef near /* Fuck Microsoft */
  29. # undef far /* Fuck Microsoft again */
  30. #endif
  31. #include "core.h"
  32. #include "easymesh/easymesh-compiler.h"
  33. LOLFX_RESOURCE_DECLARE(shiny);
  34. LOLFX_RESOURCE_DECLARE(shinydebugwireframe);
  35. LOLFX_RESOURCE_DECLARE(shinydebuglighting);
  36. LOLFX_RESOURCE_DECLARE(shinydebugnormal);
  37. LOLFX_RESOURCE_DECLARE(shinydebugUV);
  38. LOLFX_RESOURCE_DECLARE(shiny_SK);
  39. namespace lol
  40. {
  41. //-----------------------------------------------------------------------------
  42. GpuShaderData::GpuShaderData()
  43. {
  44. m_render_mode = DebugRenderMode::Default;
  45. }
  46. //-----------------------------------------------------------------------------
  47. GpuShaderData::GpuShaderData(uint16_t vert_decl_flags, Shader* shader, DebugRenderMode render_mode)
  48. {
  49. m_render_mode = render_mode;
  50. m_shader = shader;
  51. m_vert_decl_flags = vert_decl_flags;
  52. }
  53. //-----------------------------------------------------------------------------
  54. GpuShaderData::~GpuShaderData()
  55. {
  56. m_shader_uniform.Empty();
  57. m_shader_attrib.Empty();
  58. }
  59. //-----------------------------------------------------------------------------
  60. void GpuShaderData::AddUniform(const lol::String &new_uniform)
  61. {
  62. m_shader_uniform.Push(new_uniform, m_shader->GetUniformLocation(new_uniform.C()));
  63. }
  64. //-----------------------------------------------------------------------------
  65. void GpuShaderData::AddAttribute(const lol::String &new_attribute, VertexUsage usage, int index)
  66. {
  67. m_shader_attrib.Push(new_attribute, m_shader->GetAttribLocation(new_attribute.C(), usage, index));
  68. }
  69. //-----------------------------------------------------------------------------
  70. ShaderUniform const *GpuShaderData::GetUniform(const lol::String &uniform)
  71. {
  72. for (int i = 0; i < m_shader_uniform.Count(); ++i)
  73. if (m_shader_uniform[i].m1 == uniform)
  74. return &m_shader_uniform[i].m2;
  75. return NULL;
  76. }
  77. //-----------------------------------------------------------------------------
  78. ShaderAttrib const *GpuShaderData::GetAttribute(const lol::String &attribute)
  79. {
  80. for (int i = 0; i < m_shader_attrib.Count(); ++i)
  81. if (m_shader_attrib[i].m1 == attribute)
  82. return &m_shader_attrib[i].m2;
  83. return NULL;
  84. }
  85. //-----------------------------------------------------------------------------
  86. DefaultShaderData::DefaultShaderData(DebugRenderMode render_mode)
  87. {
  88. bool with_UV = false;
  89. m_render_mode = render_mode;
  90. m_vert_decl_flags = (1 << VertexUsage::Position) |
  91. (1 << VertexUsage::Normal) |
  92. (1 << VertexUsage::Color);
  93. if (render_mode == DebugRenderMode::Default)
  94. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shiny));
  95. else if (render_mode == DebugRenderMode::Wireframe)
  96. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugwireframe));
  97. else if (render_mode == DebugRenderMode::Lighting)
  98. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebuglighting));
  99. else if (render_mode == DebugRenderMode::Normal)
  100. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugnormal));
  101. else if (render_mode == DebugRenderMode::UV)
  102. {
  103. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugUV));
  104. m_vert_decl_flags |= (1 << VertexUsage::TexCoord);
  105. with_UV = true;
  106. }
  107. SetupDefaultData(with_UV);
  108. }
  109. //-----------------------------------------------------------------------------
  110. DefaultShaderData::DefaultShaderData(uint16_t vert_decl_flags, Shader* shader, bool with_UV)
  111. : GpuShaderData(vert_decl_flags, shader, DebugRenderMode::Default)
  112. {
  113. SetupDefaultData(with_UV);
  114. }
  115. //-----------------------------------------------------------------------------
  116. void DefaultShaderData::SetupDefaultData(bool with_UV)
  117. {
  118. AddUniform("in_ModelView");
  119. AddUniform("in_Inv_ModelView");
  120. AddUniform("in_View");
  121. AddUniform("in_Inv_View");
  122. AddUniform("in_Proj");
  123. AddUniform("in_NormalMat");
  124. AddUniform("in_Damage");
  125. AddUniform("u_Lights");
  126. AddAttribute("in_Vertex", VertexUsage::Position, 0);
  127. AddAttribute("in_Normal", VertexUsage::Normal, 0);
  128. AddAttribute("in_Color", VertexUsage::Color, 0);
  129. if (with_UV)
  130. AddAttribute("in_TexCoord", VertexUsage::TexCoord, 0);
  131. }
  132. //-----------------------------------------------------------------------------
  133. void DefaultShaderData::SetupShaderDatas(mat4 const &model)
  134. {
  135. mat4 modelview = Scene::GetDefault()->GetViewMatrix() * model;
  136. mat3 normalmat = transpose(inverse(mat3(modelview)));
  137. /* FIXME: this should be hidden in the shader */
  138. /* FIXME: the 4th component of the position can be used for other things */
  139. /* FIXME: GetUniform("blabla") is costly */
  140. Array<Light *> const lights = Scene::GetDefault()->GetLights();
  141. Array<vec4> light_data;
  142. for (int i = 0; i < lights.Count(); ++i)
  143. light_data << lights[i]->GetPosition() << lights[i]->GetColor();
  144. while (light_data.Count() < 8)
  145. light_data << vec4(0.f) << vec4(0.f);
  146. m_shader->SetUniform(*GetUniform("u_Lights"), light_data);
  147. m_shader->SetUniform(*GetUniform("in_ModelView"), modelview);
  148. m_shader->SetUniform(*GetUniform("in_Inv_ModelView"), inverse(modelview));
  149. m_shader->SetUniform(*GetUniform("in_View"), Scene::GetDefault()->GetViewMatrix());
  150. m_shader->SetUniform(*GetUniform("in_Inv_View"), inverse(Scene::GetDefault()->GetViewMatrix()));
  151. m_shader->SetUniform(*GetUniform("in_Proj"), Scene::GetDefault()->GetProjMatrix());
  152. m_shader->SetUniform(*GetUniform("in_NormalMat"), normalmat);
  153. m_shader->SetUniform(*GetUniform("in_Damage"), 0);
  154. }
  155. //-----------------------------------------------------------------------------
  156. GpuEasyMeshData::GpuEasyMeshData()
  157. {
  158. m_vertexcount = 0;
  159. m_indexcount = 0;
  160. m_ibo = NULL;
  161. }
  162. //-----------------------------------------------------------------------------
  163. GpuEasyMeshData::~GpuEasyMeshData()
  164. {
  165. m_gpudatas.Empty();
  166. m_vdatas.Empty();
  167. if (m_ibo)
  168. delete(m_ibo);
  169. }
  170. //-----------------------------------------------------------------------------
  171. void GpuEasyMeshData::AddGpuData(GpuShaderData* gpudata, EasyMesh* src_mesh)
  172. {
  173. SetupVertexData(gpudata->m_vert_decl_flags, src_mesh);
  174. if (!m_ibo)
  175. {
  176. Array<uint16_t> indexlist;
  177. for (int i = 0; i < src_mesh->m_indices.Count(); i += 3)
  178. {
  179. indexlist << src_mesh->m_indices[i + 0];
  180. indexlist << src_mesh->m_indices[i + 1];
  181. indexlist << src_mesh->m_indices[i + 2];
  182. }
  183. m_ibo = new IndexBuffer(indexlist.Bytes());
  184. void *indices = m_ibo->Lock(0, 0);
  185. memcpy(indices, &indexlist[0], indexlist.Bytes());
  186. m_ibo->Unlock();
  187. m_indexcount = indexlist.Count();
  188. }
  189. if (m_gpudatas.Count() != DebugRenderMode::Max)
  190. {
  191. m_gpudatas.Reserve(DebugRenderMode::Max);
  192. for (int i = 0; i < DebugRenderMode::Max; i++)
  193. m_gpudatas << NULL;
  194. }
  195. m_gpudatas[gpudata->m_render_mode] = gpudata;
  196. }
  197. //-----------------------------------------------------------------------------
  198. void GpuEasyMeshData::SetupVertexData(uint16_t vdecl_flags, EasyMesh* src_mesh)
  199. {
  200. for (int i = 0; i < m_vdatas.Count(); ++i)
  201. if (m_vdatas[i].m1 == vdecl_flags)
  202. return;
  203. VertexDeclaration* new_vdecl = NULL;
  204. VertexBuffer* new_vbo = NULL;
  205. void *vbo_data = NULL;
  206. int vbo_bytes = 0;
  207. #define COPY_VBO \
  208. new_vbo = new VertexBuffer(vbo_bytes); \
  209. void *mesh = new_vbo->Lock(0, 0); \
  210. memcpy(mesh, vbo_data, vbo_bytes); \
  211. new_vbo->Unlock();
  212. uint16_t baseflag = (1 << VertexUsage::Position) | (1 << VertexUsage::Normal) | (1 << VertexUsage::Color);
  213. if (vdecl_flags == (baseflag | (1 << VertexUsage::TexCoordExt)) ||
  214. vdecl_flags == (baseflag | (1 << VertexUsage::TexCoord) |
  215. (1 << VertexUsage::TexCoordExt)))
  216. {
  217. new_vdecl = new VertexDeclaration(
  218. VertexStream<vec3,vec3,u8vec4,vec4>(
  219. VertexUsage::Position,
  220. VertexUsage::Normal,
  221. VertexUsage::Color,
  222. VertexUsage::TexCoord));
  223. Array<vec3, vec3, u8vec4, vec4> vertexlist;
  224. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  225. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  226. src_mesh->m_vert[i].m_normal,
  227. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f),
  228. src_mesh->m_vert[i].m_texcoord);
  229. vbo_data = &vertexlist[0];
  230. vbo_bytes = vertexlist.Bytes();
  231. m_vertexcount = vertexlist.Count();
  232. COPY_VBO;
  233. }
  234. else if (vdecl_flags == (baseflag | (1 << VertexUsage::TexCoord)))
  235. {
  236. new_vdecl = new VertexDeclaration(
  237. VertexStream<vec3,vec3,u8vec4,vec2>(
  238. VertexUsage::Position,
  239. VertexUsage::Normal,
  240. VertexUsage::Color,
  241. VertexUsage::TexCoord));
  242. Array<vec3, vec3, u8vec4, vec2> vertexlist;
  243. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  244. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  245. src_mesh->m_vert[i].m_normal,
  246. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f),
  247. src_mesh->m_vert[i].m_texcoord.xy);
  248. vbo_data = &vertexlist[0];
  249. vbo_bytes = vertexlist.Bytes();
  250. m_vertexcount = vertexlist.Count();
  251. COPY_VBO;
  252. }
  253. else if (vdecl_flags == baseflag)
  254. {
  255. new_vdecl = new VertexDeclaration(
  256. VertexStream<vec3,vec3,u8vec4>(
  257. VertexUsage::Position,
  258. VertexUsage::Normal,
  259. VertexUsage::Color));
  260. Array<vec3,vec3,u8vec4> vertexlist;
  261. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  262. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  263. src_mesh->m_vert[i].m_normal,
  264. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f));
  265. vbo_data = &vertexlist[0];
  266. vbo_bytes = vertexlist.Bytes();
  267. m_vertexcount = vertexlist.Count();
  268. COPY_VBO;
  269. }
  270. m_vdatas.Push(vdecl_flags, new_vdecl, new_vbo);
  271. }
  272. //-----------------------------------------------------------------------------
  273. void GpuEasyMeshData::RenderMeshData(mat4 const &model)
  274. {
  275. DebugRenderMode d = Video::GetDebugRenderMode();
  276. GpuShaderData& gpu_sd = *(m_gpudatas[d]);
  277. int vdecl_idx = 0;
  278. for (; vdecl_idx < m_vdatas.Count(); ++vdecl_idx)
  279. if (m_vdatas[vdecl_idx].m1 == gpu_sd.m_vert_decl_flags)
  280. break;
  281. if (vdecl_idx >= m_vdatas.Count())
  282. return;
  283. uint16_t vflags = m_vdatas[vdecl_idx].m1;
  284. VertexDeclaration* vdecl = m_vdatas[vdecl_idx].m2;
  285. VertexBuffer* vbo = m_vdatas[vdecl_idx].m3;
  286. gpu_sd.m_shader->Bind();
  287. gpu_sd.SetupShaderDatas(model);
  288. vdecl->Bind();
  289. uint16_t baseflag = (1 << VertexUsage::Position) | (1 << VertexUsage::Normal) | (1 << VertexUsage::Color);
  290. if (vflags == (baseflag | (1 << VertexUsage::TexCoord)) ||
  291. vflags == (baseflag | (1 << VertexUsage::TexCoordExt)) ||
  292. vflags == (baseflag | (1 << VertexUsage::TexCoord) |
  293. (1 << VertexUsage::TexCoordExt)))
  294. {
  295. vdecl->SetStream(vbo, *gpu_sd.GetAttribute(lol::String("in_Vertex")),
  296. *gpu_sd.GetAttribute(lol::String("in_Normal")),
  297. *gpu_sd.GetAttribute(lol::String("in_Color")),
  298. *gpu_sd.GetAttribute(lol::String("in_TexCoord")));
  299. }
  300. else if (vflags == baseflag)
  301. {
  302. vdecl->SetStream(vbo, *gpu_sd.GetAttribute(lol::String("in_Vertex")),
  303. *gpu_sd.GetAttribute(lol::String("in_Normal")),
  304. *gpu_sd.GetAttribute(lol::String("in_Color")));
  305. }
  306. m_ibo->Bind();
  307. vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0, m_vertexcount, 0, m_indexcount);
  308. m_ibo->Unbind();
  309. vdecl->Unbind();
  310. }
  311. //-----------------------------------------------------------------------------
  312. EasyMesh::EasyMesh()
  313. : m_build_data(NULL)
  314. {
  315. m_cursors.Push(0, 0);
  316. }
  317. //-----------------------------------------------------------------------------
  318. bool EasyMesh::Compile(char const *command)
  319. {
  320. EasyMeshCompiler mc(*this);
  321. bool res = mc.ParseString(command);
  322. delete(m_build_data);
  323. return res;
  324. }
  325. //-----------------------------------------------------------------------------
  326. void EasyMesh::OpenBrace()
  327. {
  328. m_cursors.Push(m_vert.Count(), m_indices.Count());
  329. }
  330. //-----------------------------------------------------------------------------
  331. void EasyMesh::CloseBrace()
  332. {
  333. m_cursors.Pop();
  334. }
  335. //-----------------------------------------------------------------------------
  336. void EasyMesh::MeshConvert(GpuShaderData* new_gpu_sdata)
  337. {
  338. if (new_gpu_sdata)
  339. {
  340. m_gpu_data.AddGpuData(new_gpu_sdata, this);
  341. for (int i = DebugRenderMode::Default + 1; i < DebugRenderMode::Max; i++)
  342. m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode(i)), this);
  343. }
  344. }
  345. //-----------------------------------------------------------------------------
  346. void EasyMesh::MeshConvert(Shader* provided_shader)
  347. {
  348. if (provided_shader)
  349. {
  350. GpuShaderData *new_gpu_sdata = new DefaultShaderData(((1 << VertexUsage::Position) |
  351. (1 << VertexUsage::Normal) |
  352. (1 << VertexUsage::Color)),
  353. provided_shader,
  354. false);
  355. m_gpu_data.AddGpuData(new_gpu_sdata, this);
  356. }
  357. else
  358. m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode::Default), this);
  359. for (int i = DebugRenderMode::Default + 1; i < DebugRenderMode::Max; i++)
  360. m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode(i)), this);
  361. }
  362. //-----------------------------------------------------------------------------
  363. void EasyMesh::Render(mat4 const &model, float damage)
  364. {
  365. m_gpu_data.RenderMeshData(model);
  366. }
  367. //-------------------
  368. // "Collisions" functions
  369. //-------------------
  370. #define VX_ALONE -2
  371. #define VX_MASTER -1
  372. //-----------------------------------------------------------------------------
  373. //helpers func to retrieve a vertex.
  374. int VertexDictionnary::FindVertexMaster(const int search_idx)
  375. {
  376. //Resolve current vertex idx in the dictionnary (if exist)
  377. for (int j = 0; j < vertex_list.Count(); j++)
  378. if (vertex_list[j].m1 == search_idx)
  379. return vertex_list[j].m3;
  380. return VDictType::DoesNotExist;
  381. }
  382. //-----------------------------------------------------------------------------
  383. //retrieve a list of matching vertices, doesn't include search_idx.
  384. bool VertexDictionnary::FindMatchingVertices(const int search_idx, Array<int> &matching_ids)
  385. {
  386. int cur_mast = FindVertexMaster(search_idx);
  387. if (cur_mast == VDictType::DoesNotExist || cur_mast == VDictType::Alone)
  388. return false;
  389. if (cur_mast == VDictType::Master)
  390. cur_mast = search_idx;
  391. else
  392. matching_ids << vertex_list[cur_mast].m1;
  393. for (int j = 0; j < vertex_list.Count(); j++)
  394. if (vertex_list[j].m3 == cur_mast && vertex_list[j].m1 != search_idx)
  395. matching_ids << vertex_list[j].m1;
  396. return (matching_ids.Count() > 0);
  397. }
  398. //-----------------------------------------------------------------------------
  399. //Will return connected vertices (through triangles), if returned vertex has matching ones, it only returns the master.
  400. bool VertexDictionnary::FindConnectedVertices(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_vert, Array<int> const *ignored_tri)
  401. {
  402. Array<int> connected_tri;
  403. FindConnectedTriangles(search_idx, tri_list, tri0, connected_tri, ignored_tri);
  404. for (int i = 0; i < connected_tri.Count(); i++)
  405. {
  406. for (int j = 0; j < 3; j++)
  407. {
  408. int v_indice = tri_list[connected_tri[i] + j];
  409. if (v_indice != search_idx)
  410. {
  411. int found_master = FindVertexMaster(tri_list[connected_tri[i] + j]);
  412. if (found_master == VDictType::Alone || found_master == VDictType::Master)
  413. found_master = v_indice;
  414. if (found_master != search_idx)
  415. {
  416. bool already_exist = false;
  417. for (int k = 0; !already_exist && k < connected_vert.Count(); k++)
  418. if (connected_vert[k] == found_master)
  419. already_exist = true;
  420. if (!already_exist)
  421. connected_vert << found_master;
  422. }
  423. }
  424. }
  425. }
  426. return (connected_vert.Count() > 0);
  427. }
  428. //-----------------------------------------------------------------------------
  429. bool VertexDictionnary::FindConnectedTriangles(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri)
  430. {
  431. return FindConnectedTriangles(ivec3(search_idx, search_idx, search_idx), tri_list, tri0, connected_tri, ignored_tri);
  432. }
  433. //-----------------------------------------------------------------------------
  434. bool VertexDictionnary::FindConnectedTriangles(const ivec2 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri)
  435. {
  436. return FindConnectedTriangles(ivec3(search_idx, search_idx.x), tri_list, tri0, connected_tri, ignored_tri);
  437. }
  438. //-----------------------------------------------------------------------------
  439. bool VertexDictionnary::FindConnectedTriangles(const ivec3 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri)
  440. {
  441. int needed_validation = 0;
  442. Array<int> vert_list[3];
  443. for (int i = 0; i < 3; i++)
  444. {
  445. //Small optim since above func will use this one
  446. if ((i == 1 && search_idx[0] == search_idx[1]) ||
  447. (i == 2 && (search_idx[0] == search_idx[2] || search_idx[1] == search_idx[2])))
  448. continue;
  449. else
  450. {
  451. //increment the validation info, hence empty list aren't taken into account.
  452. needed_validation++;
  453. vert_list[i] << search_idx[i];
  454. FindMatchingVertices(search_idx[i], vert_list[i]);
  455. }
  456. }
  457. for (int i = tri0; i < tri_list.Count(); i += 3)
  458. {
  459. if (ignored_tri)
  460. {
  461. bool should_pass = false;
  462. for (int j = 0; !should_pass && j < ignored_tri->Count(); j++)
  463. if ((*ignored_tri)[j] == i)
  464. should_pass = true;
  465. if (should_pass)
  466. continue;
  467. }
  468. int found_validation = 0;
  469. for (int j = 0; j < 3; j++)
  470. {
  471. bool validated = false;
  472. for (int k = 0; !validated && k < vert_list[j].Count(); k++)
  473. for (int l = 0; !validated && l < 3; l++)
  474. if (vert_list[j][k] == tri_list[i + l])
  475. validated = true;
  476. found_validation += (validated)?(1):(0);
  477. }
  478. //triangle is validated store it
  479. if (found_validation == needed_validation)
  480. connected_tri << i;
  481. }
  482. return (connected_tri.Count() > 0);
  483. }
  484. //-----------------------------------------------------------------------------
  485. //Will update the given list with all the vertices on the same spot.
  486. void VertexDictionnary::AddVertex(const int vert_id, const vec3 vert_coord)
  487. {
  488. for (int j = 0; j < vertex_list.Count(); j++)
  489. if (vertex_list[j].m1 == vert_id)
  490. return;
  491. //First, build the vertex Dictionnary
  492. int i = 0;
  493. for (; i < master_list.Count(); i++)
  494. {
  495. int cur_mast = master_list[i];
  496. int cur_id = vertex_list[cur_mast].m1;
  497. vec3 cur_loc = vertex_list[cur_mast].m2;
  498. int &cur_type = vertex_list[cur_mast].m3;
  499. if (cur_id == vert_id)
  500. return;
  501. if (sqlength(cur_loc - vert_coord) < CSG_EPSILON)
  502. {
  503. if (cur_type == VDictType::Alone)
  504. cur_type = VDictType::Master;
  505. vertex_list.Push(vert_id, vert_coord, cur_mast);
  506. return;
  507. }
  508. }
  509. //We're here because we couldn't find any matching vertex
  510. master_list.Push(vertex_list.Count());
  511. vertex_list.Push(vert_id, vert_coord, VDictType::Alone);
  512. }
  513. //-----------------------------------------------------------------------------
  514. void EasyMesh::MeshCsg(CSGUsage csg_operation)
  515. {
  516. //A vertex dictionnary for vertices on the same spot.
  517. Array< int, int > vertex_dict;
  518. //This list keeps track of the triangle that will need deletion at the end.
  519. Array< int > triangle_to_kill;
  520. //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>>
  521. Array< int, Array< vec3, vec3, vec3 > > triangle_isec;
  522. //keep a track of the intersection point on the triangle. <pos, side_id>
  523. Array< vec3, int > triangle_vertex;
  524. for (int k = 0; k < 10; k++)
  525. triangle_vertex.Push(vec3(.0f), 0);
  526. //bsp infos
  527. CsgBsp mesh_bsp_0;
  528. CsgBsp mesh_bsp_1;
  529. if (m_cursors.Count() == 0)
  530. return;
  531. //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]"
  532. int cursor_start = (m_cursors.Count() < 2)?(0):(m_cursors[(m_cursors.Count() - 2)].m2);
  533. for (int mesh_id = 0; mesh_id < 2; mesh_id++)
  534. {
  535. int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
  536. int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count());
  537. CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1);
  538. for (int i = start_point; i < end_point; i += 3)
  539. mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord,
  540. m_vert[m_indices[i + 1]].m_coord,
  541. m_vert[m_indices[i + 2]].m_coord);
  542. }
  543. //BSP Useage : let's crunch all triangles on the correct BSP
  544. int indices_count = m_indices.Count();
  545. for (int mesh_id = 0; mesh_id < 2; mesh_id++)
  546. {
  547. int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
  548. int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count);
  549. CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0);
  550. Array< vec3, int, int, float > vert_list;
  551. Array< int, int, int, int > tri_list;
  552. vec3 n0(.0f); vec3 n1(.0f);
  553. vec4 c0(.0f); vec4 c1(.0f);
  554. //Reserve some memory
  555. vert_list.Reserve(3);
  556. tri_list.Reserve(3);
  557. for (int i = start_point; i < end_point; i += 3)
  558. {
  559. int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord,
  560. m_vert[m_indices[i + 1]].m_coord,
  561. m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list);
  562. int tri_base_idx = m_indices.Count();
  563. //one split has been done, we need to had the new vertices & the new triangles.
  564. if (Result == 1)
  565. {
  566. triangle_to_kill.Push(i);
  567. #if 1
  568. int base_idx = m_vert.Count();
  569. for (int k = 3; k < vert_list.Count(); k++)
  570. {
  571. int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3);
  572. int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3);
  573. AddVertex(vert_list[k].m1);
  574. //Normal : bad calculations there.
  575. n0 = m_vert[P0].m_normal;
  576. n1 = m_vert[P1].m_normal;
  577. SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4));
  578. #if 1
  579. //Color
  580. c0 = m_vert[P0].m_color;
  581. c1 = m_vert[P1].m_color;
  582. vec4 res = c0 + ((c1 - c0) * vert_list[k].m4);
  583. SetCurVertColor(res);
  584. #else
  585. if (mesh_id == 0)
  586. SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f));
  587. else
  588. SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f));
  589. #endif
  590. }
  591. for (int k = 0; k < tri_list.Count(); k++)
  592. {
  593. int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3));
  594. int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3));
  595. int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3));
  596. AppendTriangle(P0, P1, P2, 0);
  597. }
  598. #endif
  599. }
  600. #if 1
  601. //Main case
  602. if (Result >= 0)
  603. {
  604. for (int k = 0; k < tri_list.Count(); k++)
  605. {
  606. int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3));
  607. //Triangle Kill Test
  608. if (//csgu : CSGUnion() -> m0_Outside + m1_Outside
  609. (csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) ||
  610. //csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted
  611. (csg_operation == CSGUsage::Substract &&
  612. ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) ||
  613. (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) ||
  614. //csgs : CSGSubstractLoss() -> m0_Outside
  615. (csg_operation == CSGUsage::SubstractLoss &&
  616. ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) ||
  617. //csga : CSGAnd() -> m0_Inside + m1_Inside
  618. (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT))
  619. {
  620. triangle_to_kill.Push(tri_idx);
  621. }
  622. //Triangle Invert Test
  623. if (//csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted
  624. (csg_operation == CSGUsage::Substract && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) ||
  625. //csgx : CSGXor() -> m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted
  626. (csg_operation == CSGUsage::Xor && tri_list[k].m1 == LEAF_BACK))
  627. {
  628. //a Xor means we will share vertices with the outside, so duplicate the vertices.
  629. //TODO : This operation disconnect all triangle, in some cases, not a good thing.
  630. if (csg_operation == CSGUsage::Xor)
  631. {
  632. for (int l = 0; l < 3; l++)
  633. {
  634. AddDuplicateVertex(m_indices[tri_idx + l]);
  635. m_indices[tri_idx + l] = m_vert.Count() - 1;
  636. }
  637. }
  638. m_indices[tri_idx + 1] += m_indices[tri_idx + 2];
  639. m_indices[tri_idx + 2] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
  640. m_indices[tri_idx + 1] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
  641. ComputeNormals(tri_idx, 3);
  642. }
  643. }
  644. }
  645. #endif
  646. vert_list.Empty();
  647. tri_list.Empty();
  648. }
  649. }
  650. for (int i = 0; i < m_vert.Count(); i++)
  651. if (length(m_vert[i].m_normal) < 1.0f)
  652. i = i;
  653. int dir = 1;
  654. for (int i = 0; i >= 0 && i < triangle_to_kill.Count() - 1; i += dir)
  655. {
  656. if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0)
  657. dir = 1;
  658. if (triangle_to_kill[i] == triangle_to_kill[i + 1])
  659. {
  660. triangle_to_kill.Remove(i);
  661. dir = -1;
  662. }
  663. if (triangle_to_kill[i] > triangle_to_kill[i + 1])
  664. {
  665. triangle_to_kill[i] += triangle_to_kill[i + 1];
  666. triangle_to_kill[i + 1] = triangle_to_kill[i] - triangle_to_kill[i + 1];
  667. triangle_to_kill[i] = triangle_to_kill[i] - triangle_to_kill[i + 1];
  668. dir = -1;
  669. }
  670. if (i == 0 && dir == -1)
  671. dir = 1;
  672. }
  673. for (int i = triangle_to_kill.Count() - 1; i >= 0; i--)
  674. m_indices.Remove(triangle_to_kill[i], 3);
  675. m_cursors.Last().m1 = m_vert.Count();
  676. m_cursors.Last().m2 = m_indices.Count();
  677. //DONE for the splitting !
  678. }
  679. //-----------------------------------------------------------------------------
  680. void EasyMesh::ToggleScaleWinding()
  681. {
  682. BD()->Toggle(MeshBuildOperation::Scale_Winding);
  683. }
  684. //-----------------------------------------------------------------------------
  685. void EasyMesh::SetCurColor(vec4 const &color)
  686. {
  687. BD()->Color() = color;
  688. }
  689. //-----------------------------------------------------------------------------
  690. void EasyMesh::SetCurColor2(vec4 const &color)
  691. {
  692. BD()->Color2() = color;
  693. }
  694. //-----------------------------------------------------------------------------
  695. void EasyMesh::AddVertex(vec3 const &coord)
  696. {
  697. m_vert.Push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->Color()));
  698. }
  699. //-----------------------------------------------------------------------------
  700. void EasyMesh::AddDuplicateVertex(int i)
  701. {
  702. m_vert << m_vert[i];
  703. }
  704. //-----------------------------------------------------------------------------
  705. void EasyMesh::AddLerpVertex(int i, int j, float alpha)
  706. {
  707. m_vert.Push(VertexData(
  708. lol::lerp(m_vert[i].m_coord, m_vert[j].m_coord, alpha),
  709. lol::lerp(m_vert[i].m_normal, m_vert[j].m_normal, alpha),
  710. lol::lerp(m_vert[i].m_color, m_vert[j].m_color, alpha),
  711. lol::lerp(m_vert[i].m_texcoord, m_vert[j].m_texcoord, alpha),
  712. ((alpha < .5f) ? (m_vert[i].m_bone_id) : (m_vert[j].m_bone_id)), /* FIXME ? */
  713. lol::lerp(m_vert[i].m_bone_weight, m_vert[j].m_bone_weight, alpha)));
  714. }
  715. //-----------------------------------------------------------------------------
  716. void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
  717. {
  718. m_indices << base + i1;
  719. m_indices << base + i2;
  720. m_indices << base + i3;
  721. m_indices << base + i4;
  722. m_indices << base + i1;
  723. m_indices << base + i3;
  724. }
  725. //-----------------------------------------------------------------------------
  726. void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
  727. {
  728. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  729. m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
  730. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  731. m_indices << m_vert.Count(); AddDuplicateVertex(base + i4);
  732. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  733. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  734. }
  735. //-----------------------------------------------------------------------------
  736. void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
  737. {
  738. m_indices << base + i1;
  739. m_indices << base + i2;
  740. m_indices << base + i3;
  741. }
  742. //-----------------------------------------------------------------------------
  743. void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
  744. {
  745. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  746. m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
  747. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  748. }
  749. //-----------------------------------------------------------------------------
  750. void EasyMesh::ComputeNormals(int start, int vcount)
  751. {
  752. for (int i = 0; i < vcount; i += 3)
  753. {
  754. vec3 v0 = m_vert[m_indices[start + i + 2]].m_coord
  755. - m_vert[m_indices[start + i + 0]].m_coord;
  756. vec3 v1 = m_vert[m_indices[start + i + 1]].m_coord
  757. - m_vert[m_indices[start + i + 0]].m_coord;
  758. vec3 n = normalize(cross(v1, v0));
  759. for (int j = 0; j < 3; j++)
  760. m_vert[m_indices[start + i + j]].m_normal = n;
  761. }
  762. }
  763. //-----------------------------------------------------------------------------
  764. void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset)
  765. {
  766. #if 0
  767. VertexDictionnary vert_dict;
  768. Array<int> tri_list;
  769. tri_list.Reserve(m_indices.Count() - m_cursors.Last().m2);
  770. for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++)
  771. {
  772. vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
  773. tri_list << m_indices[i];
  774. }
  775. //full triangle count
  776. Array<int> tri_done;
  777. Array<int> tri_check;
  778. int tri_count = (m_indices.Count() - m_cursors.Last().m2) / 3;
  779. tri_check << tri_list[0];
  780. while (tri_check.Count())
  781. {
  782. int cur_tri = tri_check[0];
  783. 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] };
  784. 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 };
  785. for (int j = 0; j < 3; j++)
  786. {
  787. if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3])
  788. {
  789. uv[0] = vec2(-1.0f);
  790. uv[1] = vec2(-1.0f);
  791. uv[2] = vec2(-1.0f);
  792. break;
  793. }
  794. }
  795. int uv_set = 0;
  796. for (int j = 0; j < 3; j++)
  797. uv_set += (uv[j].x < 0.f)?(0):(1);
  798. //this case shouldn't happen.
  799. if (uv_set == 1)
  800. {
  801. /*
  802. for (int j = 0; j < 3; j++)
  803. {
  804. if (uv[j] != vec2(-1.0f))
  805. {
  806. uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(m_vert[v[j]].m1 - m_vert[v[(j + 1) % 3]].m1));
  807. uv_set = 2;
  808. break;
  809. }
  810. }
  811. */
  812. }
  813. //No UV is set, let's do the arbitrary set and use the basic method.
  814. if (uv_set == 0)
  815. {
  816. float new_dot = FLT_MAX;
  817. int base_i = 0;
  818. for (int j = 0; j < 3; j++)
  819. {
  820. float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m_coord - m_vert[v[j]].m_coord),
  821. normalize(m_vert[v[(j + 2) % 3]].m_coord - m_vert[v[j]].m_coord)));
  822. if (tmp_dot < new_dot)
  823. {
  824. base_i = j;
  825. new_dot = tmp_dot;
  826. }
  827. }
  828. uv[base_i] = vec2(.0f);
  829. 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));
  830. uv_set = 2;
  831. }
  832. //2 points have been set, let's figure the third
  833. if (uv_set == 2)
  834. {
  835. {
  836. //invert values so the two set uv are in [0, 1] slots.
  837. int new_v[3];
  838. vec2 new_uv[3];
  839. bool ignore_set = false;
  840. if (uv[0].x >= 0.f && uv[1].x < 0.f)
  841. {
  842. new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1];
  843. new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1];
  844. }
  845. else if (uv[0].x < 0.f && uv[1].x >= 0.f)
  846. {
  847. new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0];
  848. new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0];
  849. }
  850. else
  851. ignore_set = true;
  852. if (!ignore_set)
  853. {
  854. v[0] = new_v[0]; v[1] = new_v[1]; v[2] = new_v[2];
  855. uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2];
  856. }
  857. }
  858. //Do this to be sure the normal is OK.
  859. ComputeNormals(cur_tri, 3);
  860. vec3 v01 = normalize(m_vert[v[1]].m_coord - m_vert[v[0]].m_coord);
  861. vec3 v02 = m_vert[v[2]].m_coord - m_vert[v[0]].m_coord;
  862. vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m_normal, v01));
  863. vec2 texu_dir = uv[1] - uv[0];
  864. vec2 texv_dir = vec2(texu_dir.y, texu_dir.x);
  865. //Final calculations
  866. uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02);
  867. //Set UV on ALL matching vertices!
  868. Array<int> matching_vert;
  869. for (int i = 0; i < 3; i++)
  870. {
  871. #if 1
  872. //This marks all same position UV to the same values
  873. //Deactivation is a test.
  874. matching_vert << v[i];
  875. vert_dict.FindMatchingVertices(v[i], matching_vert);
  876. for (int j = 0; j < matching_vert.Count(); j++)
  877. if (m_vert[matching_vert[j]].m_texcoord.xy == vec2(-1.0f))
  878. m_vert[matching_vert[j]].m_texcoord = vec4(abs(uv[i]), m_vert[matching_vert[j]].m_texcoord.zw);
  879. #else
  880. m_vert[v[i]].m_texcoord = abs(uv[i]);
  881. #endif
  882. }
  883. tri_done << cur_tri;
  884. tri_check.Remove(0);
  885. //Get connected triangles and go from there.
  886. for (int j = 0; j < 3; j++)
  887. {
  888. #if 1
  889. //This finds triangle that are connected to this triangle
  890. vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done);
  891. #else
  892. //This finds triangle that are connected to the vertices of this triangle
  893. vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done);
  894. #endif
  895. }
  896. }
  897. else if (uv_set == 3)
  898. {
  899. for (int j = 0; j < 3; j++)
  900. {
  901. m_vert[tri_list[cur_tri]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri]].m_texcoord.zw);
  902. m_vert[tri_list[cur_tri + 1]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 1]].m_texcoord.zw);
  903. m_vert[tri_list[cur_tri + 2]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 2]].m_texcoord.zw);
  904. }
  905. //uv[0] = vec2(-1.0f);
  906. //uv[1] = vec2(-1.0f);
  907. //uv[2] = vec2(-1.0f);
  908. /*
  909. bool tri_present = false;
  910. for (int j = 0; j < tri_done.Count(); j++)
  911. if (cur_tri == tri_done[j])
  912. tri_present = true;
  913. if (!tri_present)
  914. tri_done << cur_tri;
  915. tri_check.Remove(0);
  916. */
  917. }
  918. if (tri_check.Count() == 0 && tri_done.Count() != tri_count)
  919. {
  920. //look for unset triangle
  921. for (int i = 0; !tri_check.Count() && i < tri_list.Count(); i += 3)
  922. {
  923. bool tri_present = false;
  924. for (int j = 0; j < tri_done.Count(); j++)
  925. if (i == tri_done[j])
  926. tri_present = true;
  927. if (!tri_present)
  928. tri_check << i;
  929. }
  930. }
  931. }
  932. #endif
  933. }
  934. //-----------------------------------------------------------------------------
  935. void EasyMesh::SetVertColor(vec4 const &color)
  936. {
  937. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  938. m_vert[i].m_color = color;
  939. }
  940. //-----------------------------------------------------------------------------
  941. void EasyMesh::SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale)
  942. {
  943. BD()->TexCoordOffset() = new_offset;
  944. BD()->TexCoordScale() = new_scale;
  945. }
  946. //-----------------------------------------------------------------------------
  947. void EasyMesh::SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale)
  948. {
  949. BD()->TexCoordOffset2() = new_offset;
  950. BD()->TexCoordScale2() = new_scale;
  951. }
  952. //-----------------------------------------------------------------------------
  953. void EasyMesh::SetCurVertNormal(vec3 const &normal)
  954. {
  955. m_vert[m_vert.Count() - 1].m_normal = normal;
  956. }
  957. //-----------------------------------------------------------------------------
  958. void EasyMesh::SetCurVertColor(vec4 const &color)
  959. {
  960. m_vert[m_vert.Count() - 1].m_color = color;
  961. }
  962. //-----------------------------------------------------------------------------
  963. void EasyMesh::SetCurVertTexCoord(vec2 const &texcoord)
  964. {
  965. m_vert[m_vert.Count() - 1].m_texcoord = vec4(texcoord, m_vert[m_vert.Count() - 1].m_texcoord.zw);
  966. }
  967. //-----------------------------------------------------------------------------
  968. void EasyMesh::SetCurVertTexCoord2(vec2 const &texcoord)
  969. {
  970. m_vert[m_vert.Count() - 1].m_texcoord = vec4(m_vert[m_vert.Count() - 1].m_texcoord.xy, texcoord);
  971. }
  972. //-----------------------------------------------------------------------------
  973. void EasyMesh::Translate(vec3 const &v)
  974. {
  975. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  976. m_vert[i].m_coord += v;
  977. }
  978. //-----------------------------------------------------------------------------
  979. void EasyMesh::RotateX(float angle) { Rotate(angle, vec3(1, 0, 0)); }
  980. void EasyMesh::RotateY(float angle) { Rotate(angle, vec3(0, 1, 0)); }
  981. void EasyMesh::RotateZ(float angle) { Rotate(angle, vec3(0, 0, 1)); }
  982. //-----------------------------------------------------------------------------
  983. void EasyMesh::Rotate(float angle, vec3 const &axis)
  984. {
  985. mat3 m = mat3::rotate(angle, axis);
  986. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  987. {
  988. m_vert[i].m_coord = m * m_vert[i].m_coord;
  989. m_vert[i].m_normal = m * m_vert[i].m_normal;
  990. }
  991. }
  992. //-----------------------------------------------------------------------------
  993. void EasyMesh::RadialJitter(float r)
  994. {
  995. Array<int> Welded;
  996. Welded.Push(-1);
  997. for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++)
  998. {
  999. int j, k;
  1000. for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++)
  1001. {
  1002. if(Welded[k] < 0)
  1003. {
  1004. vec3 diff = m_vert[i].m_coord - m_vert[j].m_coord;
  1005. if(diff.x > 0.1f || diff.x < -0.1f)
  1006. continue;
  1007. if(diff.y > 0.1f || diff.y < -0.1f)
  1008. continue;
  1009. if(diff.z > 0.1f || diff.z < -0.1f)
  1010. continue;
  1011. break;
  1012. }
  1013. }
  1014. if(j == i)
  1015. Welded.Push(-1);
  1016. else
  1017. Welded.Push(j);
  1018. }
  1019. int i, j;
  1020. for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++)
  1021. {
  1022. if(Welded[j] == -1)
  1023. m_vert[i].m_coord *= 1.0f + RandF(r);
  1024. else
  1025. m_vert[i].m_coord = m_vert[Welded[j]].m_coord;
  1026. }
  1027. ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
  1028. }
  1029. //-----------------------------------------------------------------------------
  1030. void EasyMesh::TaperX(float ny, float nz, float xoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::X, Axis::X, ny, nz, xoff, absolute); }
  1031. void EasyMesh::TaperY(float nx, float nz, float yoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
  1032. void EasyMesh::TaperZ(float nx, float ny, float zoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
  1033. //-----------------------------------------------------------------------------
  1034. void EasyMesh::TwistX(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::X, Axis::X, t, t, toff, 0); }
  1035. void EasyMesh::TwistY(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Y, Axis::Y, t, t, toff, 0); }
  1036. void EasyMesh::TwistZ(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Z, Axis::Z, t, t, toff, 0); }
  1037. //-----------------------------------------------------------------------------
  1038. void EasyMesh::ShearX(float ny, float nz, float xoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::X, Axis::X, ny, nz, xoff, absolute); }
  1039. void EasyMesh::ShearY(float nx, float nz, float yoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
  1040. void EasyMesh::ShearZ(float nx, float ny, float zoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
  1041. //-----------------------------------------------------------------------------
  1042. void EasyMesh::StretchX(float ny, float nz, float xoff) { DoMeshTransform(MeshTransform::Stretch, Axis::X, Axis::X, ny, nz, xoff, 0); }
  1043. void EasyMesh::StretchY(float nx, float nz, float yoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Y, Axis::Y, nz, nx, yoff, 0); }
  1044. void EasyMesh::StretchZ(float nx, float ny, float zoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Z, Axis::Z, nx, ny, zoff, 0); }
  1045. //-----------------------------------------------------------------------------
  1046. void EasyMesh::BendXY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Y, t, t, toff, 0); }
  1047. void EasyMesh::BendXZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Z, t, t, toff, 0); }
  1048. void EasyMesh::BendYX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::X, t, t, toff, 0); }
  1049. void EasyMesh::BendYZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::Z, t, t, toff, 0); }
  1050. void EasyMesh::BendZX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::X, t, t, toff, 0); }
  1051. void EasyMesh::BendZY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::Y, t, t, toff, 0); }
  1052. //-----------------------------------------------------------------------------
  1053. void EasyMesh::DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, int absolute)
  1054. {
  1055. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  1056. {
  1057. switch (ct)
  1058. {
  1059. case MeshTransform::Taper:
  1060. {
  1061. float value = m_vert[i].m_coord[axis0];
  1062. if (absolute) value = abs(value);
  1063. m_vert[i].m_coord[(axis0 + 1) % 3] *= max(0.f, 1.f + (n0 * value + noff));
  1064. m_vert[i].m_coord[(axis0 + 2) % 3] *= max(0.f, 1.f + (n1 * value + noff));
  1065. break;
  1066. }
  1067. case MeshTransform::Twist:
  1068. {
  1069. vec3 rotaxis = vec3(1.f); rotaxis[(axis0 + 1) % 3] = .0f; rotaxis[(axis0 + 2) % 3] = .0f;
  1070. m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0] * n0 + noff, rotaxis) * m_vert[i].m_coord;
  1071. break;
  1072. }
  1073. case MeshTransform::Shear:
  1074. {
  1075. float value = m_vert[i].m_coord[axis0];
  1076. if (absolute) value = abs(value);
  1077. m_vert[i].m_coord[(axis0 + 1) % 3] += (n0 * value + noff);
  1078. m_vert[i].m_coord[(axis0 + 2) % 3] += (n1 * value + noff);
  1079. break;
  1080. }
  1081. case MeshTransform::Stretch:
  1082. {
  1083. //float value = abs(m_vert[i].m1[axis0]);
  1084. //m_vert[i].m1[(axis0 + 1) % 3] += (lol::pow(value, n0) + noff);
  1085. //m_vert[i].m1[(axis0 + 2) % 3] += (lol::pow(value, n1) + noff);
  1086. break;
  1087. }
  1088. case MeshTransform::Bend:
  1089. {
  1090. vec3 rotaxis = vec3(1.f); rotaxis[(axis1 + 1) % 3] = .0f; rotaxis[(axis1 + 2) % 3] = .0f;
  1091. m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0] * n0 + noff, rotaxis) * m_vert[i].m_coord;
  1092. break;
  1093. }
  1094. }
  1095. }
  1096. ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
  1097. }
  1098. //-----------------------------------------------------------------------------
  1099. void EasyMesh::Scale(vec3 const &s)
  1100. {
  1101. vec3 const invs = vec3(1) / s;
  1102. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  1103. {
  1104. m_vert[i].m_coord *= s;
  1105. m_vert[i].m_normal = normalize(m_vert[i].m_normal * invs);
  1106. }
  1107. /* Flip winding if the scaling involves mirroring */
  1108. if (!BD()->IsEnabled(MeshBuildOperation::Scale_Winding) && s.x * s.y * s.z < 0)
  1109. {
  1110. for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3)
  1111. {
  1112. uint16_t tmp = m_indices[i + 0];
  1113. m_indices[i + 0] = m_indices[i + 1];
  1114. m_indices[i + 1] = tmp;
  1115. }
  1116. }
  1117. }
  1118. //-----------------------------------------------------------------------------
  1119. void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
  1120. void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
  1121. void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
  1122. //-----------------------------------------------------------------------------
  1123. void EasyMesh::DupAndScale(vec3 const &s)
  1124. {
  1125. int vlen = m_vert.Count() - m_cursors.Last().m1;
  1126. int tlen = m_indices.Count() - m_cursors.Last().m2;
  1127. for (int i = 0; i < vlen; i++)
  1128. AddDuplicateVertex(m_cursors.Last().m1++);
  1129. for (int i = 0; i < tlen; i++)
  1130. m_indices << m_indices[m_cursors.Last().m2++] + vlen;
  1131. Scale(s);
  1132. m_cursors.Last().m1 -= vlen;
  1133. m_cursors.Last().m2 -= tlen;
  1134. }
  1135. //-----------------------------------------------------------------------------
  1136. void EasyMesh::AppendCylinder(int nsides, float h, float d1, float d2,
  1137. int dualside, int smooth, int close)
  1138. {
  1139. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1140. float r1 = d1 * .5f;
  1141. float r2 = d2 * .5f;
  1142. //SAVE
  1143. vec4 Saved_Color = BD()->Color();
  1144. vec4 Saved_Color2 = BD()->Color2();
  1145. vec2 Save_texcoord_offset = BD()->TexCoordOffset();
  1146. vec2 Save_texcoord_scale = BD()->TexCoordScale();
  1147. int vbase = m_vert.Count();
  1148. mat3 rotmat = mat3::rotate(360.0f / (float)nsides, 0.f, 1.f, 0.f);
  1149. vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
  1150. vec2 uv1(.0f, .0f), uv2(.0f, 1.0f), uvadd(1.0f / (float)nsides, .0f);
  1151. if (close)
  1152. SetTexCoordData(vec2(.0f), vec2(1.0f, .5f));
  1153. /* Construct normal */
  1154. if (r2 != .0f)
  1155. n = vec3(r2, h * .5f, 0.f);
  1156. else
  1157. n = vec3(r1, h * .5f, 0.f);
  1158. n.y = r1 * (r1 - r2) / h;
  1159. if (!smooth)
  1160. n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
  1161. n = normalize(n);
  1162. /* FIXME: normals should be flipped in two-sided mode, but that
  1163. * means duplicating the vertices again... */
  1164. for (int i = 0; i < nsides; i++)
  1165. {
  1166. AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
  1167. AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2);
  1168. SetCurVertColor(BD()->Color2());
  1169. if (smooth)
  1170. {
  1171. int j = (i + 1) % nsides;
  1172. AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
  1173. if (dualside)
  1174. AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
  1175. }
  1176. p1 = rotmat * p1; uv1 += uvadd;
  1177. p2 = rotmat * p2; uv2 += uvadd;
  1178. if (!smooth)
  1179. {
  1180. AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
  1181. AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2);
  1182. SetCurVertColor(BD()->Color2());
  1183. AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
  1184. if (dualside)
  1185. AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
  1186. }
  1187. n = rotmat * n;
  1188. }
  1189. if (close)
  1190. {
  1191. //START
  1192. OpenBrace();
  1193. //LOWER DISC
  1194. SetTexCoordData(vec2(.0f, .5f), vec2(.5f, .5f));
  1195. SetCurColor(BD()->Color());
  1196. AppendDisc(nsides, d1);
  1197. Translate(vec3(.0f, h, .0f));
  1198. RotateX(180.0f);
  1199. //UPPER DISC
  1200. SetTexCoordData(vec2(.5f, .5f), vec2(.5f, .5f));
  1201. SetCurColor(BD()->Color2());
  1202. AppendDisc(nsides, d2);
  1203. Translate(vec3(.0f, h * .5f, .0f));
  1204. CloseBrace();
  1205. }
  1206. //RESTORE
  1207. SetCurColor(Saved_Color);
  1208. SetCurColor2(Saved_Color2);
  1209. SetTexCoordData(Save_texcoord_offset, Save_texcoord_scale);
  1210. }
  1211. //-----------------------------------------------------------------------------
  1212. void EasyMesh::AppendSphere(int ndivisions, float d)
  1213. {
  1214. AppendCapsule(ndivisions, 0.f, d);
  1215. }
  1216. //-----------------------------------------------------------------------------
  1217. void EasyMesh::AppendCapsule(int ndivisions, float h, float d)
  1218. {
  1219. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1220. float r = d * .5f;
  1221. int ibase = m_indices.Count();
  1222. Array<vec3> vertices;
  1223. float uv_h = 0;
  1224. float uv_r = 0;
  1225. /* FIXME: we don't know how to handle even-divided capsules, so we
  1226. * force the count to be odd. */
  1227. if (h)
  1228. {
  1229. ndivisions |= 1;
  1230. //calculate uv h&r percents
  1231. uv_h = (float)h / (float)(h + r * 2);
  1232. uv_r = (float)r / (float)(h + r * 2);
  1233. }
  1234. /* Fill in the icosahedron vertices, rotating them so that there
  1235. * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */
  1236. float phi = 0.5f + 0.5f * sqrt(5.f);
  1237. mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / (float)M_PI),
  1238. vec3(0.f, 0.f, 1.f));
  1239. for (int i = 0; i < 4; i++)
  1240. {
  1241. float x = (i & 1) ? 0.5f : -0.5f;
  1242. float y = (i & 2) ? phi * 0.5f : phi * -0.5f;
  1243. vertices << mat * vec3(x, y, 0.f);
  1244. vertices << mat * vec3(0.f, x, y);
  1245. vertices << mat * vec3(y, 0.f, x);
  1246. }
  1247. static int const trilist[] =
  1248. {
  1249. 0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8,
  1250. 7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11,
  1251. 0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1,
  1252. 2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6,
  1253. 7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8
  1254. };
  1255. for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3)
  1256. {
  1257. vec3 const &a = vertices[trilist[i]];
  1258. vec3 const &b = vertices[trilist[i + 1]];
  1259. vec3 const &c = vertices[trilist[i + 2]];
  1260. vec3 const vb = 1.f / ndivisions * (b - a);
  1261. vec3 const vc = 1.f / ndivisions * (c - a);
  1262. int line = ndivisions + 1;
  1263. for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++)
  1264. {
  1265. vec3 p[] = { a + (float)x * vb + (float)y * vc,
  1266. p[0] + vb,
  1267. p[0] + vc,
  1268. p[0] + vb + vc };
  1269. vec2 uv[4];
  1270. /* FIXME: when we normalise here, we get a volume that is slightly
  1271. * smaller than the sphere of radius 1, since we are not using
  1272. * the midradius. */
  1273. for (int k = 0; k < 4; k++)
  1274. {
  1275. //keep normalized until the end of the UV calculations
  1276. p[k] = normalize(p[k]);
  1277. uv[k].x = (lol::atan2(p[k].z, p[k].x) + (float)M_PI) / ((float)M_PI * 2.f);
  1278. if (abs(p[k].y) >= 1.0f)
  1279. uv[k].x = -1.f;
  1280. uv[k].y = lol::atan2(p[k].y, dot(p[k], normalize(p[k] * vec3(1.f,0.f,1.f)))) / (float)M_PI + 0.5f;
  1281. if (h)
  1282. {
  1283. if (uv[k].y > .5f)
  1284. uv[k].y = uv_r + uv_h + (uv[k].y - .5f) * uv_r * 2.f;
  1285. else
  1286. uv[k].y *= uv_r * 2.f;
  1287. }
  1288. p[k] *= r;
  1289. }
  1290. /* If this is a capsule, grow in the Y direction */
  1291. if (h > 0.f)
  1292. {
  1293. for (int k = 0; k < 4; k++)
  1294. p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h;
  1295. }
  1296. /* Add zero, one or two triangles */
  1297. int id[] = { 0, 1, 2,
  1298. 1, 3 ,2 };
  1299. int l = 6;
  1300. while ((l -= 3) >= 0)
  1301. {
  1302. if ((l == 0 && y < line - 1) || (l == 3 && y < line - 2))
  1303. {
  1304. int k = -1;
  1305. while (++k < 3)
  1306. {
  1307. int rid[] = { id[k + l], id[(k + 1) % 3 + l] };
  1308. if (uv[rid[0]].x >= .0f &&
  1309. uv[rid[1]].x >= .0f &&
  1310. abs(uv[rid[0]].x - uv[rid[1]].x) > .5f)
  1311. {
  1312. if (uv[rid[0]].x < uv[rid[1]].x)
  1313. uv[rid[0]].x += 1.0f;
  1314. else
  1315. uv[rid[1]].x += 1.0f;
  1316. }
  1317. }
  1318. k = -1;
  1319. while (++k < 3)
  1320. {
  1321. int rid[] = { id[k + l], id[(k + 1) % 3 + l], id[(k + 2) % 3 + l] };
  1322. AddVertex(p[rid[0]]);
  1323. vec2 new_uv;
  1324. if (uv[rid[0]].x < .0f)
  1325. new_uv = vec2((uv[rid[1]].x + uv[rid[2]].x) * .5f, uv[rid[0]].y);
  1326. else
  1327. new_uv = uv[rid[0]];
  1328. SetCurVertTexCoord(vec2(0.f, 1.f) - new_uv);
  1329. SetCurVertTexCoord2(vec2(0.f, 1.f) - new_uv);
  1330. }
  1331. AppendTriangle(0, 2, 1, m_vert.Count() - 3);
  1332. }
  1333. }
  1334. y++;
  1335. if (y == line)
  1336. {
  1337. x++;
  1338. y = 0;
  1339. line--;
  1340. }
  1341. }
  1342. }
  1343. ComputeNormals(ibase, m_indices.Count() - ibase);
  1344. }
  1345. //-----------------------------------------------------------------------------
  1346. void EasyMesh::AppendTorus(int ndivisions, float d1, float d2)
  1347. {
  1348. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1349. float r1 = d1 * .5f;
  1350. float r2 = d2 * .5f;
  1351. int ibase = m_indices.Count();
  1352. int nidiv = ndivisions; /* Cross-section */
  1353. int njdiv = ndivisions; /* Full circumference */
  1354. for (int j = 0; j < njdiv; j++)
  1355. for (int i = 0; i < 2 * nidiv; i++)
  1356. {
  1357. for (int di = 0; di < 2; di++)
  1358. for (int dj = 0; dj < 2; dj++)
  1359. {
  1360. int i2 = (i + di) % nidiv;
  1361. int j2 = (j + dj) % njdiv;
  1362. //Location on the donut
  1363. float x = 0.5f * (r2 - r1) * (float)lol::cos(2.0 * M_PI * i2 / nidiv) + 0.5f * (r1 + r2);
  1364. float y = 0.5f * (r2 - r1) * (float)lol::sin(2.0 * M_PI * i2 / nidiv);
  1365. float z = 0.0f;
  1366. //Center circle
  1367. float ca = (float)lol::cos(2.0 * M_PI * j2 / njdiv);
  1368. float sa = (float)lol::sin(2.0 * M_PI * j2 / njdiv);
  1369. //Actual location
  1370. float x2 = x * ca - z * sa;
  1371. float z2 = z * ca + x * sa;
  1372. AddVertex(vec3(x2, y, z2));
  1373. SetCurVertTexCoord(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
  1374. SetCurVertTexCoord2(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
  1375. }
  1376. AppendTriangle(0, 2, 3, m_vert.Count() - 4);
  1377. AppendTriangle(0, 3, 1, m_vert.Count() - 4);
  1378. }
  1379. ComputeNormals(ibase, m_indices.Count() - ibase);
  1380. }
  1381. //-----------------------------------------------------------------------------
  1382. void EasyMesh::AppendBox(vec3 const &size, float chamf)
  1383. {
  1384. AppendBox(size, chamf, false);
  1385. }
  1386. //-----------------------------------------------------------------------------
  1387. void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
  1388. {
  1389. AppendBox(size, chamf, true);
  1390. }
  1391. //-----------------------------------------------------------------------------
  1392. void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
  1393. {
  1394. AppendBox(size, chamf, false);
  1395. }
  1396. //-----------------------------------------------------------------------------
  1397. void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
  1398. {
  1399. if (chamf < 0.0f)
  1400. {
  1401. AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
  1402. return;
  1403. }
  1404. int vbase = m_vert.Count();
  1405. int ibase = m_indices.Count();
  1406. vec3 d = size * 0.5f;
  1407. MeshType mt = MeshType::Box;
  1408. TexCoordPos bl = TexCoordPos::BL;
  1409. TexCoordPos br = TexCoordPos::BR;
  1410. TexCoordPos tl = TexCoordPos::TL;
  1411. TexCoordPos tr = TexCoordPos::TR;
  1412. //--
  1413. //Side vertices
  1414. //--
  1415. MeshFaceType mft = MeshFaceType::BoxFront;
  1416. AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
  1417. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1418. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1419. //--
  1420. AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
  1421. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1422. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1423. //--
  1424. AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
  1425. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1426. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1427. //--
  1428. AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
  1429. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1430. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1431. //--
  1432. mft = MeshFaceType::BoxLeft;
  1433. AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
  1434. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1435. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1436. //--
  1437. AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
  1438. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1439. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1440. //--
  1441. AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
  1442. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1443. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1444. //--
  1445. AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
  1446. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1447. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1448. //--
  1449. mft = MeshFaceType::BoxBack;
  1450. AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
  1451. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1452. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1453. //--
  1454. AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
  1455. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1456. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1457. //--
  1458. AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
  1459. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1460. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1461. //--
  1462. AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
  1463. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1464. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1465. //--
  1466. mft = MeshFaceType::BoxRight;
  1467. AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
  1468. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1469. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1470. //--
  1471. AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
  1472. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1473. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1474. //--
  1475. AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
  1476. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1477. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1478. //--
  1479. AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
  1480. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1481. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1482. //--
  1483. //Bottom vertices
  1484. //--
  1485. mft = MeshFaceType::BoxBottom;
  1486. AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
  1487. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1488. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1489. //--
  1490. AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
  1491. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1492. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1493. //--
  1494. AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
  1495. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1496. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1497. //--
  1498. AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
  1499. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1500. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1501. //--
  1502. //Top vertices
  1503. //--
  1504. mft = MeshFaceType::BoxTop;
  1505. AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
  1506. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1507. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1508. //--
  1509. AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
  1510. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1511. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1512. //--
  1513. AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
  1514. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1515. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1516. //--
  1517. AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
  1518. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1519. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1520. /* The 6 quads on each side of the box */
  1521. for (int i = 0; i < 24; i += 4)
  1522. AppendQuad(i, i + 1, i + 2, i + 3, vbase);
  1523. ComputeNormals(ibase, m_indices.Count() - ibase);
  1524. ibase = m_indices.Count();
  1525. /* The 8 quads at each edge of the box */
  1526. if (chamf)
  1527. {
  1528. static int const quadlist[48] =
  1529. {
  1530. 0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
  1531. 2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
  1532. 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
  1533. };
  1534. for (int i = 0; i < 48; i += 4)
  1535. {
  1536. if (smooth)
  1537. AppendQuad(quadlist[i], quadlist[i + 1],
  1538. quadlist[i + 2], quadlist[i + 3], vbase);
  1539. else
  1540. AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
  1541. quadlist[i + 2], quadlist[i + 3], vbase);
  1542. }
  1543. }
  1544. /* The 8 triangles at each corner of the box */
  1545. if (chamf)
  1546. {
  1547. static int const trilist[24] =
  1548. {
  1549. 3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
  1550. 2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
  1551. };
  1552. for (int i = 0; i < 24; i += 3)
  1553. {
  1554. if (smooth)
  1555. AppendTriangle(trilist[i], trilist[i + 1],
  1556. trilist[i + 2], vbase);
  1557. else
  1558. AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
  1559. trilist[i + 2], vbase);
  1560. }
  1561. }
  1562. if (!smooth)
  1563. ComputeNormals(ibase, m_indices.Count() - ibase);
  1564. }
  1565. //-----------------------------------------------------------------------------
  1566. void EasyMesh::AppendStar(int nbranches, float d1, float d2,
  1567. int fade, int fade2)
  1568. {
  1569. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1570. float r1 = d1 * .5f;
  1571. float r2 = d2 * .5f;
  1572. //TODO: It would probably be good to think of another way of UV painting this, like "branch repeating"
  1573. int vbase = m_vert.Count();
  1574. float maxr = max(r1, r2);
  1575. AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
  1576. mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
  1577. vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
  1578. vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
  1579. uv2(0.f, 0.f, -.5f * ((float)r2 / maxr));
  1580. p2 = rotmat * p2; uv2 = rotmat * uv2;
  1581. rotmat = rotmat * rotmat;
  1582. for (int i = 0; i < nbranches; i++)
  1583. {
  1584. AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
  1585. if (fade2)
  1586. SetCurVertColor(BD()->Color2());
  1587. AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
  1588. if (fade)
  1589. SetCurVertColor(BD()->Color2());
  1590. AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
  1591. vbase);
  1592. p1 = rotmat * p1; uv1 = rotmat * uv1;
  1593. p2 = rotmat * p2; uv2 = rotmat * uv2;
  1594. }
  1595. }
  1596. //-----------------------------------------------------------------------------
  1597. void EasyMesh::AppendExpandedStar(int nbranches, float d1, float d2, float extrad)
  1598. {
  1599. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1600. float r1 = d1 * .5f;
  1601. float r2 = d2 * .5f;
  1602. float extrar = extrad * .5f;
  1603. int vbase = m_vert.Count();
  1604. float maxr = (float)max(max(r1, r2), max(r1 + extrar, r2 + extrar));
  1605. AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
  1606. mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
  1607. vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
  1608. p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
  1609. vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
  1610. uv2(0.f, 0.f, -.5f * ((float)r2 / maxr)),
  1611. uv3(0.f, 0.f, -.5f * ((float)(r1 + extrar) / maxr)),
  1612. uv4(0.f, 0.f, -.5f * ((float)(r2 + extrar) / maxr));
  1613. p2 = rotmat * p2; uv2 = rotmat * uv2;
  1614. p4 = rotmat * p4; uv4 = rotmat * uv4;
  1615. rotmat = rotmat * rotmat;
  1616. for (int i = 0; i < nbranches; i++)
  1617. {
  1618. AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
  1619. AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
  1620. AddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->Color2());
  1621. AddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->Color2());
  1622. int j = (i + 1) % nbranches;
  1623. AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
  1624. AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
  1625. AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
  1626. p1 = rotmat * p1; uv1 = rotmat * uv1;
  1627. p2 = rotmat * p2; uv2 = rotmat * uv2;
  1628. p3 = rotmat * p3; uv3 = rotmat * uv3;
  1629. p4 = rotmat * p4; uv4 = rotmat * uv4;
  1630. }
  1631. }
  1632. //-----------------------------------------------------------------------------
  1633. void EasyMesh::AppendDisc(int nsides, float d, int fade)
  1634. {
  1635. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1636. float r = d * .5f;
  1637. int vbase = m_vert.Count();
  1638. AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
  1639. mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
  1640. vec3 p1(r, 0.f, 0.f);
  1641. vec3 uv(.5f, .0f, .0f);
  1642. for (int i = 0; i < nsides; i++)
  1643. {
  1644. AddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f));
  1645. if (fade)
  1646. SetCurVertColor(BD()->Color2());
  1647. AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
  1648. p1 = rotmat * p1;
  1649. uv = rotmat * uv;
  1650. }
  1651. }
  1652. //-----------------------------------------------------------------------------
  1653. void EasyMesh::AppendSimpleTriangle(float d, int fade)
  1654. {
  1655. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1656. float size = d * .5f;
  1657. mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
  1658. vec3 p(0.f, 0.f, size);
  1659. AddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f));
  1660. p = m * p;
  1661. AddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f));
  1662. if (fade)
  1663. SetCurVertColor(BD()->Color2());
  1664. p = m * p;
  1665. AddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f));
  1666. if (fade)
  1667. SetCurVertColor(BD()->Color2());
  1668. AppendTriangle(0, 1, 2, m_vert.Count() - 3);
  1669. }
  1670. //-----------------------------------------------------------------------------
  1671. void EasyMesh::AppendSimpleQuad(float size, int fade)
  1672. {
  1673. AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
  1674. }
  1675. //-----------------------------------------------------------------------------
  1676. void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
  1677. {
  1678. MeshType mt = MeshType::Quad;
  1679. MeshFaceType mft = MeshFaceType::QuadDefault;
  1680. //--
  1681. AddVertex(vec3(p2.x, z, -p1.y));
  1682. TexCoordPos br = TexCoordPos::BR;
  1683. SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
  1684. SetCurVertTexCoord2(BD()->TexCoord2(mt, br, mft));
  1685. //--
  1686. AddVertex(vec3(p2.x, z, -p2.y));
  1687. TexCoordPos bl = TexCoordPos::BL;
  1688. SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
  1689. SetCurVertTexCoord2(BD()->TexCoord2(mt, bl, mft));
  1690. //--
  1691. AddVertex(vec3(p1.x, z, -p2.y));
  1692. TexCoordPos tl = TexCoordPos::TL;
  1693. SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
  1694. SetCurVertTexCoord2(BD()->TexCoord2(mt, tl, mft));
  1695. if (fade) SetCurVertColor(BD()->Color2());
  1696. //--
  1697. AddVertex(vec3(p1.x, z, -p1.y));
  1698. TexCoordPos tr = TexCoordPos::TR;
  1699. SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
  1700. SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
  1701. if (fade) SetCurVertColor(BD()->Color2());
  1702. AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
  1703. ComputeNormals(m_indices.Count() - 6, 6);
  1704. }
  1705. //-----------------------------------------------------------------------------
  1706. void EasyMesh::AppendCog(int nbsides, float h, float d10, float d20,
  1707. float d1, float d2, float d12, float d22,
  1708. float sidemul, int offset)
  1709. {
  1710. //XXX : This operation is done to convert radius to diameter without changing all the code.
  1711. float r10 = d10 * .5f;
  1712. float r20 = d20 * .5f;
  1713. float r1 = d1 * .5f;
  1714. float r2 = d2 * .5f;
  1715. float r12 = d12 * .5f;
  1716. float r22 = d22 * .5f;
  1717. int ibase = m_indices.Count();
  1718. int vbase = m_vert.Count();
  1719. /* FIXME: enforce this some other way */
  1720. if (r12 < 0)
  1721. h = -h;
  1722. mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
  1723. mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
  1724. mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
  1725. vec3 p[12];
  1726. //Upper points
  1727. p[0] = vec3(r10, h * .5f, 0.f);
  1728. p[1] = rotmat * p[0];
  1729. p[2] = vec3(r1, h * .5f, 0.f);
  1730. p[3] = rotmat * p[2];
  1731. p[4] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
  1732. p[5] = smat2 * (rotmat * p[4]);
  1733. //Lower points
  1734. p[6] = vec3(r20, h * -.5f, 0.f);
  1735. p[7] = rotmat * p[6];
  1736. p[8] = vec3(r2, h * -.5f, 0.f);
  1737. p[9] = rotmat * p[8];
  1738. p[10] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
  1739. p[11] = smat2 * (rotmat * p[10]);
  1740. if (offset & 1)
  1741. for (int n = 0; n < 12; n++)
  1742. p[n] = rotmat * p[n];
  1743. rotmat = rotmat * rotmat;
  1744. //UV base computation
  1745. float maxr = max(max(r1 + r12, r2 + r22), max(r10, r20));
  1746. float InLn = length(p[1] - p[0]);
  1747. float CogLn[8] = { .0f, .0f, .0f, .0f, .0f, .0f, .0f, .0f };
  1748. for (int i = 0; i < 3; i++)
  1749. {
  1750. for (int j = 0, k = 2; j < 8 && k < 12; j += 4, k += 6)
  1751. {
  1752. CogLn[j + i] = length(p[k + i + 1] - p[k + i]);
  1753. CogLn[j + 3] += CogLn[j + i];
  1754. if (i == 1) //Add 3to4 twice since it's automatically completed by +1 loop.
  1755. CogLn[j + 3] += CogLn[j + i];
  1756. }
  1757. }
  1758. //Choose the biggest cog length
  1759. int CogSrc = (CogLn[7] > CogLn[3])?(4):(0);
  1760. CogLn[3] = CogLn[CogSrc + 3];
  1761. for (int i = 0; i < 3; i++)
  1762. CogLn[i] = CogLn[CogSrc + i] / CogLn[CogSrc + 3];
  1763. //Calculate Cog Modifiers
  1764. vec2 InUV[2] = { vec2(.0f), vec2(.5f) };
  1765. vec2 CogUV[2] = { vec2(.0f), vec2(.5f) };
  1766. vec2 upadd = vec2(.25f, .75f);
  1767. vec2 lowadd = vec2(.75f, .75f);
  1768. {
  1769. if (h < InLn)
  1770. {
  1771. InUV[0].x = 1.0f;
  1772. InUV[0].y = h / InLn;
  1773. InUV[1].x = .0f;
  1774. InUV[1].y -= InUV[0].y * .5f;
  1775. }
  1776. else
  1777. {
  1778. InUV[0].x = InLn / h;
  1779. InUV[0].y = 1.0f;
  1780. InUV[1].x -= InUV[0].x * .5f;
  1781. InUV[1].y = .0f;
  1782. }
  1783. if (h < CogLn[3])
  1784. {
  1785. CogUV[0].x = 1.0f;
  1786. CogUV[0].y = h / CogLn[3];
  1787. CogUV[1].x = .0f;
  1788. CogUV[1].y -= CogUV[0].y * .5f;
  1789. }
  1790. else
  1791. {
  1792. CogUV[0].x = CogLn[3] / h;
  1793. CogUV[0].y = 1.0f;
  1794. CogUV[1].x -= CogUV[0].x * .5f;
  1795. CogUV[1].y = .0f;
  1796. }
  1797. if (InUV[0].x + CogUV[0].x < .5f)
  1798. {
  1799. InUV[1].x = .0f;
  1800. CogUV[1].x = .5f - CogUV[0].x;
  1801. upadd = vec2(.75f, .25f);
  1802. lowadd = vec2(.75f, .75f);
  1803. }
  1804. else if (InUV[0].y + CogUV[0].y < .5f)
  1805. {
  1806. InUV[1].y = .0f;
  1807. CogUV[1].y = .5f - CogUV[0].y;
  1808. }
  1809. else
  1810. {
  1811. InUV[0] *= .5f;
  1812. InUV[1] *= .5f;
  1813. CogUV[0] *= .5f;
  1814. CogUV[1] *= .5f;
  1815. InUV[1] += vec2(.5f, .0f);
  1816. }
  1817. }
  1818. //Build UV tab
  1819. vec2 uv[12]; float CogSz;
  1820. //Upper points
  1821. CogSz = 1.0f - CogLn[1];
  1822. uv[0] = vec2(0.f, 0.f) * InUV[0] + InUV[1];
  1823. uv[1] = vec2(1.f, 0.f) * InUV[0] + InUV[1];
  1824. uv[5] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2];
  1825. uv[4] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1];
  1826. uv[3] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0];
  1827. uv[2] = vec2(0.f, 0.f) * CogUV[0] + CogUV[1];
  1828. //Lower points
  1829. CogSz = 1.0f - CogLn[1];
  1830. uv[6] = vec2(0.f, 1.f) * InUV[0] + InUV[1];
  1831. uv[7] = vec2(1.f, 1.f) * InUV[0] + InUV[1];
  1832. uv[11] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2];
  1833. uv[10] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1];
  1834. uv[ 9] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0];
  1835. uv[ 8] = vec2(0.f, 1.f) * CogUV[0] + CogUV[1];
  1836. //Gear generation loop
  1837. for (int i = 0; i < nbsides; i++)
  1838. {
  1839. int j = 3 * 12 * i,
  1840. k = 3 * 12 * ((i + 1) % nbsides);
  1841. int q[] = { /* The top and bottom faces */
  1842. j, j, j, j,
  1843. j, j, j, j,
  1844. j, j, k, k,
  1845. k, k, j, j,
  1846. j, j, j, k,
  1847. k, j, j, j,
  1848. /* The inner side quads */
  1849. j, j, j, j,
  1850. j, k, k, j,
  1851. /* The outer side quads */
  1852. j, j, j, j,
  1853. j, j, j, j,
  1854. j, j, j, j,
  1855. k, j, j, k
  1856. };
  1857. int m[] = { /* The top and bottom faces */
  1858. 0, 2, 3, 1,
  1859. 7, 9, 8, 6,
  1860. 1, 3, 2, 0,
  1861. 6, 8, 9, 7,
  1862. 3, 4, 5, 2,
  1863. 8, 11, 10, 9,
  1864. /* The inner side quads */
  1865. 0, 1, 7, 6,
  1866. 1, 0, 6, 7,
  1867. /* The outer side quads */
  1868. 3, 2, 8, 9,
  1869. 4, 3, 9, 10,
  1870. 5, 4, 10, 11,
  1871. 2, 5, 11, 8
  1872. };
  1873. int a[] = { /* The top and bottom faces */
  1874. 0, 0, 0, 0,
  1875. 0, 0, 0, 0,
  1876. 0, 0, 0, 0,
  1877. 0, 0, 0, 0,
  1878. 0, 0, 0, 0,
  1879. 0, 0, 0, 0,
  1880. /* The inner side quads */
  1881. 1, 1, 1, 1,
  1882. 2, 2, 2, 2,
  1883. /* The outer side quads */
  1884. 1, 1, 1, 1,
  1885. 1, 2, 2, 1,
  1886. 1, 2, 2, 1,
  1887. 2, 2, 2, 2
  1888. };
  1889. /* Each vertex will share three faces, so three different
  1890. * normals, therefore we add each vertex three times. */
  1891. for (int n = 0; n < 3 * 12; n++)
  1892. {
  1893. int d = n / 3;
  1894. int m = d % 6;
  1895. AddVertex(p[d]);
  1896. if (n % 3 == 0) //Top-Bottom logic
  1897. {
  1898. vec2 tmp = (p[d].xz / maxr);
  1899. vec2 add;
  1900. if (d >= 6)
  1901. {
  1902. tmp *= -1.0f;
  1903. add = lowadd;
  1904. }
  1905. else
  1906. add = upadd;
  1907. SetCurVertTexCoord(tmp * vec2(.25f) + add);
  1908. SetCurVertTexCoord2(tmp * vec2(.25f) + add);
  1909. }
  1910. else if (m == 0 || m == 1) //inner Logic
  1911. {
  1912. SetCurVertTexCoord(uv[d]);
  1913. SetCurVertTexCoord2(uv[d]);
  1914. }
  1915. else //Cog logic
  1916. {
  1917. if (m == 2 && n % 3 == 2)
  1918. {
  1919. SetCurVertTexCoord(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]);
  1920. SetCurVertTexCoord2(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]);
  1921. }
  1922. else
  1923. {
  1924. SetCurVertTexCoord(uv[d]);
  1925. SetCurVertTexCoord2(uv[d]);
  1926. }
  1927. }
  1928. if (d >= 6)
  1929. SetCurVertColor(BD()->Color2());
  1930. }
  1931. int l = -4;
  1932. while ((l += 4) < 48)
  1933. AppendQuad(q[l + 0] + m[l + 0] * 3 + a[l + 0],
  1934. q[l + 1] + m[l + 1] * 3 + a[l + 1],
  1935. q[l + 2] + m[l + 2] * 3 + a[l + 2],
  1936. q[l + 3] + m[l + 3] * 3 + a[l + 3],
  1937. vbase);
  1938. for (int n = 0; n < 12; n++)
  1939. p[n] = rotmat * p[n];
  1940. }
  1941. ComputeNormals(ibase, m_indices.Count() - ibase);
  1942. }
  1943. //-----------------------------------------------------------------------------
  1944. void EasyMesh::Chamfer(float f)
  1945. {
  1946. int vlen = m_vert.Count() - m_cursors.Last().m1;
  1947. int ilen = m_indices.Count() - m_cursors.Last().m2;
  1948. /* Step 1: enumerate all faces. This is done by merging triangles
  1949. * that are coplanar and share an edge. */
  1950. int *triangle_classes = new int[ilen / 3];
  1951. for (int i = 0; i < ilen / 3; i++)
  1952. triangle_classes[i] = -1;
  1953. for (int i = 0; i < ilen / 3; i++)
  1954. {
  1955. }
  1956. /* Fun shit: reduce all triangles */
  1957. int *vertices = new int[vlen];
  1958. memset(vertices, 0, vlen * sizeof(int));
  1959. for (int i = 0; i < ilen; i++)
  1960. vertices[m_indices[i]]++;
  1961. for (int i = 0; i < ilen / 3; i++)
  1962. {
  1963. #if 0
  1964. if (vertices[m_indices[i * 3]] > 1)
  1965. continue;
  1966. if (vertices[m_indices[i * 3 + 1]] > 1)
  1967. continue;
  1968. if (vertices[m_indices[i * 3 + 2]] > 1)
  1969. continue;
  1970. #endif
  1971. vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m_coord +
  1972. m_vert[m_indices[i * 3 + 1]].m_coord +
  1973. m_vert[m_indices[i * 3 + 2]].m_coord);
  1974. for (int k = 0; k < 3; k++)
  1975. {
  1976. vec3 &p = m_vert[m_indices[i * 3 + k]].m_coord;
  1977. p -= normalize(p - bary) * f;
  1978. }
  1979. }
  1980. }
  1981. //-----------------------------------------------------------------------------
  1982. void EasyMesh::SplitTriangles(int pass) { SplitTriangles(pass, NULL); }
  1983. //-----------------------------------------------------------------------------
  1984. void EasyMesh::SplitTriangles(int pass, VertexDictionnary *vert_dict)
  1985. {
  1986. while (pass--)
  1987. {
  1988. int trimax = m_indices.Count();
  1989. for (int i = m_cursors.Last().m2; i < trimax; i += 3)
  1990. {
  1991. int vbase = m_vert.Count();
  1992. int j = -1;
  1993. while (++j < 3)
  1994. {
  1995. AddLerpVertex(m_indices[i + j], m_indices[i + (j + 1) % 3], .5f);
  1996. if (vert_dict)
  1997. vert_dict->AddVertex(vbase + j, m_vert[vbase + j].m_coord);
  1998. }
  1999. //Add new triangles
  2000. AppendTriangle(vbase, m_indices[i + 1], vbase + 1, 0);
  2001. AppendTriangle(vbase + 2, vbase + 1, m_indices[i + 2], 0);
  2002. AppendTriangle(vbase, vbase + 1, vbase + 2, 0);
  2003. //Change current triangle
  2004. m_indices[i + 1] = vbase;
  2005. m_indices[i + 2] = vbase + 2;
  2006. }
  2007. }
  2008. ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
  2009. }
  2010. //-----------------------------------------------------------------------------
  2011. //TODO : Add an half-edges implementation to refine smooth.
  2012. //TODO : Smooth should only use connected vertices that are on edges of the mesh (See box).
  2013. void EasyMesh::SmoothMesh(int main_pass, int split_per_main_pass, int smooth_per_main_pass)
  2014. {
  2015. VertexDictionnary vert_dict;
  2016. Array<vec3> smooth_buf[2];
  2017. Array<int> master_list;
  2018. Array<int> matching_ids;
  2019. Array<int> connected_vert;
  2020. int smbuf = 0;
  2021. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  2022. vert_dict.AddVertex(i, m_vert[i].m_coord);
  2023. while (main_pass--)
  2024. {
  2025. int split_pass = split_per_main_pass;
  2026. int smooth_pass = smooth_per_main_pass;
  2027. SplitTriangles(split_pass, &vert_dict);
  2028. matching_ids.Reserve(m_vert.Count() - m_cursors.Last().m1);
  2029. connected_vert.Reserve(m_vert.Count() - m_cursors.Last().m1);
  2030. smooth_buf[0].Resize(m_vert.Count() - m_cursors.Last().m1);
  2031. smooth_buf[1].Resize(m_vert.Count() - m_cursors.Last().m1);
  2032. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  2033. smooth_buf[smbuf][i - m_cursors.Last().m1] = m_vert[i].m_coord;
  2034. while (smooth_pass--)
  2035. {
  2036. master_list.Empty();
  2037. if (vert_dict.GetMasterList(master_list))
  2038. {
  2039. for (int i = 0; i < master_list.Count(); i++)
  2040. {
  2041. connected_vert.Empty();
  2042. if (vert_dict.FindConnectedVertices(master_list[i], m_indices, m_cursors.Last().m2, connected_vert))
  2043. {
  2044. //Calculate vertices sum
  2045. vec3 vert_sum = vec3(.0f);
  2046. for (int j = 0; j < connected_vert.Count(); j++)
  2047. vert_sum += smooth_buf[smbuf][connected_vert[j] - m_cursors.Last().m1];
  2048. //Calculate new master vertex
  2049. float n = (float)connected_vert.Count();
  2050. //b(n) = 5/4 - pow(3 + 2 * cos(2 * M_PI / n), 2) / 32
  2051. float beta = 3.f + 2.f * cos(2.f * (float)M_PI / n);
  2052. beta = 5.f / 4.f - beta * beta / 32.f;
  2053. //a(n) = n * (1 - b(n)) / b(n)
  2054. float alpha = (n * (1 - beta)) / beta;
  2055. //V = (a(n) * v + v1 + ... + vn) / (a(n) + n)
  2056. vec3 new_vert = (alpha * smooth_buf[smbuf][master_list[i] - m_cursors.Last().m1] + vert_sum) / (alpha + n);
  2057. //Set all matching vertices to new value
  2058. matching_ids.Empty();
  2059. matching_ids << master_list[i];
  2060. vert_dict.FindMatchingVertices(master_list[i], matching_ids);
  2061. for (int j = 0; j < matching_ids.Count(); j++)
  2062. smooth_buf[1 - smbuf][matching_ids[j] - m_cursors.Last().m1] = new_vert;
  2063. }
  2064. }
  2065. }
  2066. smbuf = 1 - smbuf;
  2067. }
  2068. for (int i = 0; i < smooth_buf[smbuf].Count(); i++)
  2069. m_vert[i + m_cursors.Last().m1].m_coord = smooth_buf[smbuf][i];
  2070. }
  2071. }
  2072. } /* namespace lol */