source: trunk/orbital/mesh.h @ 1419

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

orbital: a lot of scanner and parser refactoring to simplify the source
files and allow to build on MSVC soon.

  • Property svn:keywords set to Id
File size: 21.9 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2012 Various People
5//
6
7/* TODO for this file:
8 *  - rename "AppendQuadVert" to "AddVertex" or something; it has nothing
9 *    to do with quads.
10 */
11
12extern char const *lolfx_shiny;
13
14#if !defined __MESH_H__
15#define __MESH_H__
16
17#include "mesh-driver.h"
18
19class Mesh
20{
21public:
22    Mesh()
23      : m_color(0), m_color2(0),
24        m_vert_cursor(0), m_quadidx_cursor(0), m_triidx_cursor(0)
25    {}
26
27    void SendCommand(char const *command)
28    {
29        orbital::Driver driver(*this);
30        driver.ParseString(command);
31    }
32
33    void Flush()
34    {
35        m_vert_cursor = m_vert.Count();
36        m_quadidx_cursor = m_quadidx.Count();
37        m_triidx_cursor = m_triidx.Count();
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_vert_cursor; 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_vert_cursor; 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_vert_cursor; 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_vert_cursor; 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_vert_cursor; 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_vert_cursor; 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_vert_cursor; 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_quadidx_cursor; 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_triidx_cursor; 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() { Duplicate(); Scale(vec3(-1, 1, 1)); }
285    void MirrorY() { Duplicate(); Scale(vec3(1, -1, 1)); }
286    void MirrorZ() { Duplicate(); Scale(vec3(1, 1, -1)); }
287
288    void Duplicate()
289    {
290        int vlen = m_vert.Count() - m_vert_cursor;
291        int qlen = m_quadidx.Count() - m_quadidx_cursor;
292        int tlen = m_triidx.Count() - m_triidx_cursor;
293
294        for (int i = 0; i < vlen; i++)
295            m_vert << m_vert[m_vert_cursor++];
296
297        for (int i = 0; i < qlen; i++)
298            m_quadidx << m_quadidx[m_quadidx_cursor++] + vlen;
299
300        for (int i = 0; i < tlen; i++)
301            m_triidx << m_triidx[m_triidx_cursor++] + vlen;
302    }
303
304    void AppendCylinder(int nsides, float h, float r1, float r2,
305                        int dualside, int smooth)
306    {
307        int vbase = m_vert.Count();
308
309        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
310        vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
311
312        /* Construct normal */
313        n = p2;
314        n.y = r1 * (r1 - r2) / h;
315        if (!smooth)
316            n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
317        n = normalize(n);
318
319        /* FIXME: normals should be flipped in two-sided mode, but that
320         * means duplicating the vertices again... */
321        for (int i = 0; i < nsides; i++)
322        {
323            AppendQuadVert(p1); SetCurVertNormal(n);
324            AppendQuadVert(p2); SetCurVertNormal(n);
325            SetCurVertColor(m_color2);
326
327            if (smooth)
328            {
329                int j = (i + 1) % nsides;
330                AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
331                if (dualside)
332                    AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
333            }
334
335            p1 = rotmat * p1;
336            p2 = rotmat * p2;
337
338            if (!smooth)
339            {
340                AppendQuadVert(p1); SetCurVertNormal(n);
341                AppendQuadVert(p2); SetCurVertNormal(n);
342                SetCurVertColor(m_color2);
343
344                AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
345                if (dualside)
346                    AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
347            }
348
349            n = rotmat * n;
350        }
351    }
352
353    void AppendSphere(int ndivisions, vec3 const &size)
354    {
355        ndivisions *= 2;
356
357        int ibase = m_quadidx.Count();
358        int vbase = m_vert.Count();
359
360        vec3 d = size * 0.5f;
361        float const pi = std::acos(-1.0f);
362
363        Array<vec2> table;
364        for (int i = 0; i <= ndivisions; i++)
365            table.Push(vec2(std::sin(pi * 2 / ndivisions * i) + 1e-5f,
366                            std::cos(pi * 2 / ndivisions * i) + 1e-5f));
367
368        for (int j = 0; j <= ndivisions / 2; j++)
369            for (int i = 0; i < ndivisions; i++)
370            {
371                int j2 = j + 1;
372                int i2 = (i + 1) % ndivisions;
373
374                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
375                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
376                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
377                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
378            }
379
380        for (int i = vbase; i < m_vert.Count(); i += 4)
381            AppendQuad(0, 1, 2, 3, i);
382
383        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
384    }
385
386    void AppendBox(vec3 const &size, float chamf = 0.f)
387    {
388        AppendBox(size, chamf, false);
389    }
390
391    void AppendSmoothChamfBox(vec3 const &size, float chamf)
392    {
393        AppendBox(size, chamf, true);
394    }
395
396    void AppendFlatChamfBox(vec3 const &size, float chamf)
397    {
398        AppendBox(size, chamf, false);
399    }
400
401    void AppendBox(vec3 const &size, float chamf, bool smooth)
402    {
403        int vbase = m_vert.Count();
404        int qibase = m_quadidx.Count();
405        int tibase = m_triidx.Count();
406
407        vec3 d = size * 0.5f;
408
409        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
410        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
411        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
412        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
413
414        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
415        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
416        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
417        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
418
419        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
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
424        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
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
429        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
430        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
431        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
432        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
433
434        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
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
439        /* The 6 quads on each side of the box */
440        for (int i = 0; i < 24; i += 4)
441            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
442
443        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
444        qibase = m_quadidx.Count();
445
446        /* The 8 quads at each edge of the box */
447        if (chamf)
448        {
449            static int const quadlist[48] =
450            {
451                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
452                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
453                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
454            };
455
456            for (int i = 0; i < 48; i += 4)
457            {
458                if (smooth)
459                    AppendQuad(quadlist[i], quadlist[i + 1],
460                               quadlist[i + 2], quadlist[i + 3], vbase);
461                else
462                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
463                                     quadlist[i + 2], quadlist[i + 3], vbase);
464            }
465        }
466
467        /* The 8 triangles at each corner of the box */
468        if (chamf)
469        {
470            static int const trilist[24] =
471            {
472                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
473                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
474            };
475
476            for (int i = 0; i < 24; i += 3)
477            {
478                if (smooth)
479                    AppendTriangle(trilist[i], trilist[i + 1],
480                                   trilist[i + 2], vbase);
481                else
482                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
483                                                 trilist[i + 2], vbase);
484            }
485        }
486
487        if (!smooth)
488        {
489            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
490            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
491        }
492    }
493
494    void AppendStar(int nbranches, float r1, float r2,
495                    int fade = 0, int fade2 = 0)
496    {
497        int vbase = m_vert.Count();
498
499        AppendQuadVert(vec3(0.f, 0.f, 0.f));
500
501        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
502        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
503
504        p2 = rotmat * p2;
505        rotmat = rotmat * rotmat;
506
507        for (int i = 0; i < nbranches; i++)
508        {
509            AppendQuadVert(p1);
510            if (fade2)
511                SetCurVertColor(m_color2);
512
513            AppendQuadVert(p2);
514            if (fade)
515                SetCurVertColor(m_color2);
516
517            AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches),
518                       vbase);
519
520            p1 = rotmat * p1;
521            p2 = rotmat * p2;
522        }
523    }
524
525    void AppendExpandedStar(int nbranches, float r1, float r2, float extrar)
526    {
527        int vbase = m_vert.Count();
528
529        AppendQuadVert(vec3(0.f, 0.f, 0.f));
530
531        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
532        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
533             p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
534
535        p2 = rotmat * p2;
536        p4 = rotmat * p4;
537        rotmat = rotmat * rotmat;
538
539        for (int i = 0; i < nbranches; i++)
540        {
541            AppendQuadVert(p1);
542            AppendQuadVert(p2);
543            AppendQuadVert(p3); SetCurVertColor(m_color2);
544            AppendQuadVert(p4); SetCurVertColor(m_color2);
545
546            int j = (i + 1) % nbranches;
547            AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
548            AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
549            AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
550
551            p1 = rotmat * p1;
552            p2 = rotmat * p2;
553            p3 = rotmat * p3;
554            p4 = rotmat * p4;
555        }
556    }
557
558    void AppendDisc(int nsides, float r, int fade = 0)
559    {
560        int vbase = m_vert.Count();
561
562        AppendQuadVert(vec3(0.f, 0.f, 0.f));
563
564        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
565        vec3 p1(r, 0.f, 0.f);
566
567        for (int i = 0; i < nsides; i++)
568        {
569            AppendQuadVert(p1);
570            if (fade)
571                SetCurVertColor(m_color2);
572            AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
573            p1 = rotmat * p1;
574        }
575    }
576
577    void AppendSimpleTriangle(float size, int fade = 0)
578    {
579        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
580        vec3 p(0.f, 0.f, size);
581
582        AppendQuadVert(p);
583        p = m * p;
584        AppendQuadVert(p);
585        if (fade)
586            SetCurVertColor(m_color2);
587        p = m * p;
588        AppendQuadVert(p);
589        if (fade)
590            SetCurVertColor(m_color2);
591
592        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
593    }
594
595    void AppendSimpleQuad(float size, int fade = 0)
596    {
597        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
598    }
599
600    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
601    {
602        AppendQuadVert(vec3(p2.x, z, -p1.y));
603        AppendQuadVert(vec3(p2.x, z, -p2.y));
604        AppendQuadVert(vec3(p1.x, z, -p2.y));
605        if (fade)
606            SetCurVertColor(m_color2);
607        AppendQuadVert(vec3(p1.x, z, -p1.y));
608        if (fade)
609            SetCurVertColor(m_color2);
610
611        AppendQuad(3, 2, 1, 0, m_vert.Count() - 4);
612        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
613    }
614
615    void AppendCog(int nbsides, float h, float r1, float r2,
616                   float r12, float r22, float sidemul, int offset)
617    {
618        int qibase = m_quadidx.Count();
619        int vbase = m_vert.Count();
620
621        AppendQuadVert(vec3(0.f, h * .5f, 0.f));
622        AppendQuadVert(vec3(0.f, h * -.5f, 0.f));
623        SetCurVertColor(m_color2);
624
625        mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
626        mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
627        mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
628
629        vec3 p[8];
630
631        p[0] = vec3(r1, h * .5f, 0.f);
632        p[1] = rotmat * p[0];
633        p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
634        p[3] = smat2 * (rotmat * p[2]);
635
636        p[4] = vec3(r2, h * -.5f, 0.f);
637        p[5] = rotmat * p[4];
638        p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
639        p[7] = smat2 * (rotmat * p[6]);
640
641        if (offset & 1)
642            for (int n = 0; n < 8; n++)
643                p[n] = rotmat * p[n];
644
645        rotmat = rotmat * rotmat;
646
647        for (int i = 0; i < nbsides; i++)
648        {
649            /* Each vertex will share three faces, so three different
650             * normals, therefore we add each vertex three times. */
651            for (int n = 0; n < 24; n++)
652            {
653                AppendQuadVert(p[n / 3]);
654                if (n / 3 >= 4)
655                    SetCurVertColor(m_color2);
656            }
657
658            int j = 24 * i, k = 24 * ((i + 1) % nbsides);
659
660            /* The top and bottom faces */
661            AppendQuad(0, j + 2, j + 5, k + 2, vbase);
662            AppendQuad(1, k + 14, j + 17, j + 14, vbase);
663            AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
664            AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
665
666            /* The side quads */
667            AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
668            AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
669            AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
670            AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
671
672            for (int n = 0; n < 8; n++)
673                p[n] = rotmat * p[n];
674        }
675
676        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
677    }
678
679private:
680    vec4 m_color, m_color2;
681    Array<uint16_t> m_triidx, m_quadidx;
682    Array<vec3, vec3, vec4> m_vert;
683    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
684
685    /* FIXME: put this in a separate class so that we can copy meshes. */
686    struct
687    {
688        Shader *shader;
689        ShaderAttrib coord, norm, color;
690        ShaderUniform modelview, proj, normalmat, damage;
691        VertexDeclaration *vdecl;
692        VertexBuffer *vbo;
693        IndexBuffer *ibo;
694        int vertexcount, indexcount;
695    }
696    m_gpu;
697};
698
699#endif /* __MESH_H__ */
700
Note: See TracBrowser for help on using the repository browser.