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

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

easymesh: set the capsule's main axis to Y, not Z.

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