source: trunk/orbital/mesh.h @ 1275

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

orbital: port the current shader to HLSL (together with its bugs for now).

  • Property svn:keywords set to Id
File size: 25.5 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#if !defined __MESH_H__
13#define __MESH_H__
14
15class Mesh
16{
17public:
18    Mesh()
19      : m_color(0), m_color2(0),
20        m_vert_cursor(0), m_quadidx_cursor(0), m_triidx_cursor(0)
21    {}
22
23    void SendCommand(char const *command)
24    {
25        vec4 v4;
26        vec3 v3;
27        float f1, f2, f3, f4, f5;
28
29        for (char const *p = command; p && *p; )
30        {
31#define CASE(str) if (!strncmp(p, str, strlen(str)) \
32                       && (p[strlen(str)] < 'a' || p[strlen(str)] > 'z') \
33                       && (p += strlen(str)))
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")  { /* TODO */ }
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, v3, f1); AppendSphere(v3, (int)f1); }
59            else CASE("as")  { p = GetArg(p, f1, f2, f3, f4, f5); AppendStar((int)f1, f2, f4, (int)f5, (int)f5); }
60            else CASE("aes") { /* TODO */ }
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") { /* TODO */ }
65            else CASE("irb") { MeshConvert(); }
66            else CASE("frb") { /* TODO */ }
67#undef CASE
68
69            /* Skip all remaining letters */
70            while (*p && *p >= 'a' && *p <= 'z')
71                p++;
72            /* ... and skip everything until next letter */
73            while (*p && (*p < 'a' || *p > 'z'))
74                p++;
75        }
76    }
77
78    static char const *GetArg(char const *p, float &f)
79    {
80        float sign = 1.0f;
81        f = 0.0f;
82        /* 1) Skip commas until the first valid character, 2) read all
83         * the minus signs, 3) read all the digits, 4) skip all the dots,
84         * if any, 5) read all the remaining digits, if any. */
85        for ( ; *p == ','; p++)
86            ;
87        for ( ; *p == '-'; p++)
88            sign = -sign;
89        for ( ; *p >= '0' && *p <= '9'; p++)
90            f = f * 10.f + (*p - '0');
91        for ( ; *p == '.'; p++)
92            ;
93        for (float div = 10.f; *p >= '0' && *p <= '9'; div *= 10.f)
94            f += (*p++ - '0') / div;
95        f *= sign;
96        return p;
97    }
98
99    static char const *GetArg(char const *p, float &f1, float &f2)
100    {
101        return GetArg(GetArg(p, f1), f2);
102    }
103
104    static char const *GetArg(char const *p, float &f1, float &f2, float &f3)
105    {
106        return GetArg(GetArg(p, f1, f2), f3);
107    }
108
109    static char const *GetArg(char const *p, float &f1, float &f2,
110                                             float &f3, float &f4)
111    {
112        return GetArg(GetArg(p, f1, f2, f3), f4);
113    }
114
115    static char const *GetArg(char const *p, float &f1, float &f2, float &f3,
116                                             float &f4, float &f5)
117    {
118        return GetArg(GetArg(p, f1, f2, f3, f4), f5);
119    }
120
121    static char const *GetArg(char const *p, vec3 &v)
122    {
123        return GetArg(p, v.x, v.y, v.z);
124    }
125
126    static char const *GetArg(char const *p, vec3 &v, float &f)
127    {
128        return GetArg(p, v.x, v.y, v.z, f);
129    }
130
131    static char const *GetArg(char const *p, vec4 &v)
132    {
133        return GetArg(p, v.x, v.y, v.z, v.w);
134    }
135
136    void Flush()
137    {
138        m_vert_cursor = m_vert.Count();
139        m_quadidx_cursor = m_quadidx.Count();
140        m_triidx_cursor = m_triidx.Count();
141    }
142
143    void MeshConvert()
144    {
145        m_gpu.shader = Shader::Create(
146#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
147            "#version 120\n"
148            "attribute vec3 in_Vertex;"
149            "attribute vec3 in_Normal;"
150            "attribute vec4 in_Color;"
151            "uniform mat4 in_ModelView;"
152            "uniform mat4 in_Proj;"
153            "uniform mat3 in_NormalMat;"
154            "varying vec4 pass_Color;"
155            ""
156            "void main(void)"
157            "{"
158                 /* Diffuse information -- the level decides this */
159
160                 /* Global shit */
161            "    float alpha_mul = 1.0f;"
162
163                 /* Ambient: global constant */
164            "    float ambient_mul = 0.5f;"
165
166                 /* Diffuse: the level should decide of these values */
167            "    vec3 diffuse_dir = normalize(vec3(-0.7, -0.7, -0.4));"
168            "    vec4 frontColor = vec4(1.0, 1.0, 1.0, 1.0);"
169            "    vec4 backColor = vec4(0.3, 0.2, 0.0, 1.0);"
170
171            "    vec3 world_normal = normalize(in_NormalMat * in_Normal);"
172            "    float d = dot(world_normal, diffuse_dir);"
173            "    vec2 diffuse_mul = max(vec2(-d, d), 0.0);"
174            "    diffuse_mul[0] = min(diffuse_mul[0] + ambient_mul, 1.0);"
175
176                 /* Specular: global settings */
177            "    vec4 spec_col = vec4(0.8, 0.85, 0.4, 1.0);"
178            "    vec3 spec_dir = normalize(vec3(-0.7, -0.7, 0.4));"
179            "    float spec_exp = 60.0f;"
180
181            "    float spec_mul = max(-dot(world_normal, spec_dir), 0.0);"
182            "    spec_mul = clamp(pow(spec_mul, spec_exp), 0.0, 1.0);"
183
184
185            "    vec4 TmpColor = frontColor * in_Color;"
186                 /* NOTE: use saturate() in HLSL */
187            "    pass_Color = clamp(diffuse_mul[0] * TmpColor"
188            "                        + diffuse_mul[1] * backColor"
189            "                        + spec_mul * spec_col, 0.0, 1.0);"
190            "    pass_Color.a *= alpha_mul;"
191
192            "    vec4 viewPosition = in_ModelView * vec4(in_Vertex, 1.0);"
193            "    gl_Position = in_Proj * viewPosition;"
194            "}",
195
196            "#version 120\n"
197            "varying vec4 pass_Color;"
198            ""
199            "void main(void) {"
200            "    gl_FragColor = pass_Color;"
201            "}"
202#else
203            "void main(float3 in_Vertex : POSITION,"
204            "          float3 in_Normal : NORMAL,"
205            "          float4 in_Color : COLOR,"
206            "          uniform float4x4 in_ModelView,"
207            "          uniform float4x4 in_Proj,"
208            "          uniform float3x3 in_NormalMat,"
209            "          out float4 out_Position : POSITION,"
210            "          out float4 pass_Color : COLOR)"
211            "{"
212            "    float alpha_mul = 1.0f;"
213            "    float ambient_mul = 0.5f;"
214            "    float3 diffuse_dir = normalize(float3(-0.7, -0.7, -0.4));"
215            "    float4 frontColor = float4(1.0, 1.0, 1.0, 1.0);"
216            "    float4 backColor = float4(0.3, 0.2, 0.0, 1.0);"
217            "    float3 world_normal = normalize(mul(in_NormalMat, in_Normal));"
218            "    float d = dot(world_normal, diffuse_dir);"
219            "    float2 diffuse_mul = max(float2(-d, d), 0.0);"
220            "    diffuse_mul[0] = min(diffuse_mul[0] + ambient_mul, 1.0);"
221            "    float4 spec_col = float4(0.8, 0.85, 0.4, 1.0);"
222            "    float3 spec_dir = normalize(float3(-0.7, -0.7, 0.4));"
223            "    float spec_exp = 60.0f;"
224            "    float spec_mul = max(-dot(world_normal, spec_dir), 0.0);"
225            "    spec_mul = saturate(pow(spec_mul, spec_exp));"
226            "    float4 TmpColor = frontColor * in_Color;"
227            "    pass_Color = saturate(diffuse_mul[0] * TmpColor"
228            "                           + diffuse_mul[1] * backColor"
229            "                           + spec_mul * spec_col);"
230            "    pass_Color.a *= alpha_mul;"
231            "    float4 viewPosition = mul(in_ModelView, float4(in_Vertex, 1.0));"
232            "    out_Position = mul(in_Proj, viewPosition);"
233            "}",
234
235            "void main(float4 pass_Color : COLOR,"
236            "          out float4 out_FragColor : COLOR) {"
237            "    out_FragColor = pass_Color;"
238            "}"
239#endif
240        );
241        m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView");
242        m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
243        m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
244        m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
245                                              VertexUsage::Position, 0);
246        m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
247                                             VertexUsage::Normal, 0);
248        m_gpu.color = m_gpu.shader->GetAttribLocation("in_Color",
249                                              VertexUsage::Color, 0);
250
251        m_gpu.vdecl = new VertexDeclaration(
252            VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
253                                           VertexUsage::Normal,
254                                           VertexUsage::Color));
255
256        Array<vec3,vec3,u8vec4> vertexlist;
257        for (int i = 0; i < m_vert.Count(); i++)
258            vertexlist.Append(m_vert[i].m1,
259                              m_vert[i].m2,
260                              (u8vec4)(m_vert[i].m3 * 255.f));
261
262        Array<uint16_t> indexlist;
263        for (int i = 0; i < m_triidx.Count(); i += 3)
264        {
265            indexlist << m_triidx[i + 0];
266            indexlist << m_triidx[i + 1];
267            indexlist << m_triidx[i + 2];
268        }
269        for (int i = 0; i < m_quadidx.Count(); i += 4)
270        {
271            indexlist << m_quadidx[i + 0];
272            indexlist << m_quadidx[i + 1];
273            indexlist << m_quadidx[i + 2];
274
275            indexlist << m_quadidx[i + 0];
276            indexlist << m_quadidx[i + 2];
277            indexlist << m_quadidx[i + 3];
278        }
279
280        m_gpu.vbo = new VertexBuffer(vertexlist.Bytes());
281        void *mesh = m_gpu.vbo->Lock(0, 0);
282        memcpy(mesh, &vertexlist[0], vertexlist.Bytes());
283        m_gpu.vbo->Unlock();
284
285        m_gpu.ibo = new IndexBuffer(indexlist.Bytes());
286        void *indices = m_gpu.ibo->Lock(0, 0);
287        memcpy(indices, &indexlist[0], indexlist.Bytes());
288        m_gpu.ibo->Unlock();
289
290        m_gpu.vertexcount = vertexlist.Count();
291        m_gpu.indexcount = indexlist.Count();
292    }
293
294    void Render(mat4 const &modelview, mat4 const &proj, mat3 const &normalmat)
295    {
296        m_gpu.shader->Bind();
297        m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
298        m_gpu.shader->SetUniform(m_gpu.proj, proj);
299        m_gpu.shader->SetUniform(m_gpu.normalmat, normalmat);
300        m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord, m_gpu.norm, m_gpu.color);
301        m_gpu.vdecl->Bind();
302        m_gpu.ibo->Bind();
303        m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
304                                         0, 0, m_gpu.vertexcount,
305                                         0, m_gpu.indexcount / 3);
306        m_gpu.ibo->Unbind();
307        m_gpu.vdecl->Unbind();
308    }
309
310    void SetCurColor(vec4 const &color) { m_color = color; }
311    void SetCurColor2(vec4 const &color) { m_color2 = color; }
312
313    void AppendQuadVert(vec3 const &coord)
314    {
315        m_vert.Append(coord, vec3(0.f, 1.f, 0.f), m_color);
316    }
317
318    void AppendDuplicateQuadVert(int i)
319    {
320        m_vert.Append(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3);
321    }
322
323    void AppendQuad(int i1, int i2, int i3, int i4, int base)
324    {
325        m_quadidx << base + i1;
326        m_quadidx << base + i2;
327        m_quadidx << base + i3;
328        m_quadidx << base + i4;
329    }
330
331    void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
332    {
333        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
334        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
335        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
336        m_quadidx << m_vert.Count(); AppendDuplicateQuadVert(base + i4);
337    }
338
339    void AppendTriangle(int i1, int i2, int i3, int base)
340    {
341        m_triidx << base + i1;
342        m_triidx << base + i2;
343        m_triidx << base + i3;
344    }
345
346    void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
347    {
348        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i1);
349        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i2);
350        m_triidx << m_vert.Count(); AppendDuplicateQuadVert(base + i3);
351    }
352
353    void ComputeQuadNormals(int start, int vcount)
354    {
355        for (int i = 0; i < vcount; i += 4)
356        {
357            vec3 v0 = m_vert[m_quadidx[start + i + 2]].m1
358                    - m_vert[m_quadidx[start + i + 0]].m1;
359            vec3 v1 = m_vert[m_quadidx[start + i + 1]].m1
360                    - m_vert[m_quadidx[start + i + 0]].m1;
361            vec3 n = normalize(cross(v1, v0));
362
363            for (int j = 0; j < 4; j++)
364                m_vert[m_quadidx[start + i + j]].m2 = n;
365        }
366    }
367
368    void ComputeTriNormals(int start, int vcount)
369    {
370        for (int i = 0; i < vcount; i += 3)
371        {
372            vec3 v0 = m_vert[m_triidx[start + i + 2]].m1
373                    - m_vert[m_triidx[start + i + 0]].m1;
374            vec3 v1 = m_vert[m_triidx[start + i + 1]].m1
375                    - m_vert[m_triidx[start + i + 0]].m1;
376            vec3 n = normalize(cross(v1, v0));
377
378            for (int j = 0; j < 3; j++)
379                m_vert[m_triidx[start + i + j]].m2 = n;
380        }
381    }
382
383    void SetVertColor(vec4 const &color)
384    {
385        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
386            m_vert[i].m3 = color;
387    }
388
389    void SetCurVertNormal(vec3 const &normal)
390    {
391        m_vert[m_vert.Count() - 1].m2 = normal;
392    }
393
394    void SetCurVertColor(vec4 const &color)
395    {
396        m_vert[m_vert.Count() - 1].m3 = color;
397    }
398
399    void Translate(vec3 const &v)
400    {
401        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
402            m_vert[i].m1 += v;
403    }
404
405    void RotateX(float t) { Rotate(t, vec3(1, 0, 0)); }
406    void RotateY(float t) { Rotate(t, vec3(0, 1, 0)); }
407    void RotateZ(float t) { Rotate(t, vec3(0, 0, 1)); }
408
409    void Rotate(float t, vec3 const &axis)
410    {
411        mat3 m = mat3::rotate(t, axis);
412        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
413        {
414            m_vert[i].m1 = m * m_vert[i].m1;
415            m_vert[i].m2 = m * m_vert[i].m2;
416        }
417    }
418
419    void TaperX(float y, float z, float xoff)
420    {
421        /* FIXME: this code breaks normals! */
422        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
423        {
424            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
425            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
426        }
427    }
428
429    void TaperY(float x, float z, float yoff)
430    {
431        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
432        {
433            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
434            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
435        }
436    }
437
438    void TaperZ(float x, float y, float zoff)
439    {
440        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
441        {
442            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
443            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
444        }
445    }
446
447    void Scale(vec3 const &s)
448    {
449        /* FIXME: this code breaks normals! */
450        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
451        {
452            m_vert[i].m1 *= s;
453            m_vert[i].m2 *= s;
454        }
455
456        // BH : TODO : not sure about this one
457        // Sam: not too sure either!
458        if (s.x * s.y * s.z < 0)
459        {
460            for (int i = m_quadidx_cursor; i < m_quadidx.Count(); i += 2)
461            {
462                uint16_t tmp = m_quadidx[i + 0];
463                m_quadidx[i + 0] = m_quadidx[i + 1];
464                m_quadidx[i + 1] = tmp;
465            }
466
467            for (int i = m_triidx_cursor; i < m_triidx.Count(); i += 3)
468            {
469                uint16_t tmp = m_triidx[i + 0];
470                m_triidx[i + 0] = m_triidx[i + 1];
471                m_triidx[i + 1] = tmp;
472            }
473        }
474    }
475
476    void MirrorX() { Duplicate(); Scale(vec3(-1, 1, 1)); }
477    void MirrorY() { Duplicate(); Scale(vec3(1, -1, 1)); }
478    void MirrorZ() { Duplicate(); Scale(vec3(1, 1, -1)); }
479
480    void Duplicate()
481    {
482        int vlen = m_vert.Count() - m_vert_cursor;
483        int qlen = m_quadidx.Count() - m_quadidx_cursor;
484        int tlen = m_triidx.Count() - m_triidx_cursor;
485
486        for (int i = 0; i < vlen; i++)
487            m_vert << m_vert[m_vert_cursor++];
488
489        for (int i = 0; i < qlen; i++)
490            m_quadidx << m_quadidx[m_quadidx_cursor++] + vlen;
491
492        for (int i = 0; i < tlen; i++)
493            m_triidx << m_triidx[m_triidx_cursor++] + vlen;
494    }
495
496    void AppendCylinder() {} /* TODO */
497
498    void AppendSphere(vec3 const &size, int divisions)
499    {
500        int ibase = m_quadidx.Count();
501        int vbase = m_vert.Count();
502
503        vec3 d = size * 0.5f;
504        float const pi = acos(-1.0f);
505
506        Array<vec2> table;
507        for (int i = 0; i <= divisions; i++)
508            table.Append(vec2(sin(pi * 2 / divisions * i) + 1e-5f,
509                              cos(pi * 2 / divisions * i) + 1e-5f));
510
511        for (int j = 0; j <= divisions / 2; j++)
512            for (int i = 0; i < divisions; i++)
513            {
514                int j2 = j + 1;
515                int i2 = (i + 1) % divisions;
516
517                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
518                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
519                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
520                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
521            }
522
523        for (int i = vbase; i < m_vert.Count(); i += 4)
524            AppendQuad(0, 1, 2, 3, i);
525
526        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
527    }
528
529    void AppendBox(vec3 const &size, float chamf = 0.f)
530    {
531        AppendBox(size, chamf, false);
532    }
533
534    void AppendSmoothChamfBox(vec3 const &size, float chamf)
535    {
536        AppendBox(size, chamf, true);
537    }
538
539    void AppendFlatChamfBox(vec3 const &size, float chamf)
540    {
541        AppendBox(size, chamf, false);
542    }
543
544    void AppendBox(vec3 const &size, float chamf, bool smooth)
545    {
546        int vbase = m_vert.Count();
547        int qibase = m_quadidx.Count();
548        int tibase = m_triidx.Count();
549
550        vec3 d = size * 0.5f;
551
552        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
553        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
554        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
555        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
556
557        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
558        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
559        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
560        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
561
562        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
563        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
564        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
565        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
566
567        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
568        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
569        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
570        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
571
572        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
573        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
574        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
575        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
576
577        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
578        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
579        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
580        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
581
582        /* The 6 quads on each side of the box */
583        for (int i = 0; i < 24; i += 4)
584            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
585
586        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
587        qibase = m_quadidx.Count();
588
589        /* The 8 quads at each edge of the box */
590        if (chamf)
591        {
592            static int const quadlist[48] =
593            {
594                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
595                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
596                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
597            };
598
599            for (int i = 0; i < 48; i += 4)
600            {
601                if (smooth)
602                    AppendQuad(quadlist[i], quadlist[i + 1],
603                               quadlist[i + 2], quadlist[i + 3], vbase);
604                else
605                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
606                                     quadlist[i + 2], quadlist[i + 3], vbase);
607            }
608        }
609
610        /* The 8 triangles at each corner of the box */
611        if (chamf)
612        {
613            static int const trilist[24] =
614            {
615                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
616                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
617            };
618
619            for (int i = 0; i < 24; i += 3)
620            {
621                if (smooth)
622                    AppendTriangle(trilist[i], trilist[i + 1],
623                                   trilist[i + 2], vbase);
624                else
625                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
626                                                 trilist[i + 2], vbase);
627            }
628        }
629
630        if (!smooth)
631        {
632            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
633            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
634        }
635    }
636
637    void AppendStar(int nbranches, float r1, float r2)
638    {
639        AppendStar(nbranches, r1, r2, 0, 0);
640    }
641
642    void AppendStar(int nbranches, float r1, float r2, int fade)
643    {
644        AppendStar(nbranches, r1, r2, fade, 0);
645    }
646
647    void AppendStar(int nbranches, float r1, float r2, int fade, int fade2)
648    {
649        int vbase = m_vert.Count();
650
651        AppendQuadVert(vec3(0.f, 0.f, 0.f));
652
653        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
654        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
655
656        p2 = rotmat * p2;
657        rotmat = rotmat * rotmat;
658
659        for (int i = 0; i < nbranches; i++)
660        {
661            AppendQuadVert(p1);
662            if (fade2)
663                SetCurVertColor(m_color2);
664
665            AppendQuadVert(p2);
666            if (fade)
667                SetCurVertColor(m_color2);
668
669            AppendQuad(0, (2 * i + 3) % (2 * nbranches),
670                       2 * i + 2, 2 * i + 1, vbase);
671
672            p1 = rotmat * p1;
673            p2 = rotmat * p2;
674        }
675    }
676
677    void AppendExpandedStar() {} /* TODO */
678
679    void AppendDisc(int nsides, float r, int fade = 0)
680    {
681        int vbase = m_vert.Count();
682
683        AppendQuadVert(vec3(0.f, 0.f, 0.f));
684
685        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
686        vec3 p1(r, 0.f, 0.f);
687
688        for (int i = 0; i < nsides; i++)
689        {
690            AppendQuadVert(p1);
691            if (fade)
692                SetCurVertColor(m_color2);
693            AppendTriangle(0, ((i + 1) % nsides) + 1, i + 1, vbase);
694            p1 = rotmat * p1;
695        }
696    }
697
698    void AppendSimpleTriangle(float size, int fade = 0)
699    {
700        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
701        vec3 p(0.f, 0.f, size);
702
703        AppendQuadVert(p);
704        p = m * p;
705        AppendQuadVert(p);
706        if (fade)
707            SetCurVertColor(m_color2);
708        p = m * p;
709        AppendQuadVert(p);
710        if (fade)
711            SetCurVertColor(m_color2);
712
713        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
714    }
715
716    void AppendSimpleQuad(float size, int fade = 0)
717    {
718        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
719    }
720
721    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
722    {
723        AppendQuadVert(vec3(p2.x, z, -p1.y));
724        AppendQuadVert(vec3(p2.x, z, -p2.y));
725        AppendQuadVert(vec3(p1.x, z, -p2.y));
726        if (fade)
727            SetCurVertColor(m_color2);
728        AppendQuadVert(vec3(p1.x, z, -p1.y));
729        if (fade)
730            SetCurVertColor(m_color2);
731
732        AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
733        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
734    }
735
736    void AppendCog() {} /* TODO */
737
738private:
739    vec4 m_color, m_color2;
740    Array<uint16_t> m_triidx, m_quadidx;
741    Array<vec3, vec3, vec4> m_vert;
742    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
743
744    struct
745    {
746        Shader *shader;
747        ShaderAttrib coord, norm, color;
748        ShaderUniform modelview, proj, normalmat;
749        VertexDeclaration *vdecl;
750        VertexBuffer *vbo;
751        IndexBuffer *ibo;
752        int vertexcount, indexcount;
753    }
754    m_gpu;
755};
756
757#endif /* __MESH_H__ */
758
Note: See TracBrowser for help on using the repository browser.