source: trunk/orbital/mesh.h @ 1442

Last change on this file since 1442 was 1442, checked in by sam, 10 years ago

orbital: some improvements to the mesh parser and error reporting.

  • Property svn:keywords set to Id
File size: 22.1 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        int vbase = m_vert.Count();
410        int qibase = m_quadidx.Count();
411        int tibase = m_triidx.Count();
412
413        vec3 d = size * 0.5f;
414
415        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
416        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
417        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
418        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
419
420        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
421        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
422        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
423        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
424
425        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
426        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
427        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
428        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
429
430        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
431        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
432        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
433        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
434
435        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
436        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
437        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
438        AppendQuadVert(vec3(+d.x, -d.y - chamf, +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        /* The 6 quads on each side of the box */
446        for (int i = 0; i < 24; i += 4)
447            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
448
449        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
450        qibase = m_quadidx.Count();
451
452        /* The 8 quads at each edge of the box */
453        if (chamf)
454        {
455            static int const quadlist[48] =
456            {
457                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
458                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
459                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
460            };
461
462            for (int i = 0; i < 48; i += 4)
463            {
464                if (smooth)
465                    AppendQuad(quadlist[i], quadlist[i + 1],
466                               quadlist[i + 2], quadlist[i + 3], vbase);
467                else
468                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
469                                     quadlist[i + 2], quadlist[i + 3], vbase);
470            }
471        }
472
473        /* The 8 triangles at each corner of the box */
474        if (chamf)
475        {
476            static int const trilist[24] =
477            {
478                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
479                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
480            };
481
482            for (int i = 0; i < 24; i += 3)
483            {
484                if (smooth)
485                    AppendTriangle(trilist[i], trilist[i + 1],
486                                   trilist[i + 2], vbase);
487                else
488                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
489                                                 trilist[i + 2], vbase);
490            }
491        }
492
493        if (!smooth)
494        {
495            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
496            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
497        }
498    }
499
500    void AppendStar(int nbranches, float r1, float r2,
501                    int fade = 0, int fade2 = 0)
502    {
503        int vbase = m_vert.Count();
504
505        AppendQuadVert(vec3(0.f, 0.f, 0.f));
506
507        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
508        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
509
510        p2 = rotmat * p2;
511        rotmat = rotmat * rotmat;
512
513        for (int i = 0; i < nbranches; i++)
514        {
515            AppendQuadVert(p1);
516            if (fade2)
517                SetCurVertColor(m_color2);
518
519            AppendQuadVert(p2);
520            if (fade)
521                SetCurVertColor(m_color2);
522
523            AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
524                       vbase);
525
526            p1 = rotmat * p1;
527            p2 = rotmat * p2;
528        }
529    }
530
531    void AppendExpandedStar(int nbranches, float r1, float r2, float extrar)
532    {
533        int vbase = m_vert.Count();
534
535        AppendQuadVert(vec3(0.f, 0.f, 0.f));
536
537        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
538        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
539             p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
540
541        p2 = rotmat * p2;
542        p4 = rotmat * p4;
543        rotmat = rotmat * rotmat;
544
545        for (int i = 0; i < nbranches; i++)
546        {
547            AppendQuadVert(p1);
548            AppendQuadVert(p2);
549            AppendQuadVert(p3); SetCurVertColor(m_color2);
550            AppendQuadVert(p4); SetCurVertColor(m_color2);
551
552            int j = (i + 1) % nbranches;
553            AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
554            AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
555            AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
556
557            p1 = rotmat * p1;
558            p2 = rotmat * p2;
559            p3 = rotmat * p3;
560            p4 = rotmat * p4;
561        }
562    }
563
564    void AppendDisc(int nsides, float r, int fade = 0)
565    {
566        int vbase = m_vert.Count();
567
568        AppendQuadVert(vec3(0.f, 0.f, 0.f));
569
570        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
571        vec3 p1(r, 0.f, 0.f);
572
573        for (int i = 0; i < nsides; i++)
574        {
575            AppendQuadVert(p1);
576            if (fade)
577                SetCurVertColor(m_color2);
578            AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
579            p1 = rotmat * p1;
580        }
581    }
582
583    void AppendSimpleTriangle(float size, int fade = 0)
584    {
585        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
586        vec3 p(0.f, 0.f, size);
587
588        AppendQuadVert(p);
589        p = m * p;
590        AppendQuadVert(p);
591        if (fade)
592            SetCurVertColor(m_color2);
593        p = m * p;
594        AppendQuadVert(p);
595        if (fade)
596            SetCurVertColor(m_color2);
597
598        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
599    }
600
601    void AppendSimpleQuad(float size, int fade = 0)
602    {
603        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
604    }
605
606    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
607    {
608        AppendQuadVert(vec3(p2.x, z, -p1.y));
609        AppendQuadVert(vec3(p2.x, z, -p2.y));
610        AppendQuadVert(vec3(p1.x, z, -p2.y));
611        if (fade)
612            SetCurVertColor(m_color2);
613        AppendQuadVert(vec3(p1.x, z, -p1.y));
614        if (fade)
615            SetCurVertColor(m_color2);
616
617        AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
618        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
619    }
620
621    void AppendCog(int nbsides, float h, float r1, float r2,
622                   float r12, float r22, float sidemul, int offset)
623    {
624        int qibase = m_quadidx.Count();
625        int vbase = m_vert.Count();
626
627        AppendQuadVert(vec3(0.f, h * .5f, 0.f));
628        AppendQuadVert(vec3(0.f, h * -.5f, 0.f));
629        SetCurVertColor(m_color2);
630
631        mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
632        mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
633        mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
634
635        vec3 p[8];
636
637        p[0] = vec3(r1, h * .5f, 0.f);
638        p[1] = rotmat * p[0];
639        p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
640        p[3] = smat2 * (rotmat * p[2]);
641
642        p[4] = vec3(r2, h * -.5f, 0.f);
643        p[5] = rotmat * p[4];
644        p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
645        p[7] = smat2 * (rotmat * p[6]);
646
647        if (offset & 1)
648            for (int n = 0; n < 8; n++)
649                p[n] = rotmat * p[n];
650
651        rotmat = rotmat * rotmat;
652
653        for (int i = 0; i < nbsides; i++)
654        {
655            /* Each vertex will share three faces, so three different
656             * normals, therefore we add each vertex three times. */
657            for (int n = 0; n < 24; n++)
658            {
659                AppendQuadVert(p[n / 3]);
660                if (n / 3 >= 4)
661                    SetCurVertColor(m_color2);
662            }
663
664            int j = 24 * i, k = 24 * ((i + 1) % nbsides);
665
666            /* The top and bottom faces */
667            AppendQuad(0, j + 2, j + 5, k + 2, vbase);
668            AppendQuad(1, k + 14, j + 17, j + 14, vbase);
669            AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
670            AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
671
672            /* The side quads */
673            AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
674            AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
675            AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
676            AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
677
678            for (int n = 0; n < 8; n++)
679                p[n] = rotmat * p[n];
680        }
681
682        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
683    }
684
685private:
686    vec4 m_color, m_color2;
687    Array<uint16_t> m_triidx, m_quadidx;
688    Array<vec3, vec3, vec4> m_vert;
689    Array<int, int, int> m_cursors;
690
691    /* FIXME: put this in a separate class so that we can copy meshes. */
692    struct
693    {
694        Shader *shader;
695        ShaderAttrib coord, norm, color;
696        ShaderUniform modelview, proj, normalmat, damage;
697        VertexDeclaration *vdecl;
698        VertexBuffer *vbo;
699        IndexBuffer *ibo;
700        int vertexcount, indexcount;
701    }
702    m_gpu;
703};
704
705#endif /* __MESH_H__ */
706
Note: See TracBrowser for help on using the repository browser.