source: trunk/orbital/mesh.h @ 1356

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

orbital: swap RGBA order in the shader on the X360.

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