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

Last change on this file since 2211 was 2211, checked in by Jnat, 7 years ago

coding style my ass

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