1 | // |
---|
2 | // Lol Engine |
---|
3 | // |
---|
4 | // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> |
---|
5 | // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> |
---|
6 | // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> |
---|
7 | // This program is free software; you can redistribute it and/or |
---|
8 | // modify it under the terms of the Do What The Fuck You Want To |
---|
9 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
10 | // http://www.wtfpl.net/ for more details. |
---|
11 | // |
---|
12 | |
---|
13 | // |
---|
14 | // The EasyMesh class |
---|
15 | // ------------------ |
---|
16 | // |
---|
17 | |
---|
18 | #if !defined __EASYMESH_EASYMESH_H__ |
---|
19 | #define __EASYMESH_EASYMESH_H__ |
---|
20 | |
---|
21 | namespace lol |
---|
22 | { |
---|
23 | |
---|
24 | //Utility enum for renderers |
---|
25 | struct MeshRender |
---|
26 | { |
---|
27 | enum Value |
---|
28 | { |
---|
29 | NeedInit, |
---|
30 | CanRender, |
---|
31 | IgnoreRender |
---|
32 | } |
---|
33 | m_value; |
---|
34 | |
---|
35 | inline MeshRender(Value v) : m_value(v) {} |
---|
36 | inline MeshRender() : m_value(NeedInit) {} |
---|
37 | inline operator Value() { return m_value; } |
---|
38 | }; |
---|
39 | |
---|
40 | //Vertex datas for easymesh vertex list. |
---|
41 | //TODO : <COORD, NORM, COLOR, UV> |
---|
42 | struct VertexData |
---|
43 | { |
---|
44 | vec3 m_coord; |
---|
45 | vec3 m_normal; |
---|
46 | vec4 m_color; |
---|
47 | vec4 m_texcoord; |
---|
48 | ivec4 m_bone_id; |
---|
49 | vec4 m_bone_weight; |
---|
50 | |
---|
51 | VertexData(vec3 new_coord = vec3(0.f), |
---|
52 | vec3 new_normal = vec3(0.f, 1.f, 0.f), |
---|
53 | vec4 new_color = vec4(0.f), |
---|
54 | vec4 new_texcoord = vec4(0.f), |
---|
55 | ivec4 new_bone_id = ivec4(0), |
---|
56 | vec4 new_bone_weight= vec4(0.f)) |
---|
57 | { |
---|
58 | m_coord = new_coord; |
---|
59 | m_normal = new_normal; |
---|
60 | m_color = new_color; |
---|
61 | m_texcoord = new_texcoord; |
---|
62 | m_bone_id = new_bone_id; |
---|
63 | m_bone_weight = new_bone_weight; |
---|
64 | } |
---|
65 | }; |
---|
66 | |
---|
67 | //Base class to declare shader datas |
---|
68 | class GpuShaderData |
---|
69 | { |
---|
70 | friend class GpuEasyMeshData; |
---|
71 | |
---|
72 | protected: |
---|
73 | GpuShaderData(); |
---|
74 | public: |
---|
75 | //-- |
---|
76 | GpuShaderData(uint16_t vert_decl_flags, Shader* shader, DebugRenderMode render_mode); |
---|
77 | ~GpuShaderData(); |
---|
78 | //-- |
---|
79 | void AddUniform(const lol::String &new_uniform); |
---|
80 | void AddAttribute(const lol::String &new_attribute, VertexUsage usage, int index); |
---|
81 | ShaderUniform const *GetUniform(const lol::String &uniform); |
---|
82 | ShaderAttrib const *GetAttribute(const lol::String &attribute); |
---|
83 | //-- |
---|
84 | virtual void SetupShaderDatas(mat4 const &model) { UNUSED(model); } |
---|
85 | |
---|
86 | protected: |
---|
87 | uint16_t m_vert_decl_flags; |
---|
88 | Shader* m_shader; |
---|
89 | DebugRenderMode m_render_mode; |
---|
90 | Array<lol::String, ShaderUniform> m_shader_uniform; |
---|
91 | Array<lol::String, ShaderAttrib> m_shader_attrib; |
---|
92 | }; |
---|
93 | |
---|
94 | class DefaultShaderData : public GpuShaderData |
---|
95 | { |
---|
96 | public: |
---|
97 | //--- |
---|
98 | DefaultShaderData(DebugRenderMode render_mode); |
---|
99 | DefaultShaderData(uint16_t vert_decl_flags, Shader* shader, bool with_UV); |
---|
100 | //--- |
---|
101 | void SetupDefaultData(bool with_UV); |
---|
102 | virtual void SetupShaderDatas(mat4 const &model); |
---|
103 | }; |
---|
104 | |
---|
105 | class GpuEasyMeshData |
---|
106 | { |
---|
107 | public: |
---|
108 | //--- |
---|
109 | GpuEasyMeshData(); |
---|
110 | ~GpuEasyMeshData(); |
---|
111 | //--- |
---|
112 | void AddGpuData(GpuShaderData* gpudata, class EasyMesh* src_mesh); |
---|
113 | void RenderMeshData(mat4 const &model); |
---|
114 | |
---|
115 | private: |
---|
116 | void SetupVertexData(uint16_t vdecl_flags, EasyMesh* src_mesh); |
---|
117 | |
---|
118 | Array<GpuShaderData*> m_gpudatas; |
---|
119 | //uint16_t are the vdecl/vbo flags to avoid copy same vdecl several times. |
---|
120 | Array<uint16_t, VertexDeclaration*, |
---|
121 | VertexBuffer*> m_vdatas; |
---|
122 | int m_vertexcount; |
---|
123 | //We only need only one ibo for the whole mesh |
---|
124 | IndexBuffer * m_ibo; |
---|
125 | int m_indexcount; |
---|
126 | }; |
---|
127 | |
---|
128 | |
---|
129 | struct MeshBuildOperation |
---|
130 | { |
---|
131 | enum Value |
---|
132 | { |
---|
133 | //When this flag is up, negative scaling will not invert faces. |
---|
134 | Scale_Winding = 1 << 0, |
---|
135 | |
---|
136 | All = 0xffffffff |
---|
137 | } |
---|
138 | m_value; |
---|
139 | |
---|
140 | inline MeshBuildOperation(Value v) : m_value(v) {} |
---|
141 | inline MeshBuildOperation(uint64_t i) : m_value((Value)i) {} |
---|
142 | inline operator Value() { return m_value; } |
---|
143 | }; |
---|
144 | |
---|
145 | struct MeshType |
---|
146 | { |
---|
147 | enum Value |
---|
148 | { |
---|
149 | Triangle = 0, |
---|
150 | Quad, |
---|
151 | Box, |
---|
152 | Sphere, |
---|
153 | Capsule, |
---|
154 | Torus, |
---|
155 | Cylinder, |
---|
156 | Disc, |
---|
157 | Star, |
---|
158 | ExpandedStar, |
---|
159 | Cog, |
---|
160 | |
---|
161 | Max |
---|
162 | } |
---|
163 | m_value; |
---|
164 | |
---|
165 | inline MeshType(Value v) : m_value(v) {} |
---|
166 | inline operator Value() { return m_value; } |
---|
167 | }; |
---|
168 | |
---|
169 | //TODO : Add other Build type |
---|
170 | struct TexCoordBuildType |
---|
171 | { |
---|
172 | enum Value |
---|
173 | { |
---|
174 | TriangleDefault = 0, |
---|
175 | QuadDefault = 0, |
---|
176 | BoxDefault = 0, |
---|
177 | SphereDefault = 0, |
---|
178 | CapsuleDefault = 0, |
---|
179 | TorusDefault = 0, |
---|
180 | CylinderDefault = 0, |
---|
181 | DiscDefault = 0, |
---|
182 | StarDefault = 0, |
---|
183 | ExpandedStarDefault = 0, |
---|
184 | CogDefault = 0, |
---|
185 | |
---|
186 | //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE |
---|
187 | Max = 1 |
---|
188 | } |
---|
189 | m_value; |
---|
190 | |
---|
191 | inline TexCoordBuildType() : m_value(TriangleDefault) {} |
---|
192 | inline TexCoordBuildType(Value v) : m_value(v) {} |
---|
193 | inline TexCoordBuildType(int v) : m_value((Value)v) {} |
---|
194 | inline operator Value() { return m_value; } |
---|
195 | }; |
---|
196 | |
---|
197 | struct MeshFaceType |
---|
198 | { |
---|
199 | enum Value |
---|
200 | { |
---|
201 | BoxFront = 0, |
---|
202 | BoxLeft = 1, |
---|
203 | BoxBack = 2, |
---|
204 | BoxRight = 3, |
---|
205 | BoxTop = 4, |
---|
206 | BoxBottom = 5, |
---|
207 | QuadDefault = 0, |
---|
208 | |
---|
209 | //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE |
---|
210 | Max = 6 |
---|
211 | } |
---|
212 | m_value; |
---|
213 | |
---|
214 | inline MeshFaceType(Value v) : m_value(v) {} |
---|
215 | inline operator Value() { return m_value; } |
---|
216 | }; |
---|
217 | |
---|
218 | struct TexCoordPos |
---|
219 | { |
---|
220 | enum Value |
---|
221 | { |
---|
222 | BL, //BottomLeft |
---|
223 | BR, //BottomRight |
---|
224 | TL, //TopLeft |
---|
225 | TR //TopRight |
---|
226 | } |
---|
227 | m_value; |
---|
228 | |
---|
229 | inline TexCoordPos(Value v) : m_value(v) {} |
---|
230 | inline operator Value() { return m_value; } |
---|
231 | }; |
---|
232 | |
---|
233 | class EasyMeshBuildData |
---|
234 | { |
---|
235 | public: |
---|
236 | EasyMeshBuildData() |
---|
237 | { |
---|
238 | m_color = vec4(0.f, 0.f, 0.f, 1.f); |
---|
239 | m_color2 = vec4(0.f, 0.f, 0.f, 1.f); |
---|
240 | m_texcoord_offset = vec2(0.f); |
---|
241 | m_texcoord_offset2 = vec2(0.f); |
---|
242 | m_texcoord_scale = vec2(1.f); |
---|
243 | m_texcoord_scale2 = vec2(1.f); |
---|
244 | m_build_flags = 0; |
---|
245 | for (int i = 0; i < MeshType::Max; ++i) |
---|
246 | { |
---|
247 | m_texcoord_build_type[i] = TexCoordBuildType::TriangleDefault; |
---|
248 | m_texcoord_build_type2[i] = TexCoordBuildType::TriangleDefault; |
---|
249 | } |
---|
250 | } |
---|
251 | |
---|
252 | inline vec4 &Color() { return m_color; } |
---|
253 | inline vec4 &Color2() { return m_color2; } |
---|
254 | inline vec2 &TexCoordOffset() { return m_texcoord_offset; } |
---|
255 | inline vec2 &TexCoordScale() { return m_texcoord_scale; } |
---|
256 | inline vec2 &TexCoordOffset2() { return m_texcoord_offset2; } |
---|
257 | inline vec2 &TexCoordScale2() { return m_texcoord_scale2; } |
---|
258 | |
---|
259 | //UV1 |
---|
260 | void SetTexCoordBuildType(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type[mt] = (1 << (tcbt + 1)) | (m_texcoord_build_type[mt] & 1); } |
---|
261 | TexCoordBuildType GetTexCoordBuildType(MeshType mt) |
---|
262 | { |
---|
263 | uint32_t flag = (uint32_t)((m_texcoord_build_type[mt] & ~(1)) >> 1); |
---|
264 | int i = 0; |
---|
265 | while (flag >>= 1) |
---|
266 | i++; |
---|
267 | return TexCoordBuildType(i); |
---|
268 | } |
---|
269 | void SetTexCoordCustomBuild(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR) |
---|
270 | { |
---|
271 | if (face >= m_texcoord_custom_build[mt].Count()) |
---|
272 | m_texcoord_custom_build[mt].Resize(face + 1); |
---|
273 | m_texcoord_custom_build[mt][face].m1 = BL; |
---|
274 | m_texcoord_custom_build[mt][face].m2 = TR; |
---|
275 | m_texcoord_build_type[mt] |= 1; |
---|
276 | } |
---|
277 | void ClearTexCoordCustomBuild(MeshType mt) { m_texcoord_build_type[mt] &= ~1; } |
---|
278 | /* FIXME : Do something better ? */ |
---|
279 | vec2 TexCoord(MeshType mt, TexCoordPos tcp, MeshFaceType face) |
---|
280 | { |
---|
281 | vec2 BL = vec2(0.f); |
---|
282 | vec2 TR = vec2(0.f); |
---|
283 | if (m_texcoord_build_type[mt] & 1 && face < m_texcoord_custom_build[mt].Count()) |
---|
284 | { |
---|
285 | BL = m_texcoord_custom_build[mt][face].m1; |
---|
286 | TR = m_texcoord_custom_build[mt][face].m2; |
---|
287 | } |
---|
288 | else |
---|
289 | { |
---|
290 | /* unused for now, but will be if new BuildType are added. */ |
---|
291 | TexCoordBuildType tcbt = GetTexCoordBuildType(mt); |
---|
292 | UNUSED(tcbt); |
---|
293 | if (mt == MeshType::Triangle) |
---|
294 | mt = mt; |
---|
295 | else if (mt == MeshType::Quad) |
---|
296 | { |
---|
297 | //There's nothin' else than QuadDefault |
---|
298 | BL = vec2(0.f); |
---|
299 | TR = vec2(1.f); |
---|
300 | } |
---|
301 | else if (mt == MeshType::Box) |
---|
302 | { |
---|
303 | vec2 data[][2] = |
---|
304 | { //TexCoordBuildType::BoxDefault |
---|
305 | { vec2(0.f), vec2(.5f) }, |
---|
306 | { vec2(.5f, 0.f), vec2(1.f, .5f) }, |
---|
307 | { vec2(0.f), vec2(.5f) }, |
---|
308 | { vec2(.5f, 0.f), vec2(1.f, .5f) }, |
---|
309 | { vec2(0.f, .5f), vec2(.5f, 1.f) }, |
---|
310 | { vec2(.5f, .5f), vec2(1.f, 1.f) } |
---|
311 | }; |
---|
312 | BL = data[face][0]; //[tcbt] |
---|
313 | TR = data[face][1]; //[tcbt] |
---|
314 | } |
---|
315 | else if (mt == MeshType::Sphere) |
---|
316 | mt = mt; |
---|
317 | else if (mt == MeshType::Capsule) |
---|
318 | mt = mt; |
---|
319 | else if (mt == MeshType::Torus) |
---|
320 | mt = mt; |
---|
321 | else if (mt == MeshType::Cylinder) |
---|
322 | mt = mt; |
---|
323 | else if (mt == MeshType::Disc) |
---|
324 | mt = mt; |
---|
325 | else if (mt == MeshType::Star) |
---|
326 | mt = mt; |
---|
327 | else if (mt == MeshType::ExpandedStar) |
---|
328 | mt = mt; |
---|
329 | else if (mt == MeshType::Cog) |
---|
330 | mt = mt; |
---|
331 | } |
---|
332 | |
---|
333 | vec2 res = vec2(.0f); |
---|
334 | if (tcp == TexCoordPos::BL) |
---|
335 | res = BL; |
---|
336 | else if (tcp == TexCoordPos::BR) |
---|
337 | res = vec2(TR.x, BL.y); |
---|
338 | else if (tcp == TexCoordPos::TL) |
---|
339 | res = vec2(BL.x, TR.y); |
---|
340 | else if (tcp == TexCoordPos::TR) |
---|
341 | res = TR; |
---|
342 | |
---|
343 | return res * m_texcoord_scale + m_texcoord_offset2; |
---|
344 | } |
---|
345 | |
---|
346 | //UV2 |
---|
347 | void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt] = (1 << (tcbt + 1)) | (m_texcoord_build_type2[mt] & 1); } |
---|
348 | TexCoordBuildType GetTexCoordBuildType2(MeshType mt) |
---|
349 | { |
---|
350 | uint32_t flag = ((m_texcoord_build_type2[mt] & ~(1)) >> 1); |
---|
351 | int i = 0; |
---|
352 | while (flag >>= 1) |
---|
353 | i++; |
---|
354 | return TexCoordBuildType(i); |
---|
355 | } |
---|
356 | void SetTexCoordCustomBuild2(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR) |
---|
357 | { |
---|
358 | if (face >= m_texcoord_custom_build2[mt].Count()) |
---|
359 | m_texcoord_custom_build2[mt].Resize(face + 1); |
---|
360 | m_texcoord_custom_build2[mt][face].m1 = BL; |
---|
361 | m_texcoord_custom_build2[mt][face].m2 = TR; |
---|
362 | m_texcoord_build_type2[mt] |= 1; |
---|
363 | } |
---|
364 | void ClearTexCoordCustomBuild2(MeshType mt) { m_texcoord_build_type2[mt] &= ~1; } |
---|
365 | vec2 TexCoord2(MeshType mt, TexCoordPos tcp, MeshFaceType face) |
---|
366 | { |
---|
367 | vec2 BL = vec2(0.f); |
---|
368 | vec2 TR = vec2(0.f); |
---|
369 | if (m_texcoord_build_type2[mt] & 1 && face < m_texcoord_custom_build2[mt].Count()) |
---|
370 | { |
---|
371 | BL = m_texcoord_custom_build2[mt][face].m1; |
---|
372 | TR = m_texcoord_custom_build2[mt][face].m2; |
---|
373 | } |
---|
374 | else |
---|
375 | { |
---|
376 | TexCoordBuildType tcbt = GetTexCoordBuildType2(mt); |
---|
377 | UNUSED(tcbt); |
---|
378 | if (mt == MeshType::Triangle) |
---|
379 | mt = mt; |
---|
380 | else if (mt == MeshType::Quad) |
---|
381 | { |
---|
382 | //There's nothin' else than QuadDefault |
---|
383 | BL = vec2(0.f); |
---|
384 | TR = vec2(1.f); |
---|
385 | } |
---|
386 | else if (mt == MeshType::Box) |
---|
387 | { |
---|
388 | vec2 data[][2] = |
---|
389 | { //TexCoordBuildType::BoxDefault |
---|
390 | { vec2(0.f), vec2(.5f) }, |
---|
391 | { vec2(.5f, 0.f), vec2(1.f, .5f) }, |
---|
392 | { vec2(0.f), vec2(.5f) }, |
---|
393 | { vec2(.5f, 0.f), vec2(1.f, .5f) }, |
---|
394 | { vec2(0.f, .5f), vec2(.5f, 1.f) }, |
---|
395 | { vec2(.5f, .5f), vec2(1.f, 1.f) } |
---|
396 | }; |
---|
397 | BL = data[face][0]; //[tcbt] |
---|
398 | TR = data[face][1]; //[tcbt] |
---|
399 | } |
---|
400 | else if (mt == MeshType::Sphere) |
---|
401 | mt = mt; |
---|
402 | else if (mt == MeshType::Capsule) |
---|
403 | mt = mt; |
---|
404 | else if (mt == MeshType::Torus) |
---|
405 | mt = mt; |
---|
406 | else if (mt == MeshType::Cylinder) |
---|
407 | mt = mt; |
---|
408 | else if (mt == MeshType::Disc) |
---|
409 | mt = mt; |
---|
410 | else if (mt == MeshType::Star) |
---|
411 | mt = mt; |
---|
412 | else if (mt == MeshType::ExpandedStar) |
---|
413 | mt = mt; |
---|
414 | else if (mt == MeshType::Cog) |
---|
415 | mt = mt; |
---|
416 | } |
---|
417 | |
---|
418 | vec2 res = vec2(.0f); |
---|
419 | if (tcp == TexCoordPos::BL) |
---|
420 | res = BL; |
---|
421 | else if (tcp == TexCoordPos::BR) |
---|
422 | res = vec2(TR.x, BL.y); |
---|
423 | else if (tcp == TexCoordPos::TL) |
---|
424 | res = vec2(BL.x, TR.y); |
---|
425 | else if (tcp == TexCoordPos::TR) |
---|
426 | res = TR; |
---|
427 | |
---|
428 | return res * m_texcoord_scale + m_texcoord_offset2; |
---|
429 | } |
---|
430 | |
---|
431 | inline bool IsEnabled(MeshBuildOperation mbo) { return (m_build_flags & mbo) != 0; } |
---|
432 | inline void Enable(MeshBuildOperation mbo) { m_build_flags |= mbo; } |
---|
433 | inline void Disable(MeshBuildOperation mbo) { m_build_flags &= ~mbo; } |
---|
434 | inline void Toggle(MeshBuildOperation mbo) { m_build_flags ^= mbo; } |
---|
435 | inline void Set(MeshBuildOperation mbo, bool value) { if (value) Enable(mbo); else Disable(mbo); } |
---|
436 | |
---|
437 | public: |
---|
438 | vec4 m_color; |
---|
439 | vec4 m_color2; |
---|
440 | vec2 m_texcoord_offset; |
---|
441 | vec2 m_texcoord_offset2; |
---|
442 | vec2 m_texcoord_scale; |
---|
443 | vec2 m_texcoord_scale2; |
---|
444 | Array<vec2, vec2> m_texcoord_custom_build[MeshType::Max]; |
---|
445 | Array<vec2, vec2> m_texcoord_custom_build2[MeshType::Max]; |
---|
446 | uint32_t m_texcoord_build_type[MeshType::Max]; |
---|
447 | uint32_t m_texcoord_build_type2[MeshType::Max]; |
---|
448 | uint32_t m_build_flags; |
---|
449 | }; |
---|
450 | |
---|
451 | /* A safe enum for MeshCSG operations. */ |
---|
452 | struct CSGUsage |
---|
453 | { |
---|
454 | enum Value |
---|
455 | { |
---|
456 | Union, |
---|
457 | Substract, |
---|
458 | SubstractLoss, //will remove B from A, but not add inverted B |
---|
459 | And, |
---|
460 | Xor, |
---|
461 | } |
---|
462 | m_value; |
---|
463 | |
---|
464 | inline CSGUsage(Value v) : m_value(v) {} |
---|
465 | inline operator Value() { return m_value; } |
---|
466 | }; |
---|
467 | |
---|
468 | /* A safe enum for VertexDictionnary operations. */ |
---|
469 | struct VDictType |
---|
470 | { |
---|
471 | enum Value |
---|
472 | { |
---|
473 | DoesNotExist=-3, |
---|
474 | Alone=-2, |
---|
475 | Master=-1 |
---|
476 | } |
---|
477 | m_value; |
---|
478 | |
---|
479 | inline VDictType(Value v) : m_value(v) {} |
---|
480 | inline operator Value() { return m_value; } |
---|
481 | }; |
---|
482 | |
---|
483 | /* TODO : replace VDict by a proper Half-edge system */ |
---|
484 | //a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes |
---|
485 | class VertexDictionnary |
---|
486 | { |
---|
487 | public: |
---|
488 | int FindVertexMaster(const int search_idx); |
---|
489 | bool FindMatchingVertices(const int search_idx, Array<int> &matching_ids); |
---|
490 | bool FindConnectedVertices(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_vert, Array<int> const *ignored_tri = NULL); |
---|
491 | bool FindConnectedTriangles(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL); |
---|
492 | bool FindConnectedTriangles(const ivec2 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL); |
---|
493 | bool FindConnectedTriangles(const ivec3 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL); |
---|
494 | void AddVertex(int vert_id, vec3 vert_coord); |
---|
495 | bool GetMasterList(Array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.Count() > 0; } |
---|
496 | void Clear() { vertex_list.Empty(); } |
---|
497 | private: |
---|
498 | //<VertexId, VertexLocation, VertexMasterId> |
---|
499 | Array<int, vec3, int> vertex_list; |
---|
500 | //List of the master_ vertices |
---|
501 | Array<int> master_list; |
---|
502 | }; |
---|
503 | |
---|
504 | struct Axis |
---|
505 | { |
---|
506 | enum Value |
---|
507 | { |
---|
508 | X, |
---|
509 | Y, |
---|
510 | Z |
---|
511 | } |
---|
512 | m_value; |
---|
513 | |
---|
514 | inline Axis(Value v) : m_value(v) {} |
---|
515 | inline operator Value() { return m_value; } |
---|
516 | }; |
---|
517 | |
---|
518 | class EasyMesh |
---|
519 | { |
---|
520 | friend class EasyMeshParser; |
---|
521 | |
---|
522 | public: |
---|
523 | EasyMesh(); |
---|
524 | |
---|
525 | bool Compile(char const *command); |
---|
526 | void MeshConvert(GpuShaderData* new_gpu_sdata); |
---|
527 | void MeshConvert(Shader* ProvidedShader = NULL); |
---|
528 | void Render(mat4 const &model); |
---|
529 | |
---|
530 | private: |
---|
531 | void UpdateVertexDict(Array< int, int > &vertex_dict); |
---|
532 | |
---|
533 | //------------------------------------------------------------------------- |
---|
534 | //Mesh CSG operations |
---|
535 | //------------------------------------------------------------------------- |
---|
536 | private: |
---|
537 | void MeshCsg(CSGUsage csg_operation); |
---|
538 | public: |
---|
539 | /* [cmd:csgu] Performs a Union operation as (mesh0_Outside + mesh1_Outside) */ |
---|
540 | void CsgUnion() { MeshCsg(CSGUsage::Union); } |
---|
541 | /* [cmd:csgs] Performs a Substract operation as (mesh0_Outside + mesh1_Inside-inverted) */ |
---|
542 | void CsgSubstract() { MeshCsg(CSGUsage::Substract); } |
---|
543 | /* [cmd:csgsl] Performs a Substract operation without keeping the mesh1 part */ |
---|
544 | void CsgSubstractLoss() { MeshCsg(CSGUsage::SubstractLoss); } |
---|
545 | /* [cmd:csga] Performs an And operation as (mesh0_Inside + mesh1_Inside) */ |
---|
546 | void CsgAnd() { MeshCsg(CSGUsage::And); } |
---|
547 | /* [cmd:csgx] Performs a Xor operation as (m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted) */ |
---|
548 | void CsgXor() { MeshCsg(CSGUsage::Xor); } |
---|
549 | |
---|
550 | public: |
---|
551 | /* [cmd:[] from this point onward, any operation will not be performed on previous vertices */ |
---|
552 | void OpenBrace(); |
---|
553 | /* [cmd:]] Merge current vertices with previous context */ |
---|
554 | void CloseBrace(); |
---|
555 | /* [cmd:tsw] When activation, on negative-scaling, normal fixing will not occur */ |
---|
556 | void ToggleScaleWinding(); |
---|
557 | /* [cmd:sc] Set vertices color */ |
---|
558 | void SetCurColor(vec4 const &color); |
---|
559 | /* [cmd:scb] Set vertices color 2 */ |
---|
560 | void SetCurColor2(vec4 const &color); |
---|
561 | |
---|
562 | private: |
---|
563 | //------------------------------------------------------------------------- |
---|
564 | //Internal : Basic triangle/vertex operations |
---|
565 | //------------------------------------------------------------------------- |
---|
566 | void AddVertex(vec3 const &coord); |
---|
567 | void AddDuplicateVertex(int i); |
---|
568 | void AddLerpVertex(int i, int j, float alpha); |
---|
569 | void AppendQuad(int i1, int i2, int i3, int i4, int base); |
---|
570 | void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base); |
---|
571 | void AppendTriangle(int i1, int i2, int i3, int base); |
---|
572 | void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base); |
---|
573 | void ComputeNormals(int start, int vcount); |
---|
574 | public: //DEBUG |
---|
575 | void ComputeTexCoord(float uv_scale, int uv_offset); |
---|
576 | |
---|
577 | //------------------------------------------------------------------------- |
---|
578 | //Vertices operations |
---|
579 | //------------------------------------------------------------------------- |
---|
580 | void SetVertColor(vec4 const &color); |
---|
581 | void SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale); |
---|
582 | void SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale); |
---|
583 | |
---|
584 | void SetCurVertNormal(vec3 const &normal); |
---|
585 | void SetCurVertColor(vec4 const &color); |
---|
586 | void SetCurVertTexCoord(vec2 const &texcoord); |
---|
587 | void SetCurVertTexCoord2(vec2 const &texcoord); |
---|
588 | |
---|
589 | public: |
---|
590 | //------------------------------------------------------------------------- |
---|
591 | //Mesh transform operations |
---|
592 | //------------------------------------------------------------------------- |
---|
593 | |
---|
594 | /* [cmd:t/tx/ty/tz] Translate vertices |
---|
595 | - v : Translation quantity. |
---|
596 | */ |
---|
597 | void Translate(vec3 const &v); |
---|
598 | /* See Rotate */ |
---|
599 | void RotateX(float angle); |
---|
600 | /* See Rotate */ |
---|
601 | void RotateY(float angle); |
---|
602 | /* See Rotate */ |
---|
603 | void RotateZ(float angle); |
---|
604 | /* [cmd:r/rx/ry/rz] Rotate vertices |
---|
605 | - angle : rotation quantity. |
---|
606 | - axis : rotation axis. |
---|
607 | */ |
---|
608 | void Rotate(float angle, vec3 const &axis); |
---|
609 | /* [cmd:rj] Randomly move vertices along Origin-to-vertex as o2v *= (1.0 + rand(r)) |
---|
610 | - r : jitter maximum value. |
---|
611 | */ |
---|
612 | void RadialJitter(float r); |
---|
613 | /* [cmd:tax] multiply axis y&z by x as y *= (1.0 + (ny * x + xoff)) |
---|
614 | - ny : value of n for y. |
---|
615 | - nz : value of n for z. |
---|
616 | - xoff : value of xoff. |
---|
617 | - absolute (def:1) : if (1) Multiply will use an absolute x. |
---|
618 | */ |
---|
619 | void TaperX(float ny, float nz, float xoff, int absolute=1); |
---|
620 | /* [cmd:tay] Same as TaperX, with Y */ |
---|
621 | void TaperY(float nx, float nz, float yoff, int absolute=1); |
---|
622 | /* [cmd:taz] Same as TaperX, with Z */ |
---|
623 | void TaperZ(float nx, float ny, float zoff, int absolute=1); |
---|
624 | /* [cmd:twx] Twist vertices around x axis with x as rotation value as p = (RotateX(x * t + toff) * p) |
---|
625 | - t : Angle multiplier. |
---|
626 | - toff : Applied offset. |
---|
627 | */ |
---|
628 | void TwistX(float t, float toff); |
---|
629 | /* [cmd:twy] Same as TwistX, with Y */ |
---|
630 | void TwistY(float t, float toff); |
---|
631 | /* [cmd:twz] Same as TwistX, with Z */ |
---|
632 | void TwistZ(float t, float toff); |
---|
633 | /* [cmd:shx] Shear vertices using x value as shear quantity as y += (ny * x + xoff) |
---|
634 | - ny : Value of n for y. |
---|
635 | - nz : Value of n for z. |
---|
636 | - xoff : Value of xoff. |
---|
637 | - absolute (def:1) : if (1) Multiply will use an absolute x. |
---|
638 | */ |
---|
639 | void ShearX(float ny, float nz, float xoff, int absolute=1); |
---|
640 | /* [cmd:shy] Same as ShearX, with Y */ |
---|
641 | void ShearY(float nx, float nz, float yoff, int absolute=1); |
---|
642 | /* [cmd:shz] Same as ShearX, with Z */ |
---|
643 | void ShearZ(float nx, float ny, float zoff, int absolute=1); |
---|
644 | /* [cmd:stx] Stretch vertices using x value as stretch quantity as y += (pow(x, ny) + xoff) |
---|
645 | - ny : Value of n for y. |
---|
646 | - nz : Value of n for z. |
---|
647 | - xoff : Value of xoff. |
---|
648 | */ |
---|
649 | void StretchX(float ny, float nz, float xoff); |
---|
650 | /* [cmd:sty] Same as StretchX, with Y */ |
---|
651 | void StretchY(float nx, float nz, float yoff); |
---|
652 | /* [cmd:stz] Same as StretchX, with Z */ |
---|
653 | void StretchZ(float nx, float ny, float zoff); |
---|
654 | /* [cmd:bdxy] Bend vertices using x as bend quantity along y axis using p = (RotateY(x * t + toff) * p) |
---|
655 | - t : Angle multiplier. |
---|
656 | - xoff : Applied offset. |
---|
657 | */ |
---|
658 | void BendXY(float t, float toff); |
---|
659 | /* [cmd:bdxz] Same as BendXY, with X & Z */ |
---|
660 | void BendXZ(float t, float toff); |
---|
661 | /* [cmd:bdyx] Same as BendXY, with Y & X */ |
---|
662 | void BendYX(float t, float toff); |
---|
663 | /* [cmd:bdyz] Same as BendXY, with Y & Z */ |
---|
664 | void BendYZ(float t, float toff); |
---|
665 | /* [cmd:bdzx] Same as BendXY, with Z & X */ |
---|
666 | void BendZX(float t, float toff); |
---|
667 | /* [cmd:bdzy] Same as BendXY, with Z & Y */ |
---|
668 | void BendZY(float t, float toff); |
---|
669 | private: |
---|
670 | struct MeshTransform |
---|
671 | { |
---|
672 | enum Value |
---|
673 | { |
---|
674 | Taper, |
---|
675 | Twist, |
---|
676 | Bend, |
---|
677 | Stretch, |
---|
678 | Shear |
---|
679 | } |
---|
680 | m_value; |
---|
681 | |
---|
682 | inline MeshTransform(Value v) : m_value(v) {} |
---|
683 | inline operator Value() { return m_value; } |
---|
684 | }; |
---|
685 | void DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, int absolute); |
---|
686 | public: |
---|
687 | /* [cmd:s/sx/sy/sz] Scale vertices |
---|
688 | - s : scale quantity. |
---|
689 | */ |
---|
690 | void Scale(vec3 const &s); |
---|
691 | /* [cmd:mx] Mirror vertices through X-plane |
---|
692 | Acts as an OpenBrace |
---|
693 | */ |
---|
694 | void MirrorX(); |
---|
695 | /* [cmd:my] Mirror vertices through Y-plane |
---|
696 | Acts as an OpenBrace |
---|
697 | */ |
---|
698 | void MirrorY(); |
---|
699 | /* [cmd:mz] Mirror vertices through Z-plane |
---|
700 | Acts as an OpenBrace |
---|
701 | */ |
---|
702 | void MirrorZ(); |
---|
703 | /* [no-cmd] Duplicates vertices and scale duplicate |
---|
704 | Acts as an OpenBrace |
---|
705 | */ |
---|
706 | void DupAndScale(vec3 const &s); |
---|
707 | /* [cmd:ch] Performs a chamfer operation //TODO : Make it work. |
---|
708 | - f : Chamfer quantity. |
---|
709 | */ |
---|
710 | void Chamfer(float f); |
---|
711 | /* [cmd:splt] split triangles in 4 smaller ones. |
---|
712 | - pass : Number of pass applied. |
---|
713 | */ |
---|
714 | void SplitTriangles(int pass); |
---|
715 | private: |
---|
716 | void SplitTriangles(int pass, VertexDictionnary *vert_dict); |
---|
717 | public: |
---|
718 | /* [cmd:smth] Smooth the mesh by subdivising it. |
---|
719 | - main_pass : a main pass is made of (n0 split then n1 smooth) repeat. |
---|
720 | - split_per_main_pass : n0 value in above explanation. |
---|
721 | - smooth_per_main_pass : n1 value in above explanation. |
---|
722 | */ |
---|
723 | void SmoothMesh(int main_pass, int split_per_main_pass, int smooth_per_main_pass); |
---|
724 | |
---|
725 | //------------------------------------------------------------------------- |
---|
726 | //Mesh shape operations |
---|
727 | //------------------------------------------------------------------------- |
---|
728 | |
---|
729 | /* [cmd:ac] Cylinder centered on (0,0,0) with BBox [-.5*max(d1, d2), -.5*h, -.5*max(d1, d2)] |
---|
730 | - nbsides : Number of sides. [+.5*max(d1, d2), +.5*h, +.5*max(d1, d2)] |
---|
731 | - h : Height of the cylinder. |
---|
732 | - d1 : Lower diameter. |
---|
733 | - d2 : Upper diameter. |
---|
734 | - dualside : if (1) will also create inner sides : TOOD:TOREMOVE?? : needed ? |
---|
735 | - smooth : if (1) will smooth normals : TOOD:TOREMOVE : smooth should be handled elsewhere |
---|
736 | - close : if (1) will add discs to close the cylinder |
---|
737 | */ |
---|
738 | void AppendCylinder(int nsides, float h, float d1, float d2, |
---|
739 | int dualside, int smooth, int close); |
---|
740 | /* [cmd:asph] Sphere centered on (0,0,0) with BBox [-.5*d][.5*d] |
---|
741 | - ndivisions : number of subdivisions each Sphere triangle will sustain. |
---|
742 | - d : Diameter. |
---|
743 | */ |
---|
744 | void AppendSphere(int ndivisions, float d); |
---|
745 | /* [cmd:acap] Capsule centered on (0,0,0) with BBox [-.5*d, -(.5*d+h), -.5*d][.5*d, (.5*d+h), .5*d] |
---|
746 | - ndivisions : number of subdivisions each Sphere triangle will sustain. |
---|
747 | - h : Inner height. |
---|
748 | - d : Diameter. |
---|
749 | */ |
---|
750 | void AppendCapsule(int ndivisions, float h, float d); |
---|
751 | /* [cmd:ato] Torus centered on (0,0,0) with BBox [-.5*d2][.5*d2] |
---|
752 | - ndivisions : number of subdivisions of the torus. |
---|
753 | - d1 : Inner diameter. |
---|
754 | - d2 : Outer diameter. |
---|
755 | */ |
---|
756 | void AppendTorus(int ndivisions, float d1, float d2); |
---|
757 | /* [cmd:ab] Box centered on (0,0,0) with BBox [-.5 * size][.5 * size] |
---|
758 | - size : size of the box. |
---|
759 | - chamf : size of the chamfer. |
---|
760 | - smooth : if (1) will smooth normals : TOOD:TOREMOVE : smooth should be handled elsewhere |
---|
761 | */ |
---|
762 | void AppendBox(vec3 const &size, float chamf = 0.f); |
---|
763 | //Same as AppendBox |
---|
764 | void AppendSmoothChamfBox(vec3 const &size, float chamf); |
---|
765 | //Same as AppendBox |
---|
766 | void AppendFlatChamfBox(vec3 const &size, float chamf); |
---|
767 | //Same as AppendBox |
---|
768 | void AppendBox(vec3 const &size, float chamf, bool smooth); |
---|
769 | /* [cmd:as] |
---|
770 | Append a Star centered on (0,0,0) contained within a disc of "max(d1, d2)" diameter. |
---|
771 | - nbranches : Number of branches. |
---|
772 | - d1 : double Length of the branches. |
---|
773 | - d2 : double Length of the "branch" located between d1-branches. |
---|
774 | - fade : if (1) in-between branches use Color2. |
---|
775 | - fade2 : if (1) Star branches use Color2. |
---|
776 | */ |
---|
777 | void AppendStar(int nbranches, float d1, float d2, |
---|
778 | int fade = 0, int fade2 = 0); |
---|
779 | /* [cmd:aes] Star centered on (0,0,0) contained within a disc of "max(max(d1, d2), max(d1 + extrad, d2 + extrad))" diameter. |
---|
780 | Expanded star branches use Color2. |
---|
781 | - nbranches : Number of branches. |
---|
782 | - d1 : Double Length of the branches. |
---|
783 | - d2 : Double Length of the "branch" located between r1-branches. |
---|
784 | - extrad : Extra length added to expand all branches. |
---|
785 | */ |
---|
786 | void AppendExpandedStar(int nbranches, float d1, float d2, float extrad); |
---|
787 | /* [cmd:ad] Disc centered on (0,0,0) with d diameter. |
---|
788 | - nbsides : Number of sides. |
---|
789 | - d : Diameter. |
---|
790 | - fade : if (1) Outer vertices will use Color2 |
---|
791 | */ |
---|
792 | void AppendDisc(int nsides, float d, int fade = 0); |
---|
793 | /* [cmd:at] Triangle centered on (0,0,0) contained within a disc of "d" diameter. |
---|
794 | - d : diameter of the containing disc.. |
---|
795 | - fade : if (1) 2nd & 3rd Vertices will use Color2 |
---|
796 | */ |
---|
797 | void AppendSimpleTriangle(float d, int fade = 0); |
---|
798 | /* [cmd:aq] Quad centered on (0,0,0) contained within BBox [-size*.5f, 0, -size*.5f][size*.5f, 0, size*.5f] |
---|
799 | - size : Size of quad. |
---|
800 | - fade : if (1) 3rd & 4th Vertices will use Color2 |
---|
801 | */ |
---|
802 | void AppendSimpleQuad(float size, int fade = 0); |
---|
803 | private: |
---|
804 | //complex version of above one |
---|
805 | void AppendSimpleQuad(vec2 p1, vec2 p2, float z = 0.f, int fade = 0); |
---|
806 | public: |
---|
807 | /* [cmd:acg] Gear centered on (0,0,0) contained within BBox [-.5*max(d1,d2), -.5*h, -.5*max(d1, d2)] |
---|
808 | - h : Height of the Gear. [+.5*max(d1,d2), +.5*h, +.5*max(d1, d2)] |
---|
809 | - d10 : Upper Inner diameter. |
---|
810 | - d20 : Lower Inner diameter. |
---|
811 | - d1 : Upper Outer diameter. |
---|
812 | - d2 : Lower Outer diameter. |
---|
813 | - d12 : Upper Cog diameter. |
---|
814 | - d22 : Lower Cog diameter. |
---|
815 | - sidemul : multiplier for the size of the cogs. |
---|
816 | - offset : useless |
---|
817 | */ |
---|
818 | void AppendCog(int nbsides, float h, float d10, float d20, float d1, |
---|
819 | float d2, float d12, float d22, float sidemul, int offset); |
---|
820 | |
---|
821 | //------------------------------------------------------------------------- |
---|
822 | //TODO : Mesh Bone operations |
---|
823 | //------------------------------------------------------------------------- |
---|
824 | //void AddBone(int parent_id) {} |
---|
825 | |
---|
826 | //Convenience functions |
---|
827 | public: |
---|
828 | int GetVertexCount() { return m_vert.Count(); } |
---|
829 | vec3 const &GetVertexLocation(int i) { return m_vert[i].m_coord; } |
---|
830 | |
---|
831 | private: |
---|
832 | Array<uint16_t> m_indices; |
---|
833 | Array<VertexData> m_vert; |
---|
834 | |
---|
835 | //<vert count, indices count> |
---|
836 | Array<int, int> m_cursors; |
---|
837 | |
---|
838 | friend class GpuEasyMeshData; |
---|
839 | GpuEasyMeshData m_gpu_data; |
---|
840 | |
---|
841 | public: |
---|
842 | inline EasyMeshBuildData* BD() |
---|
843 | { |
---|
844 | if (!m_build_data) |
---|
845 | m_build_data = new EasyMeshBuildData(); |
---|
846 | return m_build_data; |
---|
847 | }; |
---|
848 | private: |
---|
849 | class EasyMeshBuildData* m_build_data; |
---|
850 | }; |
---|
851 | } /* namespace lol */ |
---|
852 | |
---|
853 | #endif /* __EASYMESH_EASYMESH_H__ */ |
---|
854 | |
---|