source: trunk/orbital/mesh.h @ 1260

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

orbital: basic lighting in the mesh builder.

  • Property svn:keywords set to Id
File size: 13.6 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(10.0, 1.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 AppendBox(vec3 const &size)
348    {
349        AppendBox(size, 0.f);
350    }
351
352    void AppendBox(vec3 const &size, float chamf)
353    {
354        int ibase = m_quadidx.Count();
355        int vbase = m_vert.Count();
356
357        vec3 d = size * 0.5f;
358
359        AppendQuadVert(vec3(-d.x, -d.y, -d.z - chamf));
360        AppendQuadVert(vec3(-d.x, +d.y, -d.z - chamf));
361        AppendQuadVert(vec3(+d.x, +d.y, -d.z - chamf));
362        AppendQuadVert(vec3(+d.x, -d.y, -d.z - chamf));
363
364        AppendQuadVert(vec3(-d.x - chamf, -d.y, +d.z));
365        AppendQuadVert(vec3(-d.x - chamf, +d.y, +d.z));
366        AppendQuadVert(vec3(-d.x - chamf, +d.y, -d.z));
367        AppendQuadVert(vec3(-d.x - chamf, -d.y, -d.z));
368
369        AppendQuadVert(vec3(+d.x, -d.y, +d.z + chamf));
370        AppendQuadVert(vec3(+d.x, +d.y, +d.z + chamf));
371        AppendQuadVert(vec3(-d.x, +d.y, +d.z + chamf));
372        AppendQuadVert(vec3(-d.x, -d.y, +d.z + chamf));
373
374        AppendQuadVert(vec3(+d.x + chamf, -d.y, -d.z));
375        AppendQuadVert(vec3(+d.x + chamf, +d.y, -d.z));
376        AppendQuadVert(vec3(+d.x + chamf, +d.y, +d.z));
377        AppendQuadVert(vec3(+d.x + chamf, -d.y, +d.z));
378
379        AppendQuadVert(vec3(-d.x, -d.y - chamf, +d.z));
380        AppendQuadVert(vec3(-d.x, -d.y - chamf, -d.z));
381        AppendQuadVert(vec3(+d.x, -d.y - chamf, -d.z));
382        AppendQuadVert(vec3(+d.x, -d.y - chamf, +d.z));
383
384        AppendQuadVert(vec3(-d.x, +d.y + chamf, -d.z));
385        AppendQuadVert(vec3(-d.x, +d.y + chamf, +d.z));
386        AppendQuadVert(vec3(+d.x, +d.y + chamf, +d.z));
387        AppendQuadVert(vec3(+d.x, +d.y + chamf, -d.z));
388
389        AppendQuad(0, 1, 2, 3, vbase);
390        AppendQuad(4, 5, 6, 7, vbase);
391        AppendQuad(8, 9, 10, 11, vbase);
392        AppendQuad(12, 13, 14, 15, vbase);
393        AppendQuad(16, 17, 18, 19, vbase);
394        AppendQuad(20, 21, 22, 23, vbase);
395
396        ComputeQuadNormals(ibase, m_quadidx.Count() - ibase);
397    }
398
399private:
400    vec4 m_color, m_color2;
401    Array<uint16_t> m_triidx, m_quadidx;
402    Array<vec3, vec3, vec4> m_vert;
403    int m_vert_cursor, m_quadidx_cursor, m_triidx_cursor;
404
405    struct
406    {
407        Shader *shader;
408        ShaderAttrib coord, norm, color;
409        ShaderUniform modelview, proj, normalmat;
410        VertexDeclaration *vdecl;
411        VertexBuffer *vbo;
412        IndexBuffer *ibo;
413        int vertexcount, indexcount;
414    }
415    m_gpu;
416};
417
418#endif /* __MESH_H__ */
419
Note: See TracBrowser for help on using the repository browser.