source: trunk/orbital/mesh.h @ 1262

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

orbital: the mesh builder now supports spheres.

  • Property svn:keywords set to Id
File size: 14.7 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2012 Various People
5//
6
7#if !defined __MESH_H__
8#define __MESH_H__
9
10class Mesh
11{
12public:
13    Mesh()
14      : m_color(0), m_color2(0),
15        m_vert_cursor(0), m_quadidx_cursor(0), m_triidx_cursor(0)
16    {}
17
18    void Flush()
19    {
20        m_vert_cursor = m_vert.Count();
21        m_quadidx_cursor = m_quadidx.Count();
22        m_triidx_cursor = m_triidx.Count();
23    }
24
25    void MeshConvert()
26    {
27        m_gpu.shader = Shader::Create(
28#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
29            "#version 120\n"
30            "attribute vec3 in_Vertex;"
31            "attribute vec3 in_Normal;"
32            "attribute vec4 in_Color;"
33            "uniform mat4 in_ModelView;"
34            "uniform mat4 in_Proj;"
35            "uniform mat3 in_NormalMat;"
36            "varying vec4 pass_Color;"
37            ""
38            "vec4 Light = vec4(3.0, 3.0, 1.0, 1.0);"
39            "vec3 Kd = vec3(1.0, 0.8, 0.8);"
40            "vec3 Ld = vec3(1.0, 0.8, 0.8);"
41            ""
42            "void main(void) {"
43            "    vec3 tnorm = normalize(in_NormalMat * in_Normal);"
44            "    vec4 Eye = in_ModelView * vec4(in_Vertex, 1.0);"
45            "    vec3 s = normalize((Light - Eye).xyz);"
46            ""
47            "    pass_Color = vec4(Ld * Kd * max(dot(s, tnorm), 0.0), 1.0);"
48            "    gl_Position = in_Proj * Eye;"
49            "}",
50
51            "#version 120\n"
52            "varying vec4 pass_Color;"
53            ""
54            "void main(void) {"
55            "    gl_FragColor = pass_Color;"
56            "}"
57#else
58            "void main(float3 in_Vertex : POSITION,"
59            "          float3 in_Normal : NORMAL,"
60            "          float4 in_Color : COLOR,"
61            "          uniform float4x4 in_ModelView,"
62            "          uniform float4x4 in_Proj,"
63            "          uniform float3x3 in_NormalMat,"
64            "          out float4 out_Position : POSITION,"
65            "          out float4 pass_Color : COLOR) {"
66            "    float4x4 Light = float4x4(10.0, 1.0, 1.0, 1.0);"
67            "    float3x3 Kd = float3x3(1.0, 0.8, 0.8);"
68            "    float3x3 Ld = float3x3(1.0, 0.8, 0.8);"
69            ""
70            "    float3x3 tnorm = normalize(mul(in_NormalMat, in_Normal));"
71            "    float4x4 Eye = mul(in_ModelView, float4x4(in_Vertex, 1.0));"
72            "    float3x3 s = normalize((Light - Eye).xyz);"
73            ""
74            "    pass_Color = float4x4(Ld * Kd * max(dot(s, tnorm), 0.0), 1.0);"
75            "    out_Position = mul(in_Proj, Eye);"
76            "}",
77
78            "void main(float4 pass_Color : COLOR,"
79            "          out float4 out_FragColor : COLOR) {"
80            "    out_FragColor = pass_Color;"
81            "}"
82#endif
83        );
84        m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView");
85        m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj");
86        m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat");
87        m_gpu.coord = m_gpu.shader->GetAttribLocation("in_Vertex",
88                                              VertexUsage::Position, 0);
89        m_gpu.norm = m_gpu.shader->GetAttribLocation("in_Normal",
90                                             VertexUsage::Normal, 0);
91        m_gpu.color = m_gpu.shader->GetAttribLocation("in_Color",
92                                              VertexUsage::Color, 0);
93
94        m_gpu.vdecl = new VertexDeclaration(
95            VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
96                                           VertexUsage::Normal,
97                                           VertexUsage::Color));
98
99        Array<vec3,vec3,u8vec4> vertexlist;
100        for (int i = 0; i < m_vert.Count(); i++)
101            vertexlist.Append(m_vert[i].m1,
102                              m_vert[i].m2,
103                              (u8vec4)(m_vert[i].m3 * 255.f));
104
105        Array<uint16_t> indexlist;
106        for (int i = 0; i < m_triidx.Count(); i += 3)
107        {
108            indexlist += m_triidx[i + 0];
109            indexlist += m_triidx[i + 1];
110            indexlist += m_triidx[i + 2];
111        }
112        for (int i = 0; i < m_quadidx.Count(); i += 4)
113        {
114            indexlist += m_quadidx[i + 0];
115            indexlist += m_quadidx[i + 1];
116            indexlist += m_quadidx[i + 2];
117
118            indexlist += m_quadidx[i + 0];
119            indexlist += m_quadidx[i + 2];
120            indexlist += m_quadidx[i + 3];
121        }
122
123        m_gpu.vbo = new VertexBuffer(vertexlist.Bytes());
124        void *mesh = m_gpu.vbo->Lock(0, 0);
125        memcpy(mesh, &vertexlist[0], vertexlist.Bytes());
126        m_gpu.vbo->Unlock();
127
128        m_gpu.ibo = new IndexBuffer(indexlist.Bytes());
129        void *indices = m_gpu.ibo->Lock(0, 0);
130        memcpy(indices, &indexlist[0], indexlist.Bytes());
131        m_gpu.ibo->Unlock();
132
133        m_gpu.vertexcount = vertexlist.Count();
134        m_gpu.indexcount = indexlist.Count();
135    }
136
137    void Render(mat4 const &modelview, mat4 const &proj, mat3 const &normalmat)
138    {
139        m_gpu.shader->Bind();
140        m_gpu.shader->SetUniform(m_gpu.modelview, modelview);
141        m_gpu.shader->SetUniform(m_gpu.proj, proj);
142        m_gpu.shader->SetUniform(m_gpu.normalmat, normalmat);
143        m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord, m_gpu.norm, m_gpu.color);
144        m_gpu.vdecl->Bind();
145        m_gpu.ibo->Bind();
146        m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
147                                         0, 0, m_gpu.vertexcount,
148                                         0, m_gpu.indexcount / 3);
149        m_gpu.ibo->Unbind();
150        m_gpu.vdecl->Unbind();
151    }
152
153    void SetCurColor(vec4 const &color) { m_color = color; }
154    void SetCurColor2(vec4 const &color) { m_color2 = color; }
155
156    void AppendQuadVert(vec3 const &coord)
157    {
158        m_vert.Append(coord, vec3(0.f, 1.f, 0.f), m_color);
159    }
160
161    void AppendDuplicateQuadVert(int i)
162    {
163        m_vert.Append(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3);
164    }
165
166    void AppendQuad(int i1, int i2, int i3, int i4, int base)
167    {
168        m_quadidx += base + i1;
169        m_quadidx += base + i2;
170        m_quadidx += base + i3;
171        m_quadidx += base + i4;
172    }
173
174    void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
175    {
176        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i1);
177        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i2);
178        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i3);
179        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i4);
180    }
181
182    void AppendTriangle(int i1, int i2, int i3, int base)
183    {
184        m_quadidx += base + i1;
185        m_quadidx += base + i2;
186        m_quadidx += base + i3;
187    }
188
189    void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
190    {
191        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i1);
192        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i2);
193        m_quadidx += m_vert.Count(); AppendDuplicateQuadVert(base + i3);
194    }
195
196    void ComputeQuadNormals(int start, int vcount)
197    {
198        for (int i = 0; i < vcount; i += 4)
199        {
200            vec3 v0 = m_vert[m_quadidx[start + i + 2]].m1
201                    - m_vert[m_quadidx[start + i + 0]].m1;
202            vec3 v1 = m_vert[m_quadidx[start + i + 1]].m1
203                    - m_vert[m_quadidx[start + i + 0]].m1;
204            vec3 n = normalize(cross(v1, v0));
205
206            for (int j = 0; j < 4; j++)
207                m_vert[m_quadidx[start + i + j]].m2 = n;
208        }
209    }
210
211    void ComputeTriNormals(int start, int vcount)
212    {
213        for (int i = 0; i < vcount; i += 3)
214        {
215            vec3 v0 = m_vert[m_quadidx[start + i + 2]].m1
216                    - m_vert[m_quadidx[start + i + 0]].m1;
217            vec3 v1 = m_vert[m_quadidx[start + i + 1]].m1
218                    - m_vert[m_quadidx[start + i + 0]].m1;
219            vec3 n = normalize(cross(v1, v0));
220
221            for (int j = 0; j < 3; j++)
222                m_vert[m_quadidx[start + i + j]].m2 = n;
223        }
224    }
225
226    void SetVertColor(vec4 const &color)
227    {
228        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
229            m_vert[i].m3 = color;
230    }
231
232    void SetCurVertNormal(vec3 const &normal)
233    {
234        m_vert[m_vert.Count() - 1].m2 = normal;
235    }
236
237    void SetCurVertColor(vec4 const &color)
238    {
239        m_vert[m_vert.Count() - 1].m3 = color;
240    }
241
242    void Translate(vec3 const &v)
243    {
244        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
245            m_vert[i].m1 += v;
246    }
247
248    void RotateZ(float t)
249    {
250        /* FIXME: use mat3 instead of mat4 when it's working */
251        mat4 m = mat4::rotate(t, 0, 0, 1);
252        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
253            m_vert[i].m1 = (m * vec4(m_vert[i].m1, 1.f)).xyz;
254    }
255
256    void RotateY(float t)
257    {
258        mat4 m = mat4::rotate(t, 0, 1, 0);
259        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
260            m_vert[i].m1 = (m * vec4(m_vert[i].m1, 1.f)).xyz;
261    }
262
263    void RotateX(float t)
264    {
265        mat4 m = mat4::rotate(t, 1, 0, 0);
266        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
267            m_vert[i].m1 = (m * vec4(m_vert[i].m1, 1.f)).xyz;
268    }
269
270    void TaperX(float y, float z, float xoff)
271    {
272        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
273        {
274            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.x + xoff);
275            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.x + xoff);
276        }
277    }
278
279    void TaperY(float x, float z, float yoff)
280    {
281        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
282        {
283            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.y + yoff);
284            m_vert[i].m1.z *= 1.f + (z * m_vert[i].m1.y + yoff);
285        }
286    }
287
288    void TaperZ(float x, float y, float zoff)
289    {
290        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
291        {
292            m_vert[i].m1.x *= 1.f + (x * m_vert[i].m1.z + zoff);
293            m_vert[i].m1.y *= 1.f + (y * m_vert[i].m1.z + zoff);
294        }
295    }
296
297    void Scale(vec3 const &s)
298    {
299        for (int i = m_vert_cursor; i < m_vert.Count(); i++)
300        {
301            m_vert[i].m1 *= s;
302            m_vert[i].m2 *= s;
303        }
304
305        // BH : TODO : not sure about this one
306        // Sam: not too sure either!
307        if (s.x * s.y * s.z < 0)
308        {
309            for (int i = m_quadidx_cursor; i < m_quadidx.Count(); i += 2)
310            {
311                uint16_t tmp = m_quadidx[i + 0];
312                m_quadidx[i + 0] = m_quadidx[i + 1];
313                m_quadidx[i + 1] = tmp;
314            }
315
316            for (int i = m_triidx_cursor; i < m_triidx.Count(); i += 3)
317            {
318                uint16_t tmp = m_triidx[i + 0];
319                m_triidx[i + 0] = m_triidx[i + 1];
320                m_triidx[i + 1] = tmp;
321            }
322        }
323    }
324
325    void MirrorX() { Duplicate(); Scale(vec3(-1, 1, 1)); }
326    void MirrorY() { Duplicate(); Scale(vec3(1, -1, 1)); }
327    void MirrorZ() { Duplicate(); Scale(vec3(1, 1, -1)); }
328
329    void Duplicate()
330    {
331        int vlen = m_vert.Count() - m_vert_cursor;
332        int qlen = m_quadidx.Count() - m_quadidx_cursor;
333        int tlen = m_triidx.Count() - m_triidx_cursor;
334
335        for (int i = 0; i < vlen; i++)
336            m_vert += m_vert[m_vert_cursor++];
337
338        for (int i = 0; i < qlen; i++)
339            m_quadidx += m_quadidx[m_quadidx_cursor++] + vlen;
340
341        for (int i = 0; i < tlen; i++)
342            m_triidx += m_triidx[m_triidx_cursor++] + vlen;
343    }
344
345    void AppendCylinder() {} /* TODO */
346
347    void AppendSphere(vec3 const &size, int divisions)
348    {
349        int ibase = m_quadidx.Count();
350        int vbase = m_vert.Count();
351
352        vec3 d = size * 0.5f;
353        float const pi = acos(-1.0f);
354
355        Array<vec2> table;
356        for (int i = 0; i <= divisions; i++)
357            table.Append(vec2(sin(pi * 2 / divisions * i) + 1e-5f,
358                              cos(pi * 2 / divisions * i) + 1e-5f));
359
360        for (int j = 0; j <= divisions / 2; j++)
361            for (int i = 0; i < divisions; i++)
362            {
363                int j2 = j + 1;
364                int i2 = (i + 1) % divisions;
365
366                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j].xxy);
367                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j].xxy);
368                AppendQuadVert(d * vec3(table[i2], 1.0f) * table[j2].xxy);
369                AppendQuadVert(d * vec3(table[i], 1.0f) * table[j2].xxy);
370            }
371
372        for (int i = vbase; i < m_vert.Count(); i += 4)
373            AppendQuad(0, 1, 2, 3, i);
374
375        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
376    }
377
378    void AppendBox(vec3 const &size)
379    {
380        AppendBox(size, 0.f);
381    }
382
383    void AppendBox(vec3 const &size, float chamf)
384    {
385        int ibase = m_quadidx.Count();
386        int vbase = m_vert.Count();
387
388        vec3 d = size * 0.5f;
389
390        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
391        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
392        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
393        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
394
395        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
396        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
397        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
398        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
399
400        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
401        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
402        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
403        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
404
405        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
406        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
407        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
408        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
409
410        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
411        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
412        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
413        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
414
415        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
416        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
417        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
418        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
419
420        AppendQuad(0, 1, 2, 3, vbase);
421        AppendQuad(4, 5, 6, 7, vbase);
422        AppendQuad(8, 9, 10, 11, vbase);
423        AppendQuad(12, 13, 14, 15, vbase);
424        AppendQuad(16, 17, 18, 19, vbase);
425        AppendQuad(20, 21, 22, 23, vbase);
426
427        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
428    }
429
430private:
431    vec4 m_color, m_color2;
432    Array<uint16_t> m_triidx, m_quadidx;
433    Array<vec3, vec3, vec4> m_vert;
434    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
435
436    struct
437    {
438        Shader *shader;
439        ShaderAttrib coord, norm, color;
440        ShaderUniform modelview, proj, normalmat;
441        VertexDeclaration *vdecl;
442        VertexBuffer *vbo;
443        IndexBuffer *ibo;
444        int vertexcount, indexcount;
445    }
446    m_gpu;
447};
448
449#endif /* __MESH_H__ */
450
Note: See TracBrowser for help on using the repository browser.