source: trunk/orbital/mesh.h @ 1339

Last change on this file since 1339 was 1339, checked in by sam, 9 years ago

orbital: fix shader compilation.

  • Property svn:keywords set to Id
File size: 28.2 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
12#include "CommandParser.h"
13
14#if !defined __MESH_H__
15#define __MESH_H__
16
17class Mesh : public CommandParser
18{
19public:
20    Mesh()
21      : m_color(0), m_color2(0),
22        m_vert_cursor(0), m_quadidx_cursor(0), m_triidx_cursor(0)
23    {}
24
25    virtual void SwitchCommand(char const *&command)
26    {
27        vec4 v4;
28        vec3 v3;
29        float f1, f2, f3, f4, f5, f6, f7, f8;
30
31                const char *&p = command;
32        {
33#define CASE(str) if (CheckCommand(str, p))
34                 CASE("scb") { p = GetArg(p, v4); SetCurColor2(v4); }
35            else CASE("sc")  { p = GetArg(p, v4); SetCurColor(v4); }
36            else CASE("fl")  { Flush(); }
37            else CASE("tx")  { p = GetArg(p, f1); Translate(vec3(f1, 0, 0)); }
38            else CASE("ty")  { p = GetArg(p, f1); Translate(vec3(0, f1, 0)); }
39            else CASE("tz")  { p = GetArg(p, f1); Translate(vec3(0, 0, f1)); }
40            else CASE("t")   { p = GetArg(p, v3); Translate(v3); }
41            else CASE("rx")  { p = GetArg(p, f1); RotateX(f1); }
42            else CASE("ry")  { p = GetArg(p, f1); RotateY(f1); }
43            else CASE("rz")  { p = GetArg(p, f1); RotateZ(f1); }
44            else CASE("tax") { p = GetArg(p, f1, f2, f3); TaperX(f1, f2, f3); }
45            else CASE("tay") { p = GetArg(p, f1, f2, f3); TaperY(f1, f2, f3); }
46            else CASE("taz") { p = GetArg(p, f1, f2, f3); TaperZ(f1, f2, f3); }
47            else CASE("sx")  { p = GetArg(p, f1); Scale(vec3(f1, 1, 1)); }
48            else CASE("sy")  { p = GetArg(p, f1); Scale(vec3(1, f1, 1)); }
49            else CASE("sz")  { p = GetArg(p, f1); Scale(vec3(1, 1, f1)); }
50            else CASE("s")   { p = GetArg(p, v3); Scale(v3); }
51            else CASE("mx")  { MirrorX(); }
52            else CASE("my")  { MirrorY(); }
53            else CASE("mz")  { MirrorZ(); }
54            else CASE("ac")  { p = GetArg(p, f1, f2, f3); p = GetArg(p, f4, f5, f6); AppendCylinder((int)f1, f2, f3, f4, (int)f5, (int)f6); }
55            else CASE("ab")  { p = GetArg(p, v3); AppendBox(v3); }
56            else CASE("ascb") { p = GetArg(p, v3, f1); AppendSmoothChamfBox(v3, f1); }
57            else CASE("afcb") { p = GetArg(p, v3, f1); AppendFlatChamfBox(v3, f1); }
58            else CASE("asph") { p = GetArg(p, f1); p = GetArg(p, v3); AppendSphere((int)f1, v3); }
59            else CASE("as")  { p = GetArg(p, f1, f2, f3, f4, f5); AppendStar((int)f1, f2, f3, (int)f4, (int)f5); }
60            else CASE("aes") { p = GetArg(p, f1, f2, f3, f4); AppendExpandedStar((int)f1, f2, f3, f4); }
61            else CASE("ad")  { p = GetArg(p, f1, f2, f3); AppendDisc((int)f1, f2, (int)f3); }
62            else CASE("at")  { p = GetArg(p, f1, f2); AppendSimpleTriangle(f1, (int)f2); }
63            else CASE("aq")  { p = GetArg(p, f1, f2); AppendSimpleQuad(f1, (int)f2); }
64            else CASE("acg") { p = GetArg(p, f1, f2, f3, f4); p = GetArg(p, f5, f6, f7, f8); AppendCog((int)f1, f2, f3, f4, f5, f6, f7, (int)f8); }
65            else CASE("irb") { MeshConvert(); }
66            else CASE("frb") { /* TODO */ }
67#undef CASE
68        }
69    }
70
71    virtual void Flush()
72    {
73        m_vert_cursor = m_vert.Count();
74        m_quadidx_cursor = m_quadidx.Count();
75        m_triidx_cursor = m_triidx.Count();
76    }
77
78    void MeshConvert()
79    {
80        m_gpu.shader = Shader::Create(
81#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
82            "#version 120\n"
83            "attribute vec3 in_Vertex;"
84            "attribute vec3 in_Normal;"
85            "attribute vec4 in_Color;"
86            "uniform mat4 in_ModelView;"
87            "uniform mat4 in_Proj;"
88            "uniform mat3 in_NormalMat;"
89            "varying vec4 pass_Color;"
90            ""
91            "void main(void)"
92            "{"
93                 /* Material properties */
94            "    vec3 specular_reflect = vec3(0.8, 0.75, 0.4);"
95            "    float specular_power = 60.f;"
96
97                 /* World properties */
98            "    float ambient_mul = 0.5f;"
99            "    vec3 light_dir = normalize(vec3(0.3, 0.3, 0.7));"
100            "    vec3 ambient_color = vec3(0.25, 0.2, 0.35);"
101            "    vec3 diffuse_color = vec3(1.0, 1.0, 0.6);"
102            "    vec3 specular_color = vec3(1.0, 1.0, 0.6);"
103
104            "    vec3 tnorm = normalize(in_NormalMat * in_Normal);"
105            "    vec4 eye = in_ModelView * vec4(in_Vertex, 1.0);"
106
107            "    vec3 s = light_dir;" /* normalize(eye - lightpos); */
108            "    vec3 v = normalize(-eye.xyz);"
109            "    vec3 r = reflect(-s, tnorm);"
110
111            "    vec3 ambient = ambient_color;"
112            "    float sdotn = max(dot(s, tnorm), 0.0);"
113            "    vec3 diffuse = diffuse_color * sdotn;"
114            "    vec3 specular = vec3(0.0, 0.0, 0.0);"
115            "    if (sdotn > 0.0)"
116            "        specular = specular_color * specular_reflect"
117            "                 * pow(max(dot(r, v), 0.0), specular_power);"
118            "    vec3 light = ambient + diffuse + specular;"
119
120            "    pass_Color = in_Color * vec4(light, 1.0);"
121            "    gl_Position = in_Proj * eye;"
122            "}",
123
124            "#version 120\n"
125            "varying vec4 pass_Color;"
126            ""
127            "void main(void) {"
128            "    gl_FragColor = pass_Color;"
129            "}"
130#else
131            "void main(float3 in_Vertex : POSITION,"
132            "          float3 in_Normal : NORMAL,"
133            "          float4 in_Color : COLOR,"
134            "          uniform float4x4 in_ModelView,"
135            "          uniform float4x4 in_Proj,"
136            "          uniform float3x3 in_NormalMat,"
137            "          out float4 out_Position : POSITION,"
138            "          out float4 pass_Color : COLOR)"
139            "{"
140            "    float3 specular_reflect = float3(0.8, 0.75, 0.4);"
141            "    float specular_power = 60.f;"
142            "    float ambient_mul = 0.5f;"
143            "    float3 light_dir = normalize(float3(0.3, 0.3, 0.7));"
144            "    float3 ambient_color = float3(0.25, 0.2, 0.35);"
145            "    float3 diffuse_color = float3(1.0, 1.0, 0.6);"
146            "    float3 specular_color = float3(1.0, 1.0, 0.6);"
147            "    float3 tnorm = normalize(mul(in_NormalMat, in_Normal));"
148            "    float4 eye = mul(in_ModelView, float4(in_Vertex, 1.0));"
149            "    float3 s = light_dir;"
150            "    float3 v = normalize(-eye.xyz);"
151            "    float3 r = reflect(-s, tnorm);"
152            "    float3 ambient = ambient_color;"
153            "    float sdotn = max(dot(s, tnorm), 0.0);"
154            "    float3 diffuse = diffuse_color * sdotn;"
155            "    float3 specular = float3(0.0, 0.0, 0.0);"
156            "    if (sdotn > 0.0)"
157            "        specular = specular_color * specular_reflect"
158            "                 * pow(max(dot(r, v), 0.0), specular_power);"
159            "    float3 light = ambient + diffuse + specular;"
160            "    pass_Color = in_Color * float4(light, 1.0);"
161            "    out_Position = mul(in_Proj, eye);"
162            "}",
163
164            "void main(float4 pass_Color : COLOR,"
165            "          out float4 out_FragColor : COLOR) {"
166            "    out_FragColor = pass_Color;"
167            "}"
168#endif
169        );
170        m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView");
171        m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
172        m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
173        m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
174                                              VertexUsage::Position, 0);
175        m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
176                                             VertexUsage::Normal, 0);
177        m_gpu.color = m_gpu.shader->GetAttribLocation("in_Color",
178                                              VertexUsage::Color, 0);
179
180        m_gpu.vdecl = new VertexDeclaration(
181            VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
182                                           VertexUsage::Normal,
183                                           VertexUsage::Color));
184
185        Array<vec3,vec3,u8vec4> vertexlist;
186        for (int i = 0; i < m_vert.Count(); i++)
187            vertexlist.Push(m_vert[i].m1,
188                            m_vert[i].m2,
189                            (u8vec4)(m_vert[i].m3 * 255.f));
190
191        Array<uint16_t> indexlist;
192        for (int i = 0; i < m_triidx.Count(); i += 3)
193        {
194            indexlist << m_triidx[i + 0];
195            indexlist << m_triidx[i + 1];
196            indexlist << m_triidx[i + 2];
197        }
198        for (int i = 0; i < m_quadidx.Count(); i += 4)
199        {
200            indexlist << m_quadidx[i + 0];
201            indexlist << m_quadidx[i + 1];
202            indexlist << m_quadidx[i + 2];
203
204            indexlist << m_quadidx[i + 0];
205            indexlist << m_quadidx[i + 2];
206            indexlist << m_quadidx[i + 3];
207        }
208
209        m_gpu.vbo = new VertexBuffer(vertexlist.Bytes());
210        void *mesh = m_gpu.vbo->Lock(0, 0);
211        memcpy(mesh, &vertexlist[0], vertexlist.Bytes());
212        m_gpu.vbo->Unlock();
213
214        m_gpu.ibo = new IndexBuffer(indexlist.Bytes());
215        void *indices = m_gpu.ibo->Lock(0, 0);
216        memcpy(indices, &indexlist[0], indexlist.Bytes());
217        m_gpu.ibo->Unlock();
218
219        m_gpu.vertexcount = vertexlist.Count();
220        m_gpu.indexcount = indexlist.Count();
221    }
222
223    void Render(mat4 const &model)
224    {
225        mat4 modelview = Scene::GetDefault()->GetViewMatrix() * model;
226        mat3 normalmat = transpose(inverse(mat3(modelview)));
227
228        m_gpu.shader->Bind();
229        m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
230        m_gpu.shader->SetUniform(m_gpu.proj, Scene::GetDefault()->GetProjMatrix());
231        m_gpu.shader->SetUniform(m_gpu.normalmat, normalmat);
232        m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord, m_gpu.norm, m_gpu.color);
233        m_gpu.vdecl->Bind();
234        m_gpu.ibo->Bind();
235        m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
236                                         0, 0, m_gpu.vertexcount,
237                                         0, m_gpu.indexcount / 3);
238        m_gpu.ibo->Unbind();
239        m_gpu.vdecl->Unbind();
240    }
241
242    void SetCurColor(vec4 const &color) { m_color = color; }
243    void SetCurColor2(vec4 const &color) { m_color2 = color; }
244
245    void AppendQuadVert(vec3 const &coord)
246    {
247        m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color);
248    }
249
250    void AppendDuplicateQuadVert(int i)
251    {
252        m_vert.Push(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3);
253    }
254
255    void AppendQuad(int i1, int i2, int i3, int i4, int base)
256    {
257        m_quadidx << base + i1;
258        m_quadidx << base + i2;
259        m_quadidx << base + i3;
260        m_quadidx << base + i4;
261    }
262
263    void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
264    {
265        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
266        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
267        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
268        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i4);
269    }
270
271    void AppendTriangle(int i1, int i2, int i3, int base)
272    {
273        m_triidx << base + i1;
274        m_triidx << base + i2;
275        m_triidx << base + i3;
276    }
277
278    void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
279    {
280        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
281        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
282        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
283    }
284
285    void ComputeQuadNormals(int start, int vcount)
286    {
287        for (int i = 0; i < vcount; i += 4)
288        {
289            vec3 v0 = m_vert[m_quadidx[start + i + 2]].m1
290                    - m_vert[m_quadidx[start + i + 0]].m1;
291            vec3 v1 = m_vert[m_quadidx[start + i + 1]].m1
292                    - m_vert[m_quadidx[start + i + 0]].m1;
293            vec3 n = normalize(cross(v1, v0));
294
295            for (int j = 0; j < 4; j++)
296                m_vert[m_quadidx[start + i + j]].m2 = n;
297        }
298    }
299
300    void ComputeTriNormals(int start, int vcount)
301    {
302        for (int i = 0; i < vcount; i += 3)
303        {
304            vec3 v0 = m_vert[m_triidx[start + i + 2]].m1
305                    - m_vert[m_triidx[start + i + 0]].m1;
306            vec3 v1 = m_vert[m_triidx[start + i + 1]].m1
307                    - m_vert[m_triidx[start + i + 0]].m1;
308            vec3 n = normalize(cross(v1, v0));
309
310            for (int j = 0; j < 3; j++)
311                m_vert[m_triidx[start + i + j]].m2 = n;
312        }
313    }
314
315    void SetVertColor(vec4 const &color)
316    {
317        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
318            m_vert[i].m3 = color;
319    }
320
321    void SetCurVertNormal(vec3 const &normal)
322    {
323        m_vert[m_vert.Count() - 1].m2 = normal;
324    }
325
326    void SetCurVertColor(vec4 const &color)
327    {
328        m_vert[m_vert.Count() - 1].m3 = color;
329    }
330
331    void Translate(vec3 const &v)
332    {
333        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
334            m_vert[i].m1 += v;
335    }
336
337    void RotateX(float t) { Rotate(t, vec3(1, 0, 0)); }
338    void RotateY(float t) { Rotate(t, vec3(0, 1, 0)); }
339    void RotateZ(float t) { Rotate(t, vec3(0, 0, 1)); }
340
341    void Rotate(float t, vec3 const &axis)
342    {
343        mat3 m = mat3::rotate(t, axis);
344        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
345        {
346            m_vert[i].m1 = m * m_vert[i].m1;
347            m_vert[i].m2 = m * m_vert[i].m2;
348        }
349    }
350
351    void TaperX(float y, float z, float xoff)
352    {
353        /* FIXME: this code breaks normals! */
354        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
355        {
356            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
357            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
358        }
359    }
360
361    void TaperY(float x, float z, float yoff)
362    {
363        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
364        {
365            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
366            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
367        }
368    }
369
370    void TaperZ(float x, float y, float zoff)
371    {
372        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
373        {
374            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
375            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
376        }
377    }
378
379    void Scale(vec3 const &s)
380    {
381        vec3 const invs = vec3(1) / s;
382
383        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
384        {
385            m_vert[i].m1 *= s;
386            m_vert[i].m2 = normalize(m_vert[i].m2 * invs);
387        }
388
389        /* Flip winding if the scaling involves mirroring */
390        if (s.x * s.y * s.z < 0)
391        {
392            for (int i = m_quadidx_cursor; i < m_quadidx.Count(); i += 2)
393            {
394                uint16_t tmp = m_quadidx[i + 0];
395                m_quadidx[i + 0] = m_quadidx[i + 1];
396                m_quadidx[i + 1] = tmp;
397            }
398
399            for (int i = m_triidx_cursor; i < m_triidx.Count(); i += 3)
400            {
401                uint16_t tmp = m_triidx[i + 0];
402                m_triidx[i + 0] = m_triidx[i + 1];
403                m_triidx[i + 1] = tmp;
404            }
405        }
406    }
407
408    void MirrorX() { Duplicate(); Scale(vec3(-1, 1, 1)); }
409    void MirrorY() { Duplicate(); Scale(vec3(1, -1, 1)); }
410    void MirrorZ() { Duplicate(); Scale(vec3(1, 1, -1)); }
411
412    void Duplicate()
413    {
414        int vlen = m_vert.Count() - m_vert_cursor;
415        int qlen = m_quadidx.Count() - m_quadidx_cursor;
416        int tlen = m_triidx.Count() - m_triidx_cursor;
417
418        for (int i = 0; i < vlen; i++)
419            m_vert << m_vert[m_vert_cursor++];
420
421        for (int i = 0; i < qlen; i++)
422            m_quadidx << m_quadidx[m_quadidx_cursor++] + vlen;
423
424        for (int i = 0; i < tlen; i++)
425            m_triidx << m_triidx[m_triidx_cursor++] + vlen;
426    }
427
428    void AppendCylinder(int nsides, float h, float r1, float r2,
429                        int dualside, int smooth)
430    {
431        int vbase = m_vert.Count();
432
433        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
434        vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
435
436        /* Construct normal */
437        n = p2;
438        n.y = r1 * (r1 - r2) / h;
439        if (!smooth)
440            n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
441        n = normalize(n);
442
443        /* FIXME: normals should be flipped in two-sided mode, but that
444         * means duplicating the vertices again... */
445        for (int i = 0; i < nsides; i++)
446        {
447            AppendQuadVert(p1); SetCurVertNormal(n);
448            AppendQuadVert(p2); SetCurVertNormal(n);
449            SetCurVertColor(m_color2);
450
451            if (smooth)
452            {
453                int j = (i + 1) % nsides;
454                AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
455                if (dualside)
456                    AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
457            }
458
459            p1 = rotmat * p1;
460            p2 = rotmat * p2;
461
462            if (!smooth)
463            {
464                AppendQuadVert(p1); SetCurVertNormal(n);
465                AppendQuadVert(p2); SetCurVertNormal(n);
466                SetCurVertColor(m_color2);
467
468                AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
469                if (dualside)
470                    AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
471            }
472
473            n = rotmat * n;
474        }
475    }
476
477    void AppendSphere(int ndivisions, vec3 const &size)
478    {
479        ndivisions *= 2;
480
481        int ibase = m_quadidx.Count();
482        int vbase = m_vert.Count();
483
484        vec3 d = size * 0.5f;
485        float const pi = std::acos(-1.0f);
486
487        Array<vec2> table;
488        for (int i = 0; i <= ndivisions; i++)
489            table.Push(vec2(std::sin(pi * 2 / ndivisions * i) + 1e-5f,
490                            std::cos(pi * 2 / ndivisions * i) + 1e-5f));
491
492        for (int j = 0; j <= ndivisions / 2; j++)
493            for (int i = 0; i < ndivisions; i++)
494            {
495                int j2 = j + 1;
496                int i2 = (i + 1) % ndivisions;
497
498                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
499                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
500                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
501                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
502            }
503
504        for (int i = vbase; i < m_vert.Count(); i += 4)
505            AppendQuad(0, 1, 2, 3, i);
506
507        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
508    }
509
510    void AppendBox(vec3 const &size, float chamf = 0.f)
511    {
512        AppendBox(size, chamf, false);
513    }
514
515    void AppendSmoothChamfBox(vec3 const &size, float chamf)
516    {
517        AppendBox(size, chamf, true);
518    }
519
520    void AppendFlatChamfBox(vec3 const &size, float chamf)
521    {
522        AppendBox(size, chamf, false);
523    }
524
525    void AppendBox(vec3 const &size, float chamf, bool smooth)
526    {
527        int vbase = m_vert.Count();
528        int qibase = m_quadidx.Count();
529        int tibase = m_triidx.Count();
530
531        vec3 d = size * 0.5f;
532
533        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
534        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
535        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
536        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
537
538        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
539        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
540        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
541        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
542
543        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
544        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
545        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
546        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
547
548        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
549        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
550        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
551        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
552
553        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
554        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
555        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
556        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
557
558        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
559        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
560        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
561        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
562
563        /* The 6 quads on each side of the box */
564        for (int i = 0; i < 24; i += 4)
565            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
566
567        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
568        qibase = m_quadidx.Count();
569
570        /* The 8 quads at each edge of the box */
571        if (chamf)
572        {
573            static int const quadlist[48] =
574            {
575                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
576                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
577                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
578            };
579
580            for (int i = 0; i < 48; i += 4)
581            {
582                if (smooth)
583                    AppendQuad(quadlist[i], quadlist[i + 1],
584                               quadlist[i + 2], quadlist[i + 3], vbase);
585                else
586                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
587                                     quadlist[i + 2], quadlist[i + 3], vbase);
588            }
589        }
590
591        /* The 8 triangles at each corner of the box */
592        if (chamf)
593        {
594            static int const trilist[24] =
595            {
596                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
597                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
598            };
599
600            for (int i = 0; i < 24; i += 3)
601            {
602                if (smooth)
603                    AppendTriangle(trilist[i], trilist[i + 1],
604                                   trilist[i + 2], vbase);
605                else
606                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
607                                                 trilist[i + 2], vbase);
608            }
609        }
610
611        if (!smooth)
612        {
613            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
614            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
615        }
616    }
617
618    void AppendStar(int nbranches, float r1, float r2,
619                    int fade = 0, int fade2 = 0)
620    {
621        int vbase = m_vert.Count();
622
623        AppendQuadVert(vec3(0.f, 0.f, 0.f));
624
625        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
626        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
627
628        p2 = rotmat * p2;
629        rotmat = rotmat * rotmat;
630
631        for (int i = 0; i < nbranches; i++)
632        {
633            AppendQuadVert(p1);
634            if (fade2)
635                SetCurVertColor(m_color2);
636
637            AppendQuadVert(p2);
638            if (fade)
639                SetCurVertColor(m_color2);
640
641            AppendQuad(0, (2 * i + 3) % (2 * nbranches),
642                       2 * i + 2, 2 * i + 1, vbase);
643
644            p1 = rotmat * p1;
645            p2 = rotmat * p2;
646        }
647    }
648
649    void AppendExpandedStar(int nbranches, float r1, float r2, float extrar)
650    {
651        int vbase = m_vert.Count();
652
653        AppendQuadVert(vec3(0.f, 0.f, 0.f));
654
655        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
656        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
657             p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
658
659        p2 = rotmat * p2;
660        p4 = rotmat * p4;
661        rotmat = rotmat * rotmat;
662
663        for (int i = 0; i < nbranches; i++)
664        {
665            AppendQuadVert(p1);
666            AppendQuadVert(p2);
667            AppendQuadVert(p3); SetCurVertColor(m_color2);
668            AppendQuadVert(p4); SetCurVertColor(m_color2);
669
670            int j = (i + 1) % nbranches;
671            AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
672            AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
673            AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
674
675            p1 = rotmat * p1;
676            p2 = rotmat * p2;
677            p3 = rotmat * p3;
678            p4 = rotmat * p4;
679        }
680    }
681
682    void AppendDisc(int nsides, float r, int fade = 0)
683    {
684        int vbase = m_vert.Count();
685
686        AppendQuadVert(vec3(0.f, 0.f, 0.f));
687
688        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
689        vec3 p1(r, 0.f, 0.f);
690
691        for (int i = 0; i < nsides; i++)
692        {
693            AppendQuadVert(p1);
694            if (fade)
695                SetCurVertColor(m_color2);
696            AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
697            p1 = rotmat * p1;
698        }
699    }
700
701    void AppendSimpleTriangle(float size, int fade = 0)
702    {
703        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
704        vec3 p(0.f, 0.f, size);
705
706        AppendQuadVert(p);
707        p = m * p;
708        AppendQuadVert(p);
709        if (fade)
710            SetCurVertColor(m_color2);
711        p = m * p;
712        AppendQuadVert(p);
713        if (fade)
714            SetCurVertColor(m_color2);
715
716        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
717    }
718
719    void AppendSimpleQuad(float size, int fade = 0)
720    {
721        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
722    }
723
724    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
725    {
726        AppendQuadVert(vec3(p2.x, z, -p1.y));
727        AppendQuadVert(vec3(p2.x, z, -p2.y));
728        AppendQuadVert(vec3(p1.x, z, -p2.y));
729        if (fade)
730            SetCurVertColor(m_color2);
731        AppendQuadVert(vec3(p1.x, z, -p1.y));
732        if (fade)
733            SetCurVertColor(m_color2);
734
735        AppendQuad(0, 3, 2, 1, m_vert.Count() - 4);
736        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
737    }
738
739    void AppendCog(int nbsides, float h, float r1, float r2,
740                   float r12, float r22, float sidemul, int offset)
741    {
742        int qibase = m_quadidx.Count();
743        int vbase = m_vert.Count();
744
745        AppendQuadVert(vec3(0.f, h * .5f, 0.f));
746        AppendQuadVert(vec3(0.f, h * -.5f, 0.f));
747        SetCurVertColor(m_color2);
748
749        mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
750        mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
751        mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
752
753        vec3 p[8];
754
755        p[0] = vec3(r1, h * .5f, 0.f);
756        p[1] = rotmat * p[0];
757        p[2] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f));
758        p[3] = smat2 * (rotmat * p[2]);
759
760        p[4] = vec3(r2, h * -.5f, 0.f);
761        p[5] = rotmat * p[4];
762        p[6] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f));
763        p[7] = smat2 * (rotmat * p[6]);
764
765        if (offset & 1)
766            for (int n = 0; n < 8; n++)
767                p[n] = rotmat * p[n];
768
769        rotmat = rotmat * rotmat;
770
771        for (int i = 0; i < nbsides; i++)
772        {
773            /* Each vertex will share three faces, so three different
774             * normals, therefore we add each vertex three times. */
775            for (int n = 0; n < 24; n++)
776            {
777                AppendQuadVert(p[n / 3]);
778                if (n / 3 >= 4)
779                    SetCurVertColor(m_color2);
780            }
781
782            int j = 24 * i, k = 24 * ((i + 1) % nbsides);
783
784            /* The top and bottom faces */
785            AppendQuad(0, j + 2, j + 5, k + 2, vbase);
786            AppendQuad(1, k + 14, j + 17, j + 14, vbase);
787            AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
788            AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
789
790            /* The side quads */
791            AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
792            AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
793            AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
794            AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
795
796            for (int n = 0; n < 8; n++)
797                p[n] = rotmat * p[n];
798        }
799
800        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
801    }
802
803private:
804    vec4 m_color, m_color2;
805    Array<uint16_t> m_triidx, m_quadidx;
806    Array<vec3, vec3, vec4> m_vert;
807    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
808
809    /* FIXME: put this in a separate class so that we can copy meshes. */
810    struct
811    {
812        Shader *shader;
813        ShaderAttrib coord, norm, color;
814        ShaderUniform modelview, proj, normalmat;
815        VertexDeclaration *vdecl;
816        VertexBuffer *vbo;
817        IndexBuffer *ibo;
818        int vertexcount, indexcount;
819    }
820    m_gpu;
821};
822
823#endif /* __MESH_H__ */
824
Note: See TracBrowser for help on using the repository browser.