source: trunk/orbital/mesh.h @ 1424

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

orbital: port the gun command compiler to our bison/flex system.

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