Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

893 Zeilen
25 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2012 Benjamin 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://sam.zoy.org/projects/COPYING.WTFPL 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. extern char const *lolfx_shiny;
  34. namespace lol
  35. {
  36. EasyMesh::EasyMesh()
  37. : m_color(0), m_color2(0), m_ignore_winding_on_scale(0)
  38. {
  39. m_cursors.Push(0, 0);
  40. }
  41. bool EasyMesh::Compile(char const *command)
  42. {
  43. EasyMeshCompiler mc(*this);
  44. return mc.ParseString(command);
  45. }
  46. void EasyMesh::OpenBrace()
  47. {
  48. m_cursors.Push(m_vert.Count(), m_indices.Count());
  49. }
  50. void EasyMesh::CloseBrace()
  51. {
  52. m_cursors.Pop();
  53. }
  54. void EasyMesh::MeshConvert()
  55. {
  56. m_gpu.shader = Shader::Create(lolfx_shiny);
  57. m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView");
  58. m_gpu.view = m_gpu.shader->GetUniformLocation("in_View");
  59. m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
  60. m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
  61. m_gpu.damage = m_gpu.shader->GetUniformLocation("in_Damage");
  62. m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
  63. VertexUsage::Position, 0);
  64. m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
  65. VertexUsage::Normal, 0);
  66. m_gpu.color = m_gpu.shader->GetAttribLocation("in_Color",
  67. VertexUsage::Color, 0);
  68. m_gpu.vdecl = new VertexDeclaration(
  69. VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
  70. VertexUsage::Normal,
  71. VertexUsage::Color));
  72. Array<vec3,vec3,u8vec4> vertexlist;
  73. for (int i = 0; i < m_vert.Count(); i++)
  74. vertexlist.Push(m_vert[i].m1,
  75. m_vert[i].m2,
  76. (u8vec4)(m_vert[i].m3 * 255.f));
  77. Array<uint16_t> indexlist;
  78. for (int i = 0; i < m_indices.Count(); i += 3)
  79. {
  80. indexlist << m_indices[i + 0];
  81. indexlist << m_indices[i + 1];
  82. indexlist << m_indices[i + 2];
  83. }
  84. m_gpu.vbo = new VertexBuffer(vertexlist.Bytes());
  85. void *mesh = m_gpu.vbo->Lock(0, 0);
  86. memcpy(mesh, &vertexlist[0], vertexlist.Bytes());
  87. m_gpu.vbo->Unlock();
  88. m_gpu.ibo = new IndexBuffer(indexlist.Bytes());
  89. void *indices = m_gpu.ibo->Lock(0, 0);
  90. memcpy(indices, &indexlist[0], indexlist.Bytes());
  91. m_gpu.ibo->Unlock();
  92. m_gpu.vertexcount = vertexlist.Count();
  93. m_gpu.indexcount = indexlist.Count();
  94. }
  95. void EasyMesh::Render(mat4 const &model, float damage)
  96. {
  97. mat4 modelview = Scene::GetDefault()->GetViewMatrix() * model;
  98. mat3 normalmat = transpose(inverse(mat3(modelview)));
  99. m_gpu.shader->Bind();
  100. m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
  101. m_gpu.shader->SetUniform(m_gpu.view, Scene::GetDefault()->GetViewMatrix());
  102. m_gpu.shader->SetUniform(m_gpu.proj, Scene::GetDefault()->GetProjMatrix());
  103. m_gpu.shader->SetUniform(m_gpu.normalmat, normalmat);
  104. m_gpu.shader->SetUniform(m_gpu.damage, damage);
  105. m_gpu.vdecl->Bind();
  106. m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord, m_gpu.norm, m_gpu.color);
  107. m_gpu.ibo->Bind();
  108. m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
  109. 0, 0, m_gpu.vertexcount,
  110. 0, m_gpu.indexcount);
  111. m_gpu.ibo->Unbind();
  112. m_gpu.vdecl->Unbind();
  113. }
  114. void EasyMesh::ToggleScaleWinding()
  115. {
  116. m_ignore_winding_on_scale = !m_ignore_winding_on_scale;
  117. }
  118. void EasyMesh::SetCurColor(vec4 const &color)
  119. {
  120. m_color = color;
  121. }
  122. void EasyMesh::SetCurColor2(vec4 const &color)
  123. {
  124. m_color2 = color;
  125. }
  126. void EasyMesh::AddVertex(vec3 const &coord)
  127. {
  128. m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color);
  129. }
  130. void EasyMesh::AddDuplicateVertex(int i)
  131. {
  132. m_vert.Push(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3);
  133. }
  134. void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
  135. {
  136. m_indices << base + i1;
  137. m_indices << base + i2;
  138. m_indices << base + i3;
  139. m_indices << base + i4;
  140. m_indices << base + i1;
  141. m_indices << base + i3;
  142. }
  143. void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
  144. {
  145. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  146. m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
  147. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  148. m_indices << m_vert.Count(); AddDuplicateVertex(base + i4);
  149. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  150. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  151. }
  152. void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
  153. {
  154. m_indices << base + i1;
  155. m_indices << base + i2;
  156. m_indices << base + i3;
  157. }
  158. void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
  159. {
  160. m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
  161. m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
  162. m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
  163. }
  164. void EasyMesh::ComputeNormals(int start, int vcount)
  165. {
  166. for (int i = 0; i < vcount; i += 3)
  167. {
  168. vec3 v0 = m_vert[m_indices[start + i + 2]].m1
  169. - m_vert[m_indices[start + i + 0]].m1;
  170. vec3 v1 = m_vert[m_indices[start + i + 1]].m1
  171. - m_vert[m_indices[start + i + 0]].m1;
  172. vec3 n = normalize(cross(v1, v0));
  173. for (int j = 0; j < 3; j++)
  174. m_vert[m_indices[start + i + j]].m2 = n;
  175. }
  176. }
  177. void EasyMesh::SetVertColor(vec4 const &color)
  178. {
  179. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  180. m_vert[i].m3 = color;
  181. }
  182. void EasyMesh::SetCurVertNormal(vec3 const &normal)
  183. {
  184. m_vert[m_vert.Count() - 1].m2 = normal;
  185. }
  186. void EasyMesh::SetCurVertColor(vec4 const &color)
  187. {
  188. m_vert[m_vert.Count() - 1].m3 = color;
  189. }
  190. void EasyMesh::Translate(vec3 const &v)
  191. {
  192. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  193. m_vert[i].m1 += v;
  194. }
  195. void EasyMesh::RotateX(float t) { Rotate(t, vec3(1, 0, 0)); }
  196. void EasyMesh::RotateY(float t) { Rotate(t, vec3(0, 1, 0)); }
  197. void EasyMesh::RotateZ(float t) { Rotate(t, vec3(0, 0, 1)); }
  198. void EasyMesh::Rotate(float t, vec3 const &axis)
  199. {
  200. mat3 m = mat3::rotate(t, axis);
  201. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  202. {
  203. m_vert[i].m1 = m * m_vert[i].m1;
  204. m_vert[i].m2 = m * m_vert[i].m2;
  205. }
  206. }
  207. void EasyMesh::RadialJitter(float r)
  208. {
  209. Array<int> Welded;
  210. Welded.Push(-1);
  211. for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++)
  212. {
  213. int j, k;
  214. for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++)
  215. {
  216. if(Welded[k] < 0)
  217. {
  218. vec3 diff = m_vert[i].m1 - m_vert[j].m1;
  219. if(diff.x > 0.1f || diff.x < -0.1f)
  220. continue;
  221. if(diff.y > 0.1f || diff.y < -0.1f)
  222. continue;
  223. if(diff.z > 0.1f || diff.z < -0.1f)
  224. continue;
  225. break;
  226. }
  227. }
  228. if(j == i)
  229. Welded.Push(-1);
  230. else
  231. Welded.Push(j);
  232. }
  233. int i, j;
  234. for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++)
  235. {
  236. if(Welded[j] == -1)
  237. m_vert[i].m1 *= 1.0f + RandF(r);
  238. else
  239. m_vert[i].m1 = m_vert[Welded[j]].m1;
  240. }
  241. ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
  242. }
  243. void EasyMesh::TaperX(float y, float z, float xoff)
  244. {
  245. /* FIXME: this code breaks normals! */
  246. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  247. {
  248. m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
  249. m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
  250. }
  251. }
  252. void EasyMesh::TaperY(float x, float z, float yoff)
  253. {
  254. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  255. {
  256. m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
  257. m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
  258. }
  259. }
  260. void EasyMesh::TaperZ(float x, float y, float zoff)
  261. {
  262. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  263. {
  264. m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
  265. m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
  266. }
  267. }
  268. void EasyMesh::Scale(vec3 const &s)
  269. {
  270. vec3 const invs = vec3(1) / s;
  271. for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
  272. {
  273. m_vert[i].m1 *= s;
  274. m_vert[i].m2 = normalize(m_vert[i].m2 * invs);
  275. }
  276. /* Flip winding if the scaling involves mirroring */
  277. if (!m_ignore_winding_on_scale && s.x * s.y * s.z < 0)
  278. {
  279. for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3)
  280. {
  281. uint16_t tmp = m_indices[i + 0];
  282. m_indices[i + 0] = m_indices[i + 1];
  283. m_indices[i + 1] = tmp;
  284. }
  285. }
  286. }
  287. void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
  288. void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
  289. void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
  290. void EasyMesh::DupAndScale(vec3 const &s)
  291. {
  292. int vlen = m_vert.Count() - m_cursors.Last().m1;
  293. int tlen = m_indices.Count() - m_cursors.Last().m2;
  294. for (int i = 0; i < vlen; i++)
  295. m_vert << m_vert[m_cursors.Last().m1++];
  296. for (int i = 0; i < tlen; i++)
  297. m_indices << m_indices[m_cursors.Last().m2++] + vlen;
  298. Scale(s);
  299. m_cursors.Last().m1 -= vlen;
  300. m_cursors.Last().m2 -= tlen;
  301. }
  302. void EasyMesh::AppendCylinder(int nsides, float h, float r1, float r2,
  303. int dualside, int smooth)
  304. {
  305. int vbase = m_vert.Count();
  306. mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
  307. vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
  308. /* Construct normal */
  309. if (r2 != .0f)
  310. n = vec3(r2, h * .5f, 0.f);
  311. else
  312. n = vec3(r1, h * .5f, 0.f);
  313. n.y = r1 * (r1 - r2) / h;
  314. if (!smooth)
  315. n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
  316. n = normalize(n);
  317. /* FIXME: normals should be flipped in two-sided mode, but that
  318. * means duplicating the vertices again... */
  319. for (int i = 0; i < nsides; i++)
  320. {
  321. AddVertex(p1); SetCurVertNormal(n);
  322. AddVertex(p2); SetCurVertNormal(n);
  323. SetCurVertColor(m_color2);
  324. if (smooth)
  325. {
  326. int j = (i + 1) % nsides;
  327. AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
  328. if (dualside)
  329. AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
  330. }
  331. p1 = rotmat * p1;
  332. p2 = rotmat * p2;
  333. if (!smooth)
  334. {
  335. AddVertex(p1); SetCurVertNormal(n);
  336. AddVertex(p2); SetCurVertNormal(n);
  337. SetCurVertColor(m_color2);
  338. AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
  339. if (dualside)
  340. AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
  341. }
  342. n = rotmat * n;
  343. }
  344. }
  345. void EasyMesh::AppendCapsule(int ndivisions, float h, float r)
  346. {
  347. int ibase = m_indices.Count();
  348. Array<vec3> vertices;
  349. /* FIXME: we don't know how to handle even-divided capsules, so we
  350. * force the count to be odd. */
  351. if (h)
  352. ndivisions |= 1;
  353. /* Fill in the icosahedron vertices, rotating them so that there
  354. * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */
  355. float phi = 0.5f + 0.5f * sqrt(5.f);
  356. mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / M_PI),
  357. vec3(0.f, 0.f, 1.f));
  358. for (int i = 0; i < 4; i++)
  359. {
  360. float x = (i & 1) ? 0.5f : -0.5f;
  361. float y = (i & 2) ? phi * 0.5f : phi * -0.5f;
  362. vertices << mat * vec3(x, y, 0.f);
  363. vertices << mat * vec3(0.f, x, y);
  364. vertices << mat * vec3(y, 0.f, x);
  365. }
  366. static int const trilist[] =
  367. {
  368. 0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8,
  369. 7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11,
  370. 0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1,
  371. 2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6,
  372. 7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8
  373. };
  374. for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3)
  375. {
  376. vec3 const &a = vertices[trilist[i]];
  377. vec3 const &b = vertices[trilist[i + 1]];
  378. vec3 const &c = vertices[trilist[i + 2]];
  379. vec3 const vb = 1.f / ndivisions * (b - a);
  380. vec3 const vc = 1.f / ndivisions * (c - a);
  381. int line = ndivisions + 1;
  382. for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++)
  383. {
  384. vec3 p[] = { a + x * vb + y * vc,
  385. p[0] + vb,
  386. p[0] + vc,
  387. p[0] + vb + vc };
  388. /* FIXME: when we normalise here, we get a volume that is slightly
  389. * smaller than the sphere of radius 1, since we are not using
  390. * the midradius. */
  391. for (int k = 0; k < 4; k++)
  392. p[k] = normalize(p[k]) * r;
  393. /* If this is a capsule, grow in the Z direction */
  394. if (h > 0.f)
  395. {
  396. for (int k = 0; k < 4; k++)
  397. p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h;
  398. }
  399. /* Add zero, one or two triangles */
  400. if (y < line - 1)
  401. {
  402. AddVertex(p[0]);
  403. AddVertex(p[1]);
  404. AddVertex(p[2]);
  405. AppendTriangle(0, 2, 1, m_vert.Count() - 3);
  406. }
  407. if (y < line - 2)
  408. {
  409. AddVertex(p[1]);
  410. AddVertex(p[3]);
  411. AddVertex(p[2]);
  412. AppendTriangle(0, 2, 1, m_vert.Count() - 3);
  413. }
  414. y++;
  415. if (y == line)
  416. {
  417. x++;
  418. y = 0;
  419. line--;
  420. }
  421. }
  422. }
  423. ComputeNormals(ibase, m_indices.Count() - ibase);
  424. }
  425. void EasyMesh::AppendSphere(int ndivisions, vec3 const &size)
  426. {
  427. OpenBrace();
  428. AppendCapsule(ndivisions, 0.f, 1.f);
  429. Scale(size);
  430. CloseBrace();
  431. }
  432. void EasyMesh::AppendTorus(int ndivisions, float r1, float r2)
  433. {
  434. int ibase = m_indices.Count();
  435. int nidiv = ndivisions; /* Cross-section */
  436. int njdiv = ndivisions; /* Full circumference */
  437. for (int j = 0; j < njdiv; j++)
  438. for (int i = 0; i < 2 * nidiv; i++)
  439. {
  440. for (int di = 0; di < 2; di++)
  441. for (int dj = 0; dj < 2; dj++)
  442. {
  443. int i2 = (i + di) % nidiv;
  444. int j2 = (j + dj) % njdiv;
  445. float x = 0.5f * (r1 + r2) + 0.5 * (r2 - r1) * lol::cos(2.0 * M_PI * i2 / nidiv);
  446. float y = 0.5f * (r2 - r1) * lol::sin(2.0 * M_PI * i2 / nidiv);
  447. float z = 0.0f;
  448. float ca = lol::cos(2.0 * M_PI * j2 / njdiv);
  449. float sa = lol::sin(2.0 * M_PI * j2 / njdiv);
  450. float x2 = x * ca - z * sa;
  451. float z2 = z * ca + x * sa;
  452. AddVertex(vec3(x2, y, z2));
  453. }
  454. AppendTriangle(0, 2, 3, m_vert.Count() - 4);
  455. AppendTriangle(0, 3, 1, m_vert.Count() - 4);
  456. }
  457. ComputeNormals(ibase, m_indices.Count() - ibase);
  458. }
  459. void EasyMesh::AppendBox(vec3 const &size, float chamf)
  460. {
  461. AppendBox(size, chamf, false);
  462. }
  463. void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
  464. {
  465. AppendBox(size, chamf, true);
  466. }
  467. void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
  468. {
  469. AppendBox(size, chamf, false);
  470. }
  471. void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
  472. {
  473. if (chamf < 0.0f)
  474. {
  475. AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
  476. return;
  477. }
  478. int vbase = m_vert.Count();
  479. int ibase = m_indices.Count();
  480. vec3 d = size * 0.5f;
  481. AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
  482. AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
  483. AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
  484. AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
  485. AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
  486. AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
  487. AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
  488. AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
  489. AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
  490. AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
  491. AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
  492. AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
  493. AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
  494. AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
  495. AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
  496. AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
  497. AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
  498. AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
  499. AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
  500. AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
  501. AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
  502. AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
  503. AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
  504. AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
  505. /* The 6 quads on each side of the box */
  506. for (int i = 0; i < 24; i += 4)
  507. AppendQuad(i, i + 1, i + 2, i + 3, vbase);
  508. ComputeNormals(ibase, m_indices.Count() - ibase);
  509. ibase = m_indices.Count();
  510. /* The 8 quads at each edge of the box */
  511. if (chamf)
  512. {
  513. static int const quadlist[48] =
  514. {
  515. 0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
  516. 2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
  517. 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
  518. };
  519. for (int i = 0; i < 48; i += 4)
  520. {
  521. if (smooth)
  522. AppendQuad(quadlist[i], quadlist[i + 1],
  523. quadlist[i + 2], quadlist[i + 3], vbase);
  524. else
  525. AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
  526. quadlist[i + 2], quadlist[i + 3], vbase);
  527. }
  528. }
  529. /* The 8 triangles at each corner of the box */
  530. if (chamf)
  531. {
  532. static int const trilist[24] =
  533. {
  534. 3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
  535. 2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
  536. };
  537. for (int i = 0; i < 24; i += 3)
  538. {
  539. if (smooth)
  540. AppendTriangle(trilist[i], trilist[i + 1],
  541. trilist[i + 2], vbase);
  542. else
  543. AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
  544. trilist[i + 2], vbase);
  545. }
  546. }
  547. if (!smooth)
  548. ComputeNormals(ibase, m_indices.Count() - ibase);
  549. }
  550. void EasyMesh::AppendStar(int nbranches, float r1, float r2,
  551. int fade, int fade2)
  552. {
  553. int vbase = m_vert.Count();
  554. AddVertex(vec3(0.f, 0.f, 0.f));
  555. mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
  556. vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
  557. p2 = rotmat * p2;
  558. rotmat = rotmat * rotmat;
  559. for (int i = 0; i < nbranches; i++)
  560. {
  561. AddVertex(p1);
  562. if (fade2)
  563. SetCurVertColor(m_color2);
  564. AddVertex(p2);
  565. if (fade)
  566. SetCurVertColor(m_color2);
  567. AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
  568. vbase);
  569. p1 = rotmat * p1;
  570. p2 = rotmat * p2;
  571. }
  572. }
  573. void EasyMesh::AppendExpandedStar(int nbranches, float r1,
  574. float r2, float extrar)
  575. {
  576. int vbase = m_vert.Count();
  577. AddVertex(vec3(0.f, 0.f, 0.f));
  578. mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
  579. vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
  580. p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
  581. p2 = rotmat * p2;
  582. p4 = rotmat * p4;
  583. rotmat = rotmat * rotmat;
  584. for (int i = 0; i < nbranches; i++)
  585. {
  586. AddVertex(p1);
  587. AddVertex(p2);
  588. AddVertex(p3); SetCurVertColor(m_color2);
  589. AddVertex(p4); SetCurVertColor(m_color2);
  590. int j = (i + 1) % nbranches;
  591. AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
  592. AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
  593. AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
  594. p1 = rotmat * p1;
  595. p2 = rotmat * p2;
  596. p3 = rotmat * p3;
  597. p4 = rotmat * p4;
  598. }
  599. }
  600. void EasyMesh::AppendDisc(int nsides, float r, int fade)
  601. {
  602. int vbase = m_vert.Count();
  603. AddVertex(vec3(0.f, 0.f, 0.f));
  604. mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
  605. vec3 p1(r, 0.f, 0.f);
  606. for (int i = 0; i < nsides; i++)
  607. {
  608. AddVertex(p1);
  609. if (fade)
  610. SetCurVertColor(m_color2);
  611. AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
  612. p1 = rotmat * p1;
  613. }
  614. }
  615. void EasyMesh::AppendSimpleTriangle(float size, int fade)
  616. {
  617. mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
  618. vec3 p(0.f, 0.f, size);
  619. AddVertex(p);
  620. p = m * p;
  621. AddVertex(p);
  622. if (fade)
  623. SetCurVertColor(m_color2);
  624. p = m * p;
  625. AddVertex(p);
  626. if (fade)
  627. SetCurVertColor(m_color2);
  628. AppendTriangle(0, 1, 2, m_vert.Count() - 3);
  629. }
  630. void EasyMesh::AppendSimpleQuad(float size, int fade)
  631. {
  632. AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
  633. }
  634. void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
  635. {
  636. AddVertex(vec3(p2.x, z, -p1.y));
  637. AddVertex(vec3(p2.x, z, -p2.y));
  638. AddVertex(vec3(p1.x, z, -p2.y));
  639. if (fade)
  640. SetCurVertColor(m_color2);
  641. AddVertex(vec3(p1.x, z, -p1.y));
  642. if (fade)
  643. SetCurVertColor(m_color2);
  644. AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
  645. ComputeNormals(m_indices.Count() - 6, 6);
  646. }
  647. void EasyMesh::AppendCog(int nbsides, float h, float r1, float r2, float r12,
  648. float r22, float sidemul, int offset)
  649. {
  650. int ibase = m_indices.Count();
  651. int vbase = m_vert.Count();
  652. AddVertex(vec3(0.f, h * .5f, 0.f));
  653. AddVertex(vec3(0.f, h * -.5f, 0.f));
  654. SetCurVertColor(m_color2);
  655. mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
  656. mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
  657. mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
  658. vec3 p[8];
  659. p[0] = vec3(r1, h * .5f, 0.f);
  660. p[1] = rotmat * p[0];
  661. p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
  662. p[3] = smat2 * (rotmat * p[2]);
  663. p[4] = vec3(r2, h * -.5f, 0.f);
  664. p[5] = rotmat * p[4];
  665. p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
  666. p[7] = smat2 * (rotmat * p[6]);
  667. if (offset & 1)
  668. for (int n = 0; n < 8; n++)
  669. p[n] = rotmat * p[n];
  670. rotmat = rotmat * rotmat;
  671. for (int i = 0; i < nbsides; i++)
  672. {
  673. /* Each vertex will share three faces, so three different
  674. * normals, therefore we add each vertex three times. */
  675. for (int n = 0; n < 24; n++)
  676. {
  677. AddVertex(p[n / 3]);
  678. if (n / 3 >= 4)
  679. SetCurVertColor(m_color2);
  680. }
  681. int j = 24 * i, k = 24 * ((i + 1) % nbsides);
  682. /* The top and bottom faces */
  683. AppendQuad(0, j + 2, j + 5, k + 2, vbase);
  684. AppendQuad(1, k + 14, j + 17, j + 14, vbase);
  685. AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
  686. AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
  687. /* The side quads */
  688. AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
  689. AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
  690. AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
  691. AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
  692. for (int n = 0; n < 8; n++)
  693. p[n] = rotmat * p[n];
  694. }
  695. ComputeNormals(ibase, m_indices.Count() - ibase);
  696. }
  697. void EasyMesh::Chamfer(float f)
  698. {
  699. int vlen = m_vert.Count() - m_cursors.Last().m1;
  700. int ilen = m_indices.Count() - m_cursors.Last().m2;
  701. /* Step 1: enumerate all faces. This is done by merging triangles
  702. * that are coplanar and share an edge. */
  703. int *triangle_classes = new int[ilen / 3];
  704. for (int i = 0; i < ilen / 3; i++)
  705. triangle_classes[i] = -1;
  706. for (int i = 0; i < ilen / 3; i++)
  707. {
  708. }
  709. /* Fun shit: reduce all triangles */
  710. int *vertices = new int[vlen];
  711. memset(vertices, 0, vlen * sizeof(int));
  712. for (int i = 0; i < ilen; i++)
  713. vertices[m_indices[i]]++;
  714. for (int i = 0; i < ilen / 3; i++)
  715. {
  716. #if 0
  717. if (vertices[m_indices[i * 3]] > 1)
  718. continue;
  719. if (vertices[m_indices[i * 3 + 1]] > 1)
  720. continue;
  721. if (vertices[m_indices[i * 3 + 2]] > 1)
  722. continue;
  723. #endif
  724. vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m1 +
  725. m_vert[m_indices[i * 3 + 1]].m1 +
  726. m_vert[m_indices[i * 3 + 2]].m1);
  727. for (int k = 0; k < 3; k++)
  728. {
  729. vec3 &p = m_vert[m_indices[i * 3 + k]].m1;
  730. p -= normalize(p - bary) * f;
  731. }
  732. }
  733. }
  734. } /* namespace lol */