source: trunk/orbital/mesh.h @ 1304

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

orbital: add more comments to the various meshes we have.

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