source: trunk/src/easymesh/easymesh.cpp @ 1879

Last change on this file since 1879 was 1879, checked in by sam, 8 years ago

easymesh: minor torus mesh tweaks.

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