source: trunk/orbital/mesh.h @ 1506

Last change on this file since 1506 was 1506, checked in by sam, 11 years ago

orbital: add "ch" command to create chamfers.

  • Property svn:keywords set to Id
File size: 22.2 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2009-2012 Cédric Lecacheur <jordx@free.fr>
5//            (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
6//            (c) 2012 Sam Hocevar <sam@hocevar.net>
7//
8
9/* TODO for this file:
10 *  - rename "AppendQuadVert" to "AddVertex" or something; it has nothing
11 *    to do with quads.
12 */
13
14#if !defined __MESH_H__
15#define __MESH_H__
16
17extern char const *lolfx_shiny;
18
19class Mesh
20{
21public:
22    Mesh()
23      : m_color(0), m_color2(0)
24    {
25        m_cursors.Push(0, 0, 0);
26    }
27
28    bool Compile(char const *command);
29
30    void OpenBrace()
31    {
32        m_cursors.Push(m_vert.Count(), m_quadidx.Count(), m_triidx.Count());
33    }
34
35    void CloseBrace()
36    {
37        m_cursors.Pop();
38    }
39
40    void MeshConvert()
41    {
42        m_gpu.shader = Shader::Create(lolfx_shiny);
43
44        m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView");
45        m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
46        m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
47        m_gpu.damage = m_gpu.shader->GetUniformLocation("in_Damage");
48        m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
49                                              VertexUsage::Position, 0);
50        m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
51                                             VertexUsage::Normal, 0);
52        m_gpu.color = m_gpu.shader->GetAttribLocation("in_Color",
53                                              VertexUsage::Color, 0);
54
55        m_gpu.vdecl = new VertexDeclaration(
56            VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
57                                           VertexUsage::Normal,
58                                           VertexUsage::Color));
59
60        Array<vec3,vec3,u8vec4> vertexlist;
61        for (int i = 0; i < m_vert.Count(); i++)
62            vertexlist.Push(m_vert[i].m1,
63                            m_vert[i].m2,
64                            (u8vec4)(m_vert[i].m3 * 255.f));
65
66        Array<uint16_t> indexlist;
67        for (int i = 0; i < m_triidx.Count(); i += 3)
68        {
69            indexlist << m_triidx[i + 0];
70            indexlist << m_triidx[i + 1];
71            indexlist << m_triidx[i + 2];
72        }
73        for (int i = 0; i < m_quadidx.Count(); i += 4)
74        {
75            indexlist << m_quadidx[i + 0];
76            indexlist << m_quadidx[i + 1];
77            indexlist << m_quadidx[i + 2];
78
79            indexlist << m_quadidx[i + 0];
80            indexlist << m_quadidx[i + 2];
81            indexlist << m_quadidx[i + 3];
82        }
83
84        m_gpu.vbo = new VertexBuffer(vertexlist.Bytes());
85        void *mesh = m_gpu.vbo->Lock(0, 0);
86        memcpy(mesh, &vertexlist[0], vertexlist.Bytes());
87        m_gpu.vbo->Unlock();
88
89        m_gpu.ibo = new IndexBuffer(indexlist.Bytes());
90        void *indices = m_gpu.ibo->Lock(0, 0);
91        memcpy(indices, &indexlist[0], indexlist.Bytes());
92        m_gpu.ibo->Unlock();
93
94        m_gpu.vertexcount = vertexlist.Count();
95        m_gpu.indexcount = indexlist.Count();
96    }
97
98    void Render(mat4 const &model, float damage = 0.f)
99    {
100        mat4 modelview = Scene::GetDefault()->GetViewMatrix() * model;
101        mat3 normalmat = transpose(inverse(mat3(modelview)));
102
103        m_gpu.shader->Bind();
104        m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
105        m_gpu.shader->SetUniform(m_gpu.proj, Scene::GetDefault()->GetProjMatrix());
106        m_gpu.shader->SetUniform(m_gpu.normalmat, normalmat);
107        m_gpu.shader->SetUniform(m_gpu.damage, damage);
108        m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord, m_gpu.norm, m_gpu.color);
109        m_gpu.vdecl->Bind();
110        m_gpu.ibo->Bind();
111        m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
112                                         0, 0, m_gpu.vertexcount,
113                                         0, m_gpu.indexcount / 3);
114        m_gpu.ibo->Unbind();
115        m_gpu.vdecl->Unbind();
116    }
117
118    void SetCurColor(vec4 const &color) { m_color = color; }
119    void SetCurColor2(vec4 const &color) { m_color2 = color; }
120
121    void AppendQuadVert(vec3 const &coord)
122    {
123        m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color);
124    }
125
126    void AppendDuplicateQuadVert(int i)
127    {
128        m_vert.Push(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3);
129    }
130
131    void AppendQuad(int i1, int i2, int i3, int i4, int base)
132    {
133        m_quadidx << base + i1;
134        m_quadidx << base + i2;
135        m_quadidx << base + i3;
136        m_quadidx << base + i4;
137    }
138
139    void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
140    {
141        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
142        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
143        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
144        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i4);
145    }
146
147    void AppendTriangle(int i1, int i2, int i3, int base)
148    {
149        m_triidx << base + i1;
150        m_triidx << base + i2;
151        m_triidx << base + i3;
152    }
153
154    void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
155    {
156        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
157        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
158        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
159    }
160
161    void ComputeQuadNormals(int start, int vcount)
162    {
163        for (int i = 0; i < vcount; i += 4)
164        {
165            vec3 v0 = m_vert[m_quadidx[start + i + 2]].m1
166                    - m_vert[m_quadidx[start + i + 0]].m1;
167            vec3 v1 = m_vert[m_quadidx[start + i + 1]].m1
168                    - m_vert[m_quadidx[start + i + 0]].m1;
169            vec3 n = normalize(cross(v1, v0));
170
171            for (int j = 0; j < 4; j++)
172                m_vert[m_quadidx[start + i + j]].m2 = n;
173        }
174    }
175
176    void ComputeTriNormals(int start, int vcount)
177    {
178        for (int i = 0; i < vcount; i += 3)
179        {
180            vec3 v0 = m_vert[m_triidx[start + i + 2]].m1
181                    - m_vert[m_triidx[start + i + 0]].m1;
182            vec3 v1 = m_vert[m_triidx[start + i + 1]].m1
183                    - m_vert[m_triidx[start + i + 0]].m1;
184            vec3 n = normalize(cross(v1, v0));
185
186            for (int j = 0; j < 3; j++)
187                m_vert[m_triidx[start + i + j]].m2 = n;
188        }
189    }
190
191    void SetVertColor(vec4 const &color)
192    {
193        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
194            m_vert[i].m3 = color;
195    }
196
197    void SetCurVertNormal(vec3 const &normal)
198    {
199        m_vert[m_vert.Count() - 1].m2 = normal;
200    }
201
202    void SetCurVertColor(vec4 const &color)
203    {
204        m_vert[m_vert.Count() - 1].m3 = color;
205    }
206
207    void Translate(vec3 const &v)
208    {
209        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
210            m_vert[i].m1 += v;
211    }
212
213    void RotateX(float t) { Rotate(t, vec3(1, 0, 0)); }
214    void RotateY(float t) { Rotate(t, vec3(0, 1, 0)); }
215    void RotateZ(float t) { Rotate(t, vec3(0, 0, 1)); }
216
217    void Rotate(float t, vec3 const &axis)
218    {
219        mat3 m = mat3::rotate(t, axis);
220        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
221        {
222            m_vert[i].m1 = m * m_vert[i].m1;
223            m_vert[i].m2 = m * m_vert[i].m2;
224        }
225    }
226
227    void TaperX(float y, float z, float xoff)
228    {
229        /* FIXME: this code breaks normals! */
230        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
231        {
232            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
233            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
234        }
235    }
236
237    void TaperY(float x, float z, float yoff)
238    {
239        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
240        {
241            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
242            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
243        }
244    }
245
246    void TaperZ(float x, float y, float zoff)
247    {
248        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
249        {
250            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
251            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
252        }
253    }
254
255    void Scale(vec3 const &s)
256    {
257        vec3 const invs = vec3(1) / s;
258
259        for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
260        {
261            m_vert[i].m1 *= s;
262            m_vert[i].m2 = normalize(m_vert[i].m2 * invs);
263        }
264
265        /* Flip winding if the scaling involves mirroring */
266        if (s.x * s.y * s.z < 0)
267        {
268            for (int i = m_cursors.Last().m2; i < m_quadidx.Count(); i += 2)
269            {
270                uint16_t tmp = m_quadidx[i + 0];
271                m_quadidx[i + 0] = m_quadidx[i + 1];
272                m_quadidx[i + 1] = tmp;
273            }
274
275            for (int i = m_cursors.Last().m3; i < m_triidx.Count(); i += 3)
276            {
277                uint16_t tmp = m_triidx[i + 0];
278                m_triidx[i + 0] = m_triidx[i + 1];
279                m_triidx[i + 1] = tmp;
280            }
281        }
282    }
283
284    void MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
285    void MirrorY() { DupAndScale(vec3(1, -1, 1)); }
286    void MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
287
288    void DupAndScale(vec3 const &s)
289    {
290        int vlen = m_vert.Count() - m_cursors.Last().m1;
291        int qlen = m_quadidx.Count() - m_cursors.Last().m2;
292        int tlen = m_triidx.Count() - m_cursors.Last().m3;
293
294        for (int i = 0; i < vlen; i++)
295            m_vert << m_vert[m_cursors.Last().m1++];
296
297        for (int i = 0; i < qlen; i++)
298            m_quadidx << m_quadidx[m_cursors.Last().m2++] + vlen;
299
300        for (int i = 0; i < tlen; i++)
301            m_triidx << m_triidx[m_cursors.Last().m3++] + vlen;
302
303        Scale(s);
304
305        m_cursors.Last().m1 -= vlen;
306        m_cursors.Last().m2 -= qlen;
307        m_cursors.Last().m3 -= tlen;
308    }
309
310    void AppendCylinder(int nsides, float h, float r1, float r2,
311                        int dualside, int smooth)
312    {
313        int vbase = m_vert.Count();
314
315        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
316        vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
317
318        /* Construct normal */
319        n = p2;
320        n.y = r1 * (r1 - r2) / h;
321        if (!smooth)
322            n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
323        n = normalize(n);
324
325        /* FIXME: normals should be flipped in two-sided mode, but that
326         * means duplicating the vertices again... */
327        for (int i = 0; i < nsides; i++)
328        {
329            AppendQuadVert(p1); SetCurVertNormal(n);
330            AppendQuadVert(p2); SetCurVertNormal(n);
331            SetCurVertColor(m_color2);
332
333            if (smooth)
334            {
335                int j = (i + 1) % nsides;
336                AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
337                if (dualside)
338                    AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
339            }
340
341            p1 = rotmat * p1;
342            p2 = rotmat * p2;
343
344            if (!smooth)
345            {
346                AppendQuadVert(p1); SetCurVertNormal(n);
347                AppendQuadVert(p2); SetCurVertNormal(n);
348                SetCurVertColor(m_color2);
349
350                AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
351                if (dualside)
352                    AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
353            }
354
355            n = rotmat * n;
356        }
357    }
358
359    void AppendSphere(int ndivisions, vec3 const &size)
360    {
361        ndivisions *= 2;
362
363        int ibase = m_quadidx.Count();
364        int vbase = m_vert.Count();
365
366        vec3 d = size * 0.5f;
367        float const pi = std::acos(-1.0f);
368
369        Array<vec2> table;
370        for (int i = 0; i <= ndivisions; i++)
371            table.Push(vec2(std::sin(pi * 2 / ndivisions * i) + 1e-5f,
372                            std::cos(pi * 2 / ndivisions * i) + 1e-5f));
373
374        for (int j = 0; j <= ndivisions / 2; j++)
375            for (int i = 0; i < ndivisions; i++)
376            {
377                int j2 = j + 1;
378                int i2 = (i + 1) % ndivisions;
379
380                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
381                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
382                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
383                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
384            }
385
386        for (int i = vbase; i < m_vert.Count(); i += 4)
387            AppendQuad(0, 1, 2, 3, i);
388
389        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
390    }
391
392    void AppendBox(vec3 const &size, float chamf = 0.f)
393    {
394        AppendBox(size, chamf, false);
395    }
396
397    void AppendSmoothChamfBox(vec3 const &size, float chamf)
398    {
399        AppendBox(size, chamf, true);
400    }
401
402    void AppendFlatChamfBox(vec3 const &size, float chamf)
403    {
404        AppendBox(size, chamf, false);
405    }
406
407    void AppendBox(vec3 const &size, float chamf, bool smooth)
408    {
409                if (chamf < 0.0f)
410                {
411                        AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
412                        return;
413                }
414        int vbase = m_vert.Count();
415        int qibase = m_quadidx.Count();
416        int tibase = m_triidx.Count();
417
418        vec3 d = size * 0.5f;
419
420        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
421        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
422        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
423        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
424
425        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
426        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
427        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
428        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
429
430        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
431        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
432        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
433        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
434
435        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
436        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
437        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
438        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
439
440        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
441        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
442        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
443        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
444
445        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
446        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
447        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
448        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
449
450        /* The 6 quads on each side of the box */
451        for (int i = 0; i < 24; i += 4)
452            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
453
454        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
455        qibase = m_quadidx.Count();
456
457        /* The 8 quads at each edge of the box */
458        if (chamf)
459        {
460            static int const quadlist[48] =
461            {
462                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
463                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
464                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
465            };
466
467            for (int i = 0; i < 48; i += 4)
468            {
469                if (smooth)
470                    AppendQuad(quadlist[i], quadlist[i + 1],
471                               quadlist[i + 2], quadlist[i + 3], vbase);
472                else
473                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
474                                     quadlist[i + 2], quadlist[i + 3], vbase);
475            }
476        }
477
478        /* The 8 triangles at each corner of the box */
479        if (chamf)
480        {
481            static int const trilist[24] =
482            {
483                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
484                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
485            };
486
487            for (int i = 0; i < 24; i += 3)
488            {
489                if (smooth)
490                    AppendTriangle(trilist[i], trilist[i + 1],
491                                   trilist[i + 2], vbase);
492                else
493                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
494                                                 trilist[i + 2], vbase);
495            }
496        }
497
498        if (!smooth)
499        {
500            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
501            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
502        }
503    }
504
505    void AppendStar(int nbranches, float r1, float r2,
506                    int fade = 0, int fade2 = 0)
507    {
508        int vbase = m_vert.Count();
509
510        AppendQuadVert(vec3(0.f, 0.f, 0.f));
511
512        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
513        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
514
515        p2 = rotmat * p2;
516        rotmat = rotmat * rotmat;
517
518        for (int i = 0; i < nbranches; i++)
519        {
520            AppendQuadVert(p1);
521            if (fade2)
522                SetCurVertColor(m_color2);
523
524            AppendQuadVert(p2);
525            if (fade)
526                SetCurVertColor(m_color2);
527
528            AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
529                       vbase);
530
531            p1 = rotmat * p1;
532            p2 = rotmat * p2;
533        }
534    }
535
536    void AppendExpandedStar(int nbranches, float r1, float r2, float extrar)
537    {
538        int vbase = m_vert.Count();
539
540        AppendQuadVert(vec3(0.f, 0.f, 0.f));
541
542        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
543        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
544             p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
545
546        p2 = rotmat * p2;
547        p4 = rotmat * p4;
548        rotmat = rotmat * rotmat;
549
550        for (int i = 0; i < nbranches; i++)
551        {
552            AppendQuadVert(p1);
553            AppendQuadVert(p2);
554            AppendQuadVert(p3); SetCurVertColor(m_color2);
555            AppendQuadVert(p4); SetCurVertColor(m_color2);
556
557            int j = (i + 1) % nbranches;
558            AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
559            AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
560            AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
561
562            p1 = rotmat * p1;
563            p2 = rotmat * p2;
564            p3 = rotmat * p3;
565            p4 = rotmat * p4;
566        }
567    }
568
569    void AppendDisc(int nsides, float r, int fade = 0)
570    {
571        int vbase = m_vert.Count();
572
573        AppendQuadVert(vec3(0.f, 0.f, 0.f));
574
575        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
576        vec3 p1(r, 0.f, 0.f);
577
578        for (int i = 0; i < nsides; i++)
579        {
580            AppendQuadVert(p1);
581            if (fade)
582                SetCurVertColor(m_color2);
583            AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
584            p1 = rotmat * p1;
585        }
586    }
587
588    void AppendSimpleTriangle(float size, int fade = 0)
589    {
590        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
591        vec3 p(0.f, 0.f, size);
592
593        AppendQuadVert(p);
594        p = m * p;
595        AppendQuadVert(p);
596        if (fade)
597            SetCurVertColor(m_color2);
598        p = m * p;
599        AppendQuadVert(p);
600        if (fade)
601            SetCurVertColor(m_color2);
602
603        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
604    }
605
606    void AppendSimpleQuad(float size, int fade = 0)
607    {
608        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
609    }
610
611    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
612    {
613        AppendQuadVert(vec3(p2.x, z, -p1.y));
614        AppendQuadVert(vec3(p2.x, z, -p2.y));
615        AppendQuadVert(vec3(p1.x, z, -p2.y));
616        if (fade)
617            SetCurVertColor(m_color2);
618        AppendQuadVert(vec3(p1.x, z, -p1.y));
619        if (fade)
620            SetCurVertColor(m_color2);
621
622        AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
623        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
624    }
625
626    void AppendCog(int nbsides, float h, float r1, float r2,
627                   float r12, float r22, float sidemul, int offset)
628    {
629        int qibase = m_quadidx.Count();
630        int vbase = m_vert.Count();
631
632        AppendQuadVert(vec3(0.f, h * .5f, 0.f));
633        AppendQuadVert(vec3(0.f, h * -.5f, 0.f));
634        SetCurVertColor(m_color2);
635
636        mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
637        mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
638        mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
639
640        vec3 p[8];
641
642        p[0] = vec3(r1, h * .5f, 0.f);
643        p[1] = rotmat * p[0];
644        p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
645        p[3] = smat2 * (rotmat * p[2]);
646
647        p[4] = vec3(r2, h * -.5f, 0.f);
648        p[5] = rotmat * p[4];
649        p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
650        p[7] = smat2 * (rotmat * p[6]);
651
652        if (offset & 1)
653            for (int n = 0; n < 8; n++)
654                p[n] = rotmat * p[n];
655
656        rotmat = rotmat * rotmat;
657
658        for (int i = 0; i < nbsides; i++)
659        {
660            /* Each vertex will share three faces, so three different
661             * normals, therefore we add each vertex three times. */
662            for (int n = 0; n < 24; n++)
663            {
664                AppendQuadVert(p[n / 3]);
665                if (n / 3 >= 4)
666                    SetCurVertColor(m_color2);
667            }
668
669            int j = 24 * i, k = 24 * ((i + 1) % nbsides);
670
671            /* The top and bottom faces */
672            AppendQuad(0, j + 2, j + 5, k + 2, vbase);
673            AppendQuad(1, k + 14, j + 17, j + 14, vbase);
674            AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
675            AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
676
677            /* The side quads */
678            AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
679            AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
680            AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
681            AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
682
683            for (int n = 0; n < 8; n++)
684                p[n] = rotmat * p[n];
685        }
686
687        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
688    }
689
690    void Chamfer(float f)
691    {
692        (void)f;
693    }
694
695private:
696    vec4 m_color, m_color2;
697    Array<uint16_t> m_triidx, m_quadidx;
698    Array<vec3, vec3, vec4> m_vert;
699    Array<int, int, int> m_cursors;
700
701    /* FIXME: put this in a separate class so that we can copy meshes. */
702    struct
703    {
704        Shader *shader;
705        ShaderAttrib coord, norm, color;
706        ShaderUniform modelview, proj, normalmat, damage;
707        VertexDeclaration *vdecl;
708        VertexBuffer *vbo;
709        IndexBuffer *ibo;
710        int vertexcount, indexcount;
711    }
712    m_gpu;
713};
714
715#endif /* __MESH_H__ */
716
Note: See TracBrowser for help on using the repository browser.