source: trunk/orbital/mesh.h @ 1282

Last change on this file since 1282 was 1282, checked in by sam, 11 years ago

orbital: improve the cog mesh generator.

  • Property svn:keywords set to Id
File size: 30.0 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, v3, f1); AppendSphere(v3, (int)f1); }
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                 /* 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        vec3 const invs = vec3(1) / s;
450
451        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
452        {
453            m_vert[i].m1 *= s;
454            m_vert[i].m2 = normalize(m_vert[i].m2 * invs);
455        }
456
457        /* Flip winding if the scaling involves mirroring */
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 * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
504
505        /* Construct normal */
506        n = p2;
507        n.y = r1 * (r1 - r2) / h;
508        if (!smooth)
509            n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
510        n = normalize(n);
511
512        /* FIXME: normals should be flipped in two-sided mode, but that
513         * means duplicating the vertices again... */
514        for (int i = 0; i < nsides; i++)
515        {
516            AppendQuadVert(p1); SetCurVertNormal(n);
517            AppendQuadVert(p2); SetCurVertNormal(n);
518            SetCurVertColor(m_color2);
519
520            if (smooth)
521            {
522                int j = (i + 1) % nsides;
523                AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
524                if (dualside)
525                    AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
526            }
527
528            p1 = rotmat * p1;
529            p2 = rotmat * p2;
530
531            if (!smooth)
532            {
533                AppendQuadVert(p1); SetCurVertNormal(n);
534                AppendQuadVert(p2); SetCurVertNormal(n);
535                SetCurVertColor(m_color2);
536
537                AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
538                if (dualside)
539                    AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
540            }
541
542            n = rotmat * n;
543        }
544    }
545
546    void AppendSphere(vec3 const &size, int divisions)
547    {
548        int ibase = m_quadidx.Count();
549        int vbase = m_vert.Count();
550
551        vec3 d = size * 0.5f;
552        float const pi = acos(-1.0f);
553
554        Array<vec2> table;
555        for (int i = 0; i <= divisions; i++)
556            table.Append(vec2(sin(pi * 2 / divisions * i) + 1e-5f,
557                              cos(pi * 2 / divisions * i) + 1e-5f));
558
559        for (int j = 0; j <= divisions / 2; j++)
560            for (int i = 0; i < divisions; i++)
561            {
562                int j2 = j + 1;
563                int i2 = (i + 1) % divisions;
564
565                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
566                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
567                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
568                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
569            }
570
571        for (int i = vbase; i < m_vert.Count(); i += 4)
572            AppendQuad(0, 1, 2, 3, i);
573
574        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
575    }
576
577    void AppendBox(vec3 const &size, float chamf = 0.f)
578    {
579        AppendBox(size, chamf, false);
580    }
581
582    void AppendSmoothChamfBox(vec3 const &size, float chamf)
583    {
584        AppendBox(size, chamf, true);
585    }
586
587    void AppendFlatChamfBox(vec3 const &size, float chamf)
588    {
589        AppendBox(size, chamf, false);
590    }
591
592    void AppendBox(vec3 const &size, float chamf, bool smooth)
593    {
594        int vbase = m_vert.Count();
595        int qibase = m_quadidx.Count();
596        int tibase = m_triidx.Count();
597
598        vec3 d = size * 0.5f;
599
600        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
601        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
602        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
603        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
604
605        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
606        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
607        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
608        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
609
610        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
611        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
612        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
613        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
614
615        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
616        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
617        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
618        AppendQuadVert(vec3(+d.x + chamf, -d.y, +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        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
626        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
627        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
628        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
629
630        /* The 6 quads on each side of the box */
631        for (int i = 0; i < 24; i += 4)
632            AppendQuad(i, i + 1, i + 2, i + 3, vbase);
633
634        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
635        qibase = m_quadidx.Count();
636
637        /* The 8 quads at each edge of the box */
638        if (chamf)
639        {
640            static int const quadlist[48] =
641            {
642                0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
643                2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
644                1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
645            };
646
647            for (int i = 0; i < 48; i += 4)
648            {
649                if (smooth)
650                    AppendQuad(quadlist[i], quadlist[i + 1],
651                               quadlist[i + 2], quadlist[i + 3], vbase);
652                else
653                    AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1],
654                                     quadlist[i + 2], quadlist[i + 3], vbase);
655            }
656        }
657
658        /* The 8 triangles at each corner of the box */
659        if (chamf)
660        {
661            static int const trilist[24] =
662            {
663                3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
664                2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
665            };
666
667            for (int i = 0; i < 24; i += 3)
668            {
669                if (smooth)
670                    AppendTriangle(trilist[i], trilist[i + 1],
671                                   trilist[i + 2], vbase);
672                else
673                    AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1],
674                                                 trilist[i + 2], vbase);
675            }
676        }
677
678        if (!smooth)
679        {
680            ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
681            ComputeTriNormals(tibase, m_triidx.Count() - tibase);
682        }
683    }
684
685    void AppendStar(int nbranches, float r1, float r2,
686                    int fade = 0, int fade2 = 0)
687    {
688        int vbase = m_vert.Count();
689
690        AppendQuadVert(vec3(0.f, 0.f, 0.f));
691
692        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
693        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
694
695        p2 = rotmat * p2;
696        rotmat = rotmat * rotmat;
697
698        for (int i = 0; i < nbranches; i++)
699        {
700            AppendQuadVert(p1);
701            if (fade2)
702                SetCurVertColor(m_color2);
703
704            AppendQuadVert(p2);
705            if (fade)
706                SetCurVertColor(m_color2);
707
708            AppendQuad(0, (2 * i + 3) % (2 * nbranches),
709                       2 * i + 2, 2 * i + 1, vbase);
710
711            p1 = rotmat * p1;
712            p2 = rotmat * p2;
713        }
714    }
715
716    void AppendExpandedStar(int nbranches, float r1, float r2, float extrar)
717    {
718        int vbase = m_vert.Count();
719
720        AppendQuadVert(vec3(0.f, 0.f, 0.f));
721
722        mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
723        vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
724             p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
725
726        p2 = rotmat * p2;
727        p4 = rotmat * p4;
728        rotmat = rotmat * rotmat;
729
730        for (int i = 0; i < nbranches; i++)
731        {
732            AppendQuadVert(p1);
733            AppendQuadVert(p2);
734            AppendQuadVert(p3); SetCurVertColor(m_color2);
735            AppendQuadVert(p4); SetCurVertColor(m_color2);
736
737            int j = (i + 1) % nbranches;
738            AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
739            AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
740            AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
741
742            p1 = rotmat * p1;
743            p2 = rotmat * p2;
744            p3 = rotmat * p3;
745            p4 = rotmat * p4;
746        }
747    }
748
749    void AppendDisc(int nsides, float r, int fade = 0)
750    {
751        int vbase = m_vert.Count();
752
753        AppendQuadVert(vec3(0.f, 0.f, 0.f));
754
755        mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
756        vec3 p1(r, 0.f, 0.f);
757
758        for (int i = 0; i < nsides; i++)
759        {
760            AppendQuadVert(p1);
761            if (fade)
762                SetCurVertColor(m_color2);
763            AppendTriangle(0, ((i + 1) % nsides) + 1, i + 1, vbase);
764            p1 = rotmat * p1;
765        }
766    }
767
768    void AppendSimpleTriangle(float size, int fade = 0)
769    {
770        mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
771        vec3 p(0.f, 0.f, size);
772
773        AppendQuadVert(p);
774        p = m * p;
775        AppendQuadVert(p);
776        if (fade)
777            SetCurVertColor(m_color2);
778        p = m * p;
779        AppendQuadVert(p);
780        if (fade)
781            SetCurVertColor(m_color2);
782
783        AppendTriangle(0, 1, 2, m_vert.Count() - 3);
784    }
785
786    void AppendSimpleQuad(float size, int fade = 0)
787    {
788        AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
789    }
790
791    void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0)
792    {
793        AppendQuadVert(vec3(p2.x, z, -p1.y));
794        AppendQuadVert(vec3(p2.x, z, -p2.y));
795        AppendQuadVert(vec3(p1.x, z, -p2.y));
796        if (fade)
797            SetCurVertColor(m_color2);
798        AppendQuadVert(vec3(p1.x, z, -p1.y));
799        if (fade)
800            SetCurVertColor(m_color2);
801
802        AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
803        ComputeQuadNormals(m_quadidx.Count() - 4, 4);
804    }
805
806    void AppendCog(int nbsides, float h, float r1, float r2,
807                   float r12, float r22, float sidemul, int offset)
808    {
809        int qibase = m_quadidx.Count();
810        int vbase = m_vert.Count();
811
812        AppendQuadVert(vec3(0.f, h * .5f, 0.f));
813        AppendQuadVert(vec3(0.f, h * -.5f, 0.f));
814        SetCurVertColor(m_color2);
815
816        mat3 rotmat = mat3::rotate(180.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] = rotmat * vec3(r1 + r12, h * .5f, 0.f);
823        p[3] = rotmat * p[2];
824
825        p[4] = vec3(r2, h * -.5f, 0.f);
826        p[5] = rotmat * p[4];
827        p[6] = rotmat * vec3(r2 + r22, h * -.5f, 0.f);
828        p[7] = rotmat * p[6];
829
830        rotmat = rotmat * rotmat;
831
832        for (int i = 0; i < nbsides; i++)
833        {
834            /* Each vertex will share three faces, so three different
835             * normals, therefore we add each vertex three times. */
836            for (int n = 0; n < 24; n++)
837            {
838                AppendQuadVert(p[n / 3]);
839                if (n / 3 >= 4)
840                    SetCurVertColor(m_color2);
841            }
842
843            int j = 24 * i, k = 24 * ((i + 1) % nbsides);
844
845            /* The top and bottom faces */
846            AppendQuad(0, j + 2, j + 5, k + 2, vbase);
847            AppendQuad(1, k + 14, j + 17, j + 14, vbase);
848            AppendQuad(j + 5, j + 8, j + 11, k + 2, vbase);
849            AppendQuad(k + 14, j + 23, j + 20, j + 17, vbase);
850
851            /* The side quads */
852            AppendQuad(j + 6, j + 3, j + 15, j + 18, vbase);
853            AppendQuad(j + 9, j + 7, j + 19, j + 21, vbase);
854            AppendQuad(j + 12, j + 10, j + 22, j + 24, vbase);
855            AppendQuad(k + 4, j + 13, j + 25, k + 16, vbase);
856
857            for (int n = 0; n < 8; n++)
858                p[n] = rotmat * p[n];
859        }
860
861        ComputeQuadNormals(qibase, m_quadidx.Count() - qibase);
862    }
863
864private:
865    vec4 m_color, m_color2;
866    Array<uint16_t> m_triidx, m_quadidx;
867    Array<vec3, vec3, vec4> m_vert;
868    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
869
870    struct
871    {
872        Shader *shader;
873        ShaderAttrib coord, norm, color;
874        ShaderUniform modelview, proj, normalmat;
875        VertexDeclaration *vdecl;
876        VertexBuffer *vbo;
877        IndexBuffer *ibo;
878        int vertexcount, indexcount;
879    }
880    m_gpu;
881};
882
883#endif /* __MESH_H__ */
884
Note: See TracBrowser for help on using the repository browser.