source: trunk/orbital/mesh.h @ 1267

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

orbital: implement the generic effect shader; doesn't seem to work as
expected yet, maybe because of Z or Y/Z inversions.

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