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

Last change on this file since 1793 was 1793, checked in by elliotek, 8 years ago

optim radialJitter

File size: 23.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::AppendBox(vec3 const &size, float chamf)
512{
513    AppendBox(size, chamf, false);
514}
515
516void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
517{
518    AppendBox(size, chamf, true);
519}
520
521void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
522{
523    AppendBox(size, chamf, false);
524}
525
526void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
527{
528    if (chamf < 0.0f)
529    {
530        AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
531        return;
532    }
533
534    int vbase = m_vert.Count();
535    int ibase = m_indices.Count();
536
537    vec3 d = size * 0.5f;
538
539    AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
540    AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
541    AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
542    AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
543
544    AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
545    AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
546    AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
547    AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
548
549    AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
550    AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
551    AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
552    AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
553
554    AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
555    AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
556    AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
557    AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
558
559    AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
560    AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
561    AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
562    AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
563
564    AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
565    AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
566    AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
567    AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
568
569    /* The 6 quads on each side of the box */
570    for (int i = 0; i < 24; i += 4)
571        AppendQuad(i, i + 1, i + 2, i + 3, vbase);
572
573    ComputeNormals(ibase, m_indices.Count() - ibase);
574    ibase = m_indices.Count();
575
576    /* The 8 quads at each edge of the box */
577    if (chamf)
578    {
579        static int const quadlist[48] =
580        {
581            0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
582            2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
583            1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
584        };
585
586        for (int i = 0; i < 48; i += 4)
587        {
588            if (smooth)
589                AppendQuad(quadlist[i], quadlist[i + 1],
590                           quadlist[i + 2], quadlist[i + 3], vbase);
591            else
592                AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
593                                 quadlist[i + 2], quadlist[i + 3], vbase);
594        }
595    }
596
597    /* The 8 triangles at each corner of the box */
598    if (chamf)
599    {
600        static int const trilist[24] =
601        {
602            3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
603            2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
604        };
605
606        for (int i = 0; i < 24; i += 3)
607        {
608            if (smooth)
609                AppendTriangle(trilist[i], trilist[i + 1],
610                               trilist[i + 2], vbase);
611            else
612                AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
613                                             trilist[i + 2], vbase);
614        }
615    }
616
617    if (!smooth)
618        ComputeNormals(ibase, m_indices.Count() - ibase);
619}
620
621void EasyMesh::AppendStar(int nbranches, float r1, float r2,
622                          int fade, int fade2)
623{
624    int vbase = m_vert.Count();
625
626    AddVertex(vec3(0.f, 0.f, 0.f));
627
628    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
629    vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
630
631    p2 = rotmat * p2;
632    rotmat = rotmat * rotmat;
633
634    for (int i = 0; i < nbranches; i++)
635    {
636        AddVertex(p1);
637        if (fade2)
638            SetCurVertColor(m_color2);
639
640        AddVertex(p2);
641        if (fade)
642            SetCurVertColor(m_color2);
643
644        AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
645                   vbase);
646
647        p1 = rotmat * p1;
648        p2 = rotmat * p2;
649    }
650}
651
652void EasyMesh::AppendExpandedStar(int nbranches, float r1,
653                                  float r2, float extrar)
654{
655    int vbase = m_vert.Count();
656
657    AddVertex(vec3(0.f, 0.f, 0.f));
658
659    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
660    vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
661         p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
662
663    p2 = rotmat * p2;
664    p4 = rotmat * p4;
665    rotmat = rotmat * rotmat;
666
667    for (int i = 0; i < nbranches; i++)
668    {
669        AddVertex(p1);
670        AddVertex(p2);
671        AddVertex(p3); SetCurVertColor(m_color2);
672        AddVertex(p4); SetCurVertColor(m_color2);
673
674        int j = (i + 1) % nbranches;
675        AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
676        AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
677        AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
678
679        p1 = rotmat * p1;
680        p2 = rotmat * p2;
681        p3 = rotmat * p3;
682        p4 = rotmat * p4;
683    }
684}
685
686void EasyMesh::AppendDisc(int nsides, float r, int fade)
687{
688    int vbase = m_vert.Count();
689
690    AddVertex(vec3(0.f, 0.f, 0.f));
691
692    mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
693    vec3 p1(r, 0.f, 0.f);
694
695    for (int i = 0; i < nsides; i++)
696    {
697        AddVertex(p1);
698        if (fade)
699            SetCurVertColor(m_color2);
700        AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
701        p1 = rotmat * p1;
702    }
703}
704
705void EasyMesh::AppendSimpleTriangle(float size, int fade)
706{
707    mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
708    vec3 p(0.f, 0.f, size);
709
710    AddVertex(p);
711    p = m * p;
712    AddVertex(p);
713    if (fade)
714        SetCurVertColor(m_color2);
715    p = m * p;
716    AddVertex(p);
717    if (fade)
718        SetCurVertColor(m_color2);
719
720    AppendTriangle(0, 1, 2, m_vert.Count() - 3);
721}
722
723void EasyMesh::AppendSimpleQuad(float size, int fade)
724{
725    AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
726}
727
728void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
729{
730    AddVertex(vec3(p2.x, z, -p1.y));
731    AddVertex(vec3(p2.x, z, -p2.y));
732    AddVertex(vec3(p1.x, z, -p2.y));
733    if (fade)
734        SetCurVertColor(m_color2);
735    AddVertex(vec3(p1.x, z, -p1.y));
736    if (fade)
737        SetCurVertColor(m_color2);
738
739    AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
740    ComputeNormals(m_indices.Count() - 6, 6);
741}
742
743void EasyMesh::AppendCog(int nbsides, float h, float r1, float r2, float r12,
744                         float r22, float sidemul, int offset)
745{
746    int ibase = m_indices.Count();
747    int vbase = m_vert.Count();
748
749    AddVertex(vec3(0.f, h * .5f, 0.f));
750    AddVertex(vec3(0.f, h * -.5f, 0.f));
751    SetCurVertColor(m_color2);
752
753    mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
754    mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
755    mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
756
757    vec3 p[8];
758
759    p[0] = vec3(r1, h * .5f, 0.f);
760    p[1] = rotmat * p[0];
761    p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
762    p[3] = smat2 * (rotmat * p[2]);
763
764    p[4] = vec3(r2, h * -.5f, 0.f);
765    p[5] = rotmat * p[4];
766    p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
767    p[7] = smat2 * (rotmat * p[6]);
768
769    if (offset & 1)
770        for (int n = 0; n < 8; n++)
771            p[n] = rotmat * p[n];
772
773    rotmat = rotmat * rotmat;
774
775    for (int i = 0; i < nbsides; i++)
776    {
777        /* Each vertex will share three faces, so three different
778         * normals, therefore we add each vertex three times. */
779        for (int n = 0; n < 24; n++)
780        {
781            AddVertex(p[n / 3]);
782            if (n / 3 >= 4)
783                SetCurVertColor(m_color2);
784        }
785
786        int j = 24 * i, k = 24 * ((i + 1) % nbsides);
787
788        /* The top and bottom faces */
789        AppendQuad(0, j + 2, j + 5, k + 2, vbase);
790        AppendQuad(1, k + 14, j + 17, j + 14, vbase);
791        AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
792        AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
793
794        /* The side quads */
795        AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
796        AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
797        AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
798        AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
799
800        for (int n = 0; n < 8; n++)
801            p[n] = rotmat * p[n];
802    }
803
804    ComputeNormals(ibase, m_indices.Count() - ibase);
805}
806
807void EasyMesh::Chamfer(float f)
808{
809    int vlen = m_vert.Count() - m_cursors.Last().m1;
810    int ilen = m_indices.Count() - m_cursors.Last().m2;
811
812    /* Step 1: enumerate all faces. This is done by merging triangles
813     * that are coplanar and share an edge. */
814    int *triangle_classes = new int[ilen / 3];
815    for (int i = 0; i < ilen / 3; i++)
816        triangle_classes[i] = -1;
817
818    for (int i = 0; i < ilen / 3; i++)
819    {
820         
821    }
822
823    /* Fun shit: reduce all triangles */
824    int *vertices = new int[vlen];
825    memset(vertices, 0, vlen * sizeof(int));
826    for (int i = 0; i < ilen; i++)
827        vertices[m_indices[i]]++;
828
829    for (int i = 0; i < ilen / 3; i++)
830    {
831    #if 0
832        if (vertices[m_indices[i * 3]] > 1)
833            continue;
834        if (vertices[m_indices[i * 3 + 1]] > 1)
835            continue;
836        if (vertices[m_indices[i * 3 + 2]] > 1)
837            continue;
838    #endif
839
840        vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m1 +
841                                 m_vert[m_indices[i * 3 + 1]].m1 +
842                                 m_vert[m_indices[i * 3 + 2]].m1);
843        for (int k = 0; k < 3; k++)
844        {
845            vec3 &p = m_vert[m_indices[i * 3 + k]].m1;
846            p -= normalize(p - bary) * f;
847        }
848    }
849}
850
851} /* namespace lol */
852
Note: See TracBrowser for help on using the repository browser.