You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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