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

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