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

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

EsayMesh : RadialJitter func & demo added

File size: 23.3 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;
247                for (j = m_cursors.Last().m1; j < i; j++)
248                {
249                        if(sqlength(m_vert[i].m1 - m_vert[j].m1) < 0.1f)
250                                break;
251                }
252
253                if(j == i)
254                        Welded.Push(-1);
255                else
256                        Welded.Push(j);
257        }
258
259        int i, j;
260    for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++)
261        {
262                if(Welded[j] == -1)
263                        m_vert[i].m1 *= 1.0f + RandF(r);
264                else
265                        m_vert[i].m1 = m_vert[Welded[j]].m1;
266        }
267
268        ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
269}
270
271void EasyMesh::TaperX(float y, float z, float xoff)
272{
273    /* FIXME: this code breaks normals! */
274    for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
275    {
276        m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
277        m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
278    }
279}
280
281void EasyMesh::TaperY(float x, float z, float yoff)
282{
283    for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
284    {
285        m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
286        m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
287    }
288}
289
290void EasyMesh::TaperZ(float x, float y, float zoff)
291{
292    for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
293    {
294        m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
295        m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
296    }
297}
298
299void EasyMesh::Scale(vec3 const &s)
300{
301    vec3 const invs = vec3(1) / s;
302
303    for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
304    {
305        m_vert[i].m1 *= s;
306        m_vert[i].m2 = normalize(m_vert[i].m2 * invs);
307    }
308
309    /* Flip winding if the scaling involves mirroring */
310    if (s.x * s.y * s.z < 0)
311    {
312        for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3)
313        {
314            uint16_t tmp = m_indices[i + 0];
315            m_indices[i + 0] = m_indices[i + 1];
316            m_indices[i + 1] = tmp;
317        }
318    }
319}
320
321void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
322void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
323void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
324
325void EasyMesh::DupAndScale(vec3 const &s)
326{
327    int vlen = m_vert.Count() - m_cursors.Last().m1;
328    int tlen = m_indices.Count() - m_cursors.Last().m2;
329
330    for (int i = 0; i < vlen; i++)
331        m_vert << m_vert[m_cursors.Last().m1++];
332
333    for (int i = 0; i < tlen; i++)
334        m_indices << m_indices[m_cursors.Last().m2++] + vlen;
335
336    Scale(s);
337
338    m_cursors.Last().m1 -= vlen;
339    m_cursors.Last().m2 -= tlen;
340}
341
342void EasyMesh::AppendCylinder(int nsides, float h, float r1, float r2,
343                    int dualside, int smooth)
344{
345    int vbase = m_vert.Count();
346
347    mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
348    vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
349
350    /* Construct normal */
351        if (r2 != .0f)
352                n = vec3(r2, h * .5f, 0.f);
353        else
354                n = vec3(r1, h * .5f, 0.f);
355    n.y = r1 * (r1 - r2) / h;
356    if (!smooth)
357        n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
358    n = normalize(n);
359
360    /* FIXME: normals should be flipped in two-sided mode, but that
361     * means duplicating the vertices again... */
362    for (int i = 0; i < nsides; i++)
363    {
364        AddVertex(p1); SetCurVertNormal(n);
365        AddVertex(p2); SetCurVertNormal(n);
366        SetCurVertColor(m_color2);
367
368        if (smooth)
369        {
370            int j = (i + 1) % nsides;
371            AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
372            if (dualside)
373                AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
374        }
375
376        p1 = rotmat * p1;
377        p2 = rotmat * p2;
378
379        if (!smooth)
380        {
381            AddVertex(p1); SetCurVertNormal(n);
382            AddVertex(p2); SetCurVertNormal(n);
383            SetCurVertColor(m_color2);
384
385            AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
386            if (dualside)
387                AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
388        }
389
390        n = rotmat * n;
391    }
392}
393
394void EasyMesh::AppendCapsule(int ndivisions, float h, float r)
395{
396    int ibase = m_indices.Count();
397
398    Array<vec3> vertices;
399
400    /* FIXME: we don't know how to handle even-divided capsules, so we
401     * force the count to be odd. */
402    if (h)
403        ndivisions |= 1;
404
405    /* Fill in the icosahedron vertices, rotating them so that there
406     * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */
407    float phi = 0.5f + 0.5f * sqrt(5.f);
408    mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / M_PI),
409                            vec3(0.f, 0.f, 1.f));
410    for (int i = 0; i < 4; i++)
411    {
412        float x = (i & 1) ? 0.5f : -0.5f;
413        float y = (i & 2) ? phi * 0.5f : phi * -0.5f;
414        vertices << mat * vec3(x, y, 0.f);
415        vertices << mat * vec3(0.f, x, y);
416        vertices << mat * vec3(y, 0.f, x);
417    }
418
419    static int const trilist[] =
420    {
421        0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8,
422        7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11,
423
424        0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1,
425        2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6,
426        7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8
427    };
428
429    for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3)
430    {
431        vec3 const &a = vertices[trilist[i]];
432        vec3 const &b = vertices[trilist[i + 1]];
433        vec3 const &c = vertices[trilist[i + 2]];
434
435        vec3 const vb = 1.f / ndivisions * (b - a);
436        vec3 const vc = 1.f / ndivisions * (c - a);
437
438        int line = ndivisions + 1;
439
440        for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++)
441        {
442            vec3 p[] = { a + x * vb + y * vc,
443                         p[0] + vb,
444                         p[0] + vc,
445                         p[0] + vb + vc };
446
447            /* FIXME: when we normalise here, we get a volume that is slightly
448             * smaller than the sphere of radius 1, since we are not using
449             * the midradius. */
450            for (int k = 0; k < 4; k++)
451                p[k] = normalize(p[k]) * r;
452
453            /* If this is a capsule, grow in the Z direction */
454            if (h > 0.f)
455            {
456                for (int k = 0; k < 4; k++)
457                    p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h;
458            }
459
460            /* Add zero, one or two triangles */
461            if (y < line - 1)
462            {
463                AddVertex(p[0]);
464                AddVertex(p[1]);
465                AddVertex(p[2]);
466                AppendTriangle(0, 2, 1, m_vert.Count() - 3);
467            }
468
469            if (y < line - 2)
470            {
471                AddVertex(p[1]);
472                AddVertex(p[3]);
473                AddVertex(p[2]);
474                AppendTriangle(0, 2, 1, m_vert.Count() - 3);
475            }
476
477            y++;
478            if (y == line)
479            {
480                x++;
481                y = 0;
482                line--;
483            }
484        }
485    }
486
487    ComputeNormals(ibase, m_indices.Count() - ibase);
488}
489
490void EasyMesh::AppendSphere(int ndivisions, vec3 const &size)
491{
492    OpenBrace();
493    AppendCapsule(ndivisions, 0.f, 1.f);
494    Scale(size);
495    CloseBrace();
496}
497
498void EasyMesh::AppendBox(vec3 const &size, float chamf)
499{
500    AppendBox(size, chamf, false);
501}
502
503void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
504{
505    AppendBox(size, chamf, true);
506}
507
508void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
509{
510    AppendBox(size, chamf, false);
511}
512
513void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
514{
515    if (chamf < 0.0f)
516    {
517        AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
518        return;
519    }
520
521    int vbase = m_vert.Count();
522    int ibase = m_indices.Count();
523
524    vec3 d = size * 0.5f;
525
526    AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
527    AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
528    AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
529    AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
530
531    AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
532    AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
533    AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
534    AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
535
536    AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
537    AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
538    AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
539    AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
540
541    AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
542    AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
543    AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
544    AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
545
546    AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
547    AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
548    AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
549    AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
550
551    AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
552    AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
553    AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
554    AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
555
556    /* The 6 quads on each side of the box */
557    for (int i = 0; i < 24; i += 4)
558        AppendQuad(i, i + 1, i + 2, i + 3, vbase);
559
560    ComputeNormals(ibase, m_indices.Count() - ibase);
561    ibase = m_indices.Count();
562
563    /* The 8 quads at each edge of the box */
564    if (chamf)
565    {
566        static int const quadlist[48] =
567        {
568            0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
569            2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
570            1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
571        };
572
573        for (int i = 0; i < 48; i += 4)
574        {
575            if (smooth)
576                AppendQuad(quadlist[i], quadlist[i + 1],
577                           quadlist[i + 2], quadlist[i + 3], vbase);
578            else
579                AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
580                                 quadlist[i + 2], quadlist[i + 3], vbase);
581        }
582    }
583
584    /* The 8 triangles at each corner of the box */
585    if (chamf)
586    {
587        static int const trilist[24] =
588        {
589            3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
590            2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
591        };
592
593        for (int i = 0; i < 24; i += 3)
594        {
595            if (smooth)
596                AppendTriangle(trilist[i], trilist[i + 1],
597                               trilist[i + 2], vbase);
598            else
599                AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
600                                             trilist[i + 2], vbase);
601        }
602    }
603
604    if (!smooth)
605        ComputeNormals(ibase, m_indices.Count() - ibase);
606}
607
608void EasyMesh::AppendStar(int nbranches, float r1, float r2,
609                          int fade, int fade2)
610{
611    int vbase = m_vert.Count();
612
613    AddVertex(vec3(0.f, 0.f, 0.f));
614
615    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
616    vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
617
618    p2 = rotmat * p2;
619    rotmat = rotmat * rotmat;
620
621    for (int i = 0; i < nbranches; i++)
622    {
623        AddVertex(p1);
624        if (fade2)
625            SetCurVertColor(m_color2);
626
627        AddVertex(p2);
628        if (fade)
629            SetCurVertColor(m_color2);
630
631        AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
632                   vbase);
633
634        p1 = rotmat * p1;
635        p2 = rotmat * p2;
636    }
637}
638
639void EasyMesh::AppendExpandedStar(int nbranches, float r1,
640                                  float r2, float extrar)
641{
642    int vbase = m_vert.Count();
643
644    AddVertex(vec3(0.f, 0.f, 0.f));
645
646    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
647    vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
648         p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
649
650    p2 = rotmat * p2;
651    p4 = rotmat * p4;
652    rotmat = rotmat * rotmat;
653
654    for (int i = 0; i < nbranches; i++)
655    {
656        AddVertex(p1);
657        AddVertex(p2);
658        AddVertex(p3); SetCurVertColor(m_color2);
659        AddVertex(p4); SetCurVertColor(m_color2);
660
661        int j = (i + 1) % nbranches;
662        AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
663        AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
664        AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
665
666        p1 = rotmat * p1;
667        p2 = rotmat * p2;
668        p3 = rotmat * p3;
669        p4 = rotmat * p4;
670    }
671}
672
673void EasyMesh::AppendDisc(int nsides, float r, int fade)
674{
675    int vbase = m_vert.Count();
676
677    AddVertex(vec3(0.f, 0.f, 0.f));
678
679    mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
680    vec3 p1(r, 0.f, 0.f);
681
682    for (int i = 0; i < nsides; i++)
683    {
684        AddVertex(p1);
685        if (fade)
686            SetCurVertColor(m_color2);
687        AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
688        p1 = rotmat * p1;
689    }
690}
691
692void EasyMesh::AppendSimpleTriangle(float size, int fade)
693{
694    mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
695    vec3 p(0.f, 0.f, size);
696
697    AddVertex(p);
698    p = m * p;
699    AddVertex(p);
700    if (fade)
701        SetCurVertColor(m_color2);
702    p = m * p;
703    AddVertex(p);
704    if (fade)
705        SetCurVertColor(m_color2);
706
707    AppendTriangle(0, 1, 2, m_vert.Count() - 3);
708}
709
710void EasyMesh::AppendSimpleQuad(float size, int fade)
711{
712    AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
713}
714
715void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
716{
717    AddVertex(vec3(p2.x, z, -p1.y));
718    AddVertex(vec3(p2.x, z, -p2.y));
719    AddVertex(vec3(p1.x, z, -p2.y));
720    if (fade)
721        SetCurVertColor(m_color2);
722    AddVertex(vec3(p1.x, z, -p1.y));
723    if (fade)
724        SetCurVertColor(m_color2);
725
726    AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
727    ComputeNormals(m_indices.Count() - 6, 6);
728}
729
730void EasyMesh::AppendCog(int nbsides, float h, float r1, float r2, float r12,
731                         float r22, float sidemul, int offset)
732{
733    int ibase = m_indices.Count();
734    int vbase = m_vert.Count();
735
736    AddVertex(vec3(0.f, h * .5f, 0.f));
737    AddVertex(vec3(0.f, h * -.5f, 0.f));
738    SetCurVertColor(m_color2);
739
740    mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
741    mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
742    mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
743
744    vec3 p[8];
745
746    p[0] = vec3(r1, h * .5f, 0.f);
747    p[1] = rotmat * p[0];
748    p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
749    p[3] = smat2 * (rotmat * p[2]);
750
751    p[4] = vec3(r2, h * -.5f, 0.f);
752    p[5] = rotmat * p[4];
753    p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
754    p[7] = smat2 * (rotmat * p[6]);
755
756    if (offset & 1)
757        for (int n = 0; n < 8; n++)
758            p[n] = rotmat * p[n];
759
760    rotmat = rotmat * rotmat;
761
762    for (int i = 0; i < nbsides; i++)
763    {
764        /* Each vertex will share three faces, so three different
765         * normals, therefore we add each vertex three times. */
766        for (int n = 0; n < 24; n++)
767        {
768            AddVertex(p[n / 3]);
769            if (n / 3 >= 4)
770                SetCurVertColor(m_color2);
771        }
772
773        int j = 24 * i, k = 24 * ((i + 1) % nbsides);
774
775        /* The top and bottom faces */
776        AppendQuad(0, j + 2, j + 5, k + 2, vbase);
777        AppendQuad(1, k + 14, j + 17, j + 14, vbase);
778        AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
779        AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
780
781        /* The side quads */
782        AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
783        AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
784        AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
785        AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
786
787        for (int n = 0; n < 8; n++)
788            p[n] = rotmat * p[n];
789    }
790
791    ComputeNormals(ibase, m_indices.Count() - ibase);
792}
793
794void EasyMesh::Chamfer(float f)
795{
796    int vlen = m_vert.Count() - m_cursors.Last().m1;
797    int ilen = m_indices.Count() - m_cursors.Last().m2;
798
799    /* Step 1: enumerate all faces. This is done by merging triangles
800     * that are coplanar and share an edge. */
801    int *triangle_classes = new int[ilen / 3];
802    for (int i = 0; i < ilen / 3; i++)
803        triangle_classes[i] = -1;
804
805    for (int i = 0; i < ilen / 3; i++)
806    {
807         
808    }
809
810    /* Fun shit: reduce all triangles */
811    int *vertices = new int[vlen];
812    memset(vertices, 0, vlen * sizeof(int));
813    for (int i = 0; i < ilen; i++)
814        vertices[m_indices[i]]++;
815
816    for (int i = 0; i < ilen / 3; i++)
817    {
818    #if 0
819        if (vertices[m_indices[i * 3]] > 1)
820            continue;
821        if (vertices[m_indices[i * 3 + 1]] > 1)
822            continue;
823        if (vertices[m_indices[i * 3 + 2]] > 1)
824            continue;
825    #endif
826
827        vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m1 +
828                                 m_vert[m_indices[i * 3 + 1]].m1 +
829                                 m_vert[m_indices[i * 3 + 2]].m1);
830        for (int k = 0; k < 3; k++)
831        {
832            vec3 &p = m_vert[m_indices[i * 3 + k]].m1;
833            p -= normalize(p - bary) * f;
834        }
835    }
836}
837
838} /* namespace lol */
839
Note: See TracBrowser for help on using the repository browser.