source: trunk/orbital/mesh.h @ 1278

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

orbital: cylinders now have correct normals.

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