source: trunk/orbital/mesh.h @ 1276

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

orbital: implement cylinders in the mesh builder; their normals are wrong
in the smooth case, for now.

  • Property svn:keywords set to Id
File size: 26.9 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2012 Various People
5//
6
7/* TODO for this file:
8 *  - rename "AppendQuadVert" to "AddVertex" or something; it has nothing
9 *    to do with quads.
10 */
11
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, f6;
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")  { 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, 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(int nsides, float h, float r1, float r2,
497                        int dualside, int smooth)
498    {
499        int ibase = m_quadidx.Count();
500        int vbase = m_vert.Count();
501
502        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
503        vec3 p1(r1, -h, 0.f);
504        vec3 p2(r2, h, 0.f);
505
506        for (int i = 0; i < nsides; i++)
507        {
508            AppendQuadVert(p1);
509            AppendQuadVert(p2);
510            SetCurVertColor(m_color2);
511
512            if (smooth)
513            {
514                int j = (i + 1) % nsides;
515                AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
516                if (dualside)
517                    AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
518
519                /* TODO: compute normals */
520            }
521
522            p1 = rotmat * p1;
523            p2 = rotmat * p2;
524
525            if (!smooth)
526            {
527                AppendQuadVert(p1);
528                AppendQuadVert(p2);
529                SetCurVertColor(m_color2);
530
531                AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
532                if (dualside)
533                    AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
534            }
535        }
536
537        if (!smooth)
538            ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
539    }
540
541    void AppendSphere(vec3 const &size, int divisions)
542    {
543        int ibase = m_quadidx.Count();
544        int vbase = m_vert.Count();
545
546        vec3 d = size * 0.5f;
547        float const pi = acos(-1.0f);
548
549        Array<vec2> table;
550        for (int i = 0; i <= divisions; i++)
551            table.Append(vec2(sin(pi * 2 / divisions * i) + 1e-5f,
552                              cos(pi * 2 / divisions * i) + 1e-5f));
553
554        for (int j = 0; j <= divisions / 2; j++)
555            for (int i = 0; i < divisions; i++)
556            {
557                int j2 = j + 1;
558                int i2 = (i + 1) % divisions;
559
560                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
561                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
562                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
563                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
564            }
565
566        for (int i = vbase; i < m_vert.Count(); i += 4)
567            AppendQuad(0, 1, 2, 3, i);
568
569        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
570    }
571
572    void AppendBox(vec3 const &size, float chamf = 0.f)
573    {
574        AppendBox(size, chamf, false);
575    }
576
577    void AppendSmoothChamfBox(vec3 const &size, float chamf)
578    {
579        AppendBox(size, chamf, true);
580    }
581
582    void AppendFlatChamfBox(vec3 const &size, float chamf)
583    {
584        AppendBox(size, chamf, false);
585    }
586
587    void AppendBox(vec3 const &size, float chamf, bool smooth)
588    {
589        int vbase = m_vert.Count();
590        int qibase = m_quadidx.Count();
591        int tibase = m_triidx.Count();
592
593        vec3 d = size * 0.5f;
594
595        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
596        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
597        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
598        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
599
600        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
601        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
602        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
603        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
604
605        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
606        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
607        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
608        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
609
610        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
611        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
612        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
613        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
614
615        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
616        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
617        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
618        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
619
620        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
621        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
622        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
623        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
624
625        /* The 6 quads on each side of the box */
626        for (int i = 0; i < 24; i += 4)
627            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
628
629        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
630        qibase = m_quadidx.Count();
631
632        /* The 8 quads at each edge of the box */
633        if (chamf)
634        {
635            static int const quadlist[48] =
636            {
637                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
638                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
639                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
640            };
641
642            for (int i = 0; i < 48; i += 4)
643            {
644                if (smooth)
645                    AppendQuad(quadlist[i], quadlist[i + 1],
646                               quadlist[i + 2], quadlist[i + 3], vbase);
647                else
648                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
649                                     quadlist[i + 2], quadlist[i + 3], vbase);
650            }
651        }
652
653        /* The 8 triangles at each corner of the box */
654        if (chamf)
655        {
656            static int const trilist[24] =
657            {
658                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
659                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
660            };
661
662            for (int i = 0; i < 24; i += 3)
663            {
664                if (smooth)
665                    AppendTriangle(trilist[i], trilist[i + 1],
666                                   trilist[i + 2], vbase);
667                else
668                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
669                                                 trilist[i + 2], vbase);
670            }
671        }
672
673        if (!smooth)
674        {
675            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
676            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
677        }
678    }
679
680    void AppendStar(int nbranches, float r1, float r2)
681    {
682        AppendStar(nbranches, r1, r2, 0, 0);
683    }
684
685    void AppendStar(int nbranches, float r1, float r2, int fade)
686    {
687        AppendStar(nbranches, r1, r2, fade, 0);
688    }
689
690    void AppendStar(int nbranches, float r1, float r2, int fade, int fade2)
691    {
692        int vbase = m_vert.Count();
693
694        AppendQuadVert(vec3(0.f, 0.f, 0.f));
695
696        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
697        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
698
699        p2 = rotmat * p2;
700        rotmat = rotmat * rotmat;
701
702        for (int i = 0; i < nbranches; i++)
703        {
704            AppendQuadVert(p1);
705            if (fade2)
706                SetCurVertColor(m_color2);
707
708            AppendQuadVert(p2);
709            if (fade)
710                SetCurVertColor(m_color2);
711
712            AppendQuad(0, (2 * i + 3) % (2 * nbranches),
713                       2 * i + 2, 2 * i + 1, vbase);
714
715            p1 = rotmat * p1;
716            p2 = rotmat * p2;
717        }
718    }
719
720    void AppendExpandedStar() {} /* TODO */
721
722    void AppendDisc(int nsides, float r, int fade = 0)
723    {
724        int vbase = m_vert.Count();
725
726        AppendQuadVert(vec3(0.f, 0.f, 0.f));
727
728        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
729        vec3 p1(r, 0.f, 0.f);
730
731        for (int i = 0; i < nsides; i++)
732        {
733            AppendQuadVert(p1);
734            if (fade)
735                SetCurVertColor(m_color2);
736            AppendTriangle(0, ((i + 1) % nsides) + 1, i + 1, vbase);
737            p1 = rotmat * p1;
738        }
739    }
740
741    void AppendSimpleTriangle(float size, int fade = 0)
742    {
743        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
744        vec3 p(0.f, 0.f, size);
745
746        AppendQuadVert(p);
747        p = m * p;
748        AppendQuadVert(p);
749        if (fade)
750            SetCurVertColor(m_color2);
751        p = m * p;
752        AppendQuadVert(p);
753        if (fade)
754            SetCurVertColor(m_color2);
755
756        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
757    }
758
759    void AppendSimpleQuad(float size, int fade = 0)
760    {
761        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
762    }
763
764    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
765    {
766        AppendQuadVert(vec3(p2.x, z, -p1.y));
767        AppendQuadVert(vec3(p2.x, z, -p2.y));
768        AppendQuadVert(vec3(p1.x, z, -p2.y));
769        if (fade)
770            SetCurVertColor(m_color2);
771        AppendQuadVert(vec3(p1.x, z, -p1.y));
772        if (fade)
773            SetCurVertColor(m_color2);
774
775        AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
776        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
777    }
778
779    void AppendCog() {} /* TODO */
780
781private:
782    vec4 m_color, m_color2;
783    Array<uint16_t> m_triidx, m_quadidx;
784    Array<vec3, vec3, vec4> m_vert;
785    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
786
787    struct
788    {
789        Shader *shader;
790        ShaderAttrib coord, norm, color;
791        ShaderUniform modelview, proj, normalmat;
792        VertexDeclaration *vdecl;
793        VertexBuffer *vbo;
794        IndexBuffer *ibo;
795        int vertexcount, indexcount;
796    }
797    m_gpu;
798};
799
800#endif /* __MESH_H__ */
801
Note: See TracBrowser for help on using the repository browser.