source: trunk/src/easymesh/easymeshbuild.h @ 3860

Last change on this file since 3860 was 3860, checked in by touky, 7 years ago

lua property get/set added, not as nice as I wished, but working.

  • Property svn:eol-style set to LF
File size: 18.6 KB
Line 
1//
2// EasyMesh-Build: The code belonging to Vertex build operations
3//
4// Copyright: (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
5//            (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
6//            (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
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#pragma once
14
15namespace lol
16{
17
18//MeshBuildOperation ----------------------------------------------------------
19struct MeshBuildOperationBase : public StructSafeEnum
20{
21    enum Type
22    {
23        //When this flag is up, negative scaling will not invert faces.
24        ScaleWinding = (1 << 0),
25        CommandRecording = (1 << 1),
26        CommandExecution = (1 << 2),
27        QuadWeighting = (1 << 3),
28        IgnoreQuadWeighting = (1 << 4),
29        PostBuildComputeNormals = (1 << 5),
30        PreventVertCleanup = (1 << 6),
31
32        All = 0xffff,
33    };
34protected:
35    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
36    {
37        enum_map[ScaleWinding] = "ScaleWinding";
38        enum_map[CommandRecording] = "CommandRecording";
39        enum_map[CommandExecution] = "CommandExecution";
40        enum_map[QuadWeighting] = "QuadWeighting";
41        enum_map[IgnoreQuadWeighting] = "IgnoreQuadWeighting";
42        enum_map[PostBuildComputeNormals] = "PostBuildComputeNormals";
43        enum_map[PreventVertCleanup] = "PreventVertCleanup";
44        enum_map[All] = "All";
45        return true;
46    }
47};
48typedef SafeEnum<MeshBuildOperationBase> MeshBuildOperation;
49
50//EasyMeshCmdType -------------------------------------------------------------
51struct EasyMeshCmdTypeBase : public StructSafeEnum
52{
53    enum Type
54    {
55        MeshCsg,
56
57        LoopStart,
58        LoopEnd,
59        OpenBrace,
60        CloseBrace,
61
62        ScaleWinding,
63        QuadWeighting,
64        PostBuildNormal,
65        PreventVertCleanup,
66        SetColorA,
67        SetColorB,
68        SetVertColor,
69
70        VerticesMerge,
71        VerticesSeparate,
72
73        Translate,
74        Rotate,
75        RadialJitter,
76        MeshTranform,
77        Scale,
78        DupAndScale,
79        Chamfer,
80
81        SplitTriangles,
82        SmoothMesh,
83
84        AppendCylinder,
85        AppendCapsule,
86        AppendTorus,
87        AppendBox,
88        AppendStar,
89        AppendExpandedStar,
90        AppendDisc,
91        AppendSimpleTriangle,
92        AppendSimpleQuad,
93        AppendCog,
94    };
95protected:
96    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
97    {
98        enum_map[MeshCsg] = "MeshCsg";
99        enum_map[LoopStart] = "LoopStart";
100        enum_map[LoopEnd] = "LoopEnd";
101        enum_map[OpenBrace] = "OpenBrace";
102        enum_map[CloseBrace] = "CloseBrace";
103        enum_map[ScaleWinding] = "ScaleWinding";
104        enum_map[QuadWeighting] = "QuadWeighting";
105        enum_map[PostBuildNormal] = "PostBuildNormal";
106        enum_map[PreventVertCleanup] = "PreventVertCleanup";
107        enum_map[SetColorA] = "SetColorA";
108        enum_map[SetColorB] = "SetColorB";
109        enum_map[SetVertColor] = "SetVertColor";
110        enum_map[VerticesMerge] = "VerticesMerge";
111        enum_map[VerticesSeparate] = "VerticesSeparate";
112        enum_map[Translate] = "Translate";
113        enum_map[Rotate] = "Rotate";
114        enum_map[RadialJitter] = "RadialJitter";
115        enum_map[MeshTranform] = "MeshTranform";
116        enum_map[Scale] = "Scale";
117        enum_map[DupAndScale] = "DupAndScale";
118        enum_map[Chamfer] = "Chamfer";
119        enum_map[SplitTriangles] = "SplitTriangles";
120        enum_map[SmoothMesh] = "SmoothMesh";
121        enum_map[AppendCylinder] = "AppendCylinder";
122        enum_map[AppendCapsule] = "AppendCapsule";
123        enum_map[AppendTorus] = "AppendTorus";
124        enum_map[AppendBox] = "AppendBox";
125        enum_map[AppendStar] = "AppendStar";
126        enum_map[AppendExpandedStar] = "AppendExpandedStar";
127        enum_map[AppendDisc] = "AppendDisc";
128        enum_map[AppendSimpleTriangle] = "AppendSimpleTriangle";
129        enum_map[AppendSimpleQuad] = "AppendSimpleQuad";
130        enum_map[AppendCog] = "AppendCog";
131        return true;
132    }
133};
134typedef SafeEnum<EasyMeshCmdTypeBase> EasyMeshCmdType;
135
136//MeshTypeBase ----------------------------------------------------------------
137struct MeshTypeBase : public StructSafeEnum
138{
139    /* A safe enum for Primitive edge face. */
140    enum Type
141    {
142        Triangle,
143        Quad,
144        Box,
145        Sphere,
146        Capsule,
147        Torus,
148        Cylinder,
149        Disc,
150        Star,
151        ExpandedStar,
152        Cog,
153
154        MAX
155    };
156protected:
157    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
158    {
159        enum_map[Triangle] = "Triangle";
160        enum_map[Quad] = "Quad";
161        enum_map[Box] = "Box";
162        enum_map[Sphere] = "Sphere";
163        enum_map[Capsule] = "Capsule";
164        enum_map[Torus] = "Torus";
165        enum_map[Cylinder] = "Cylinder";
166        enum_map[Disc] = "Disc";
167        enum_map[Star] = "Star";
168        enum_map[ExpandedStar] = "ExpandedStar";
169        enum_map[Cog] = "Cog";
170        enum_map[MAX] = "MAX";
171        return true;
172    }
173};
174typedef SafeEnum<MeshTypeBase> MeshType;
175
176//TexCoordBuildType -----------------------------------------------------------
177struct TexCoordBuildTypeBase : public StructSafeEnum
178{
179    enum Type
180    {
181        TriangleDefault,
182        QuadDefault,
183        BoxDefault,
184        SphereDefault,
185        CapsuleDefault,
186        TorusDefault,
187        CylinderDefault,
188        DiscDefault,
189        StarDefault,
190        ExpandedStarDefault,
191        CogDefault,
192
193        //NEVER FORGET TO INCREMENT THIS WHEN ADDING A VALUE
194        Max
195    };
196protected:
197    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
198    {
199        enum_map[TriangleDefault] = "TriangleDefault";
200        enum_map[QuadDefault] = "QuadDefault";
201        enum_map[BoxDefault] = "BoxDefault";
202        enum_map[SphereDefault] = "SphereDefault";
203        enum_map[CapsuleDefault] = "CapsuleDefault";
204        enum_map[TorusDefault] = "TorusDefault";
205        enum_map[CylinderDefault] = "CylinderDefault";
206        enum_map[DiscDefault] = "DiscDefault";
207        enum_map[StarDefault] = "StarDefault";
208        enum_map[ExpandedStarDefault] = "ExpandedStarDefault";
209        enum_map[CogDefault] = "CogDefault";
210        enum_map[Max] = "Max";
211        return true;
212    }
213};
214typedef SafeEnum<TexCoordBuildTypeBase> TexCoordBuildType;
215
216//MeshFaceType ----------------------------------------------------------------
217struct MeshFaceTypeBase : public StructSafeEnum
218{
219    enum Type
220    {
221        BoxFront = 0,
222        QuadDefault = 0,
223        BoxLeft = 1,
224        BoxBack = 2,
225        BoxRight = 3,
226        BoxTop = 4,
227        BoxBottom = 5,
228
229        MAX
230    };
231protected:
232    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
233    {
234        enum_map[BoxFront] = "BoxFront";
235        enum_map[QuadDefault] = "QuadDefault";
236        enum_map[BoxLeft] = "BoxLeft";
237        enum_map[BoxBack] = "BoxBack";
238        enum_map[BoxRight] = "BoxRight";
239        enum_map[BoxTop] = "BoxTop";
240        enum_map[BoxBottom] = "BoxBottom";
241        enum_map[MAX] = "MAX";
242        return true;
243    }
244};
245typedef SafeEnum<MeshFaceTypeBase> MeshFaceType;
246
247//TexCoordPos -----------------------------------------------------------------
248struct TexCoordPosBase : public StructSafeEnum
249{
250    enum Type
251    {
252        BL, // Bottom Left
253        BR, // Bottom Right
254        TL, // Top Left
255        TR  // Top Right
256    };
257protected:
258    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
259    {
260        enum_map[BL] = "BL";
261        enum_map[BR] = "BR";
262        enum_map[TL] = "TL";
263        enum_map[TR] = "TR";
264        return true;
265    }
266};
267typedef SafeEnum<TexCoordPosBase> TexCoordPos;
268
269class EasyMeshBuildData
270{
271public:
272    EasyMeshBuildData()
273    {
274        m_color_a = vec4(0.f, 0.f, 0.f, 1.f);
275        m_color_b = vec4(0.f, 0.f, 0.f, 1.f);
276        m_texcoord_offset = vec2(0.f);
277        m_texcoord_offset2 = vec2(0.f);
278        m_texcoord_scale = vec2(1.f);
279        m_texcoord_scale2 = vec2(1.f);
280        m_build_flags = 0;
281        m_i_cmd = 0;
282        m_exec_nb = -1;
283        for (int i = 0; i < MeshType::MAX; ++i)
284        {
285            m_texcoord_build_type[i] = TexCoordBuildType::TriangleDefault;
286            m_texcoord_build_type2[i] = TexCoordBuildType::TriangleDefault;
287        }
288    }
289
290    inline CommandStack &CmdStack() { return m_stack; }
291    inline int &Cmdi()              { return m_i_cmd; }
292    inline int &CmdExecNb()         { return m_exec_nb; }
293    inline array<int, int> &LoopStack(){ return m_loop_stack; }
294    inline vec4 &ColorA()           { return m_color_a; }
295    inline vec4 &ColorB()           { return m_color_b; }
296    inline vec2 &TexCoordOffset()   { return m_texcoord_offset; }
297    inline vec2 &TexCoordScale()    { return m_texcoord_scale; }
298    inline vec2 &TexCoordOffset2()  { return m_texcoord_offset2; }
299    inline vec2 &TexCoordScale2()   { return m_texcoord_scale2; }
300
301    //UV1
302    void SetTexCoordBuildType(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type[mt.ToScalar()] = (1 << (tcbt.ToScalar() + 1)) | (m_texcoord_build_type[mt.ToScalar()] & 1); }
303    TexCoordBuildType GetTexCoordBuildType(MeshType mt)
304    {
305        uint32_t flag = (uint32_t)((m_texcoord_build_type[mt.ToScalar()] & ~(1)) >> 1);
306        int i = 0;
307        while (flag >>= 1)
308            i++;
309        return TexCoordBuildType(i);
310    }
311    void SetTexCoordCustomBuild(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
312    {
313        if (face.ToScalar() >= m_texcoord_custom_build[mt.ToScalar()].Count())
314            m_texcoord_custom_build[mt.ToScalar()].Resize(face.ToScalar() + 1);
315        m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m1 = BL;
316        m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m2 = TR;
317        m_texcoord_build_type[mt.ToScalar()] |= 1;
318    }
319    void ClearTexCoordCustomBuild(MeshType mt) { m_texcoord_build_type[mt.ToScalar()] &= ~1; }
320    /* FIXME : Do something better ? */
321    vec2 TexCoord(MeshType mt, TexCoordPos tcp, MeshFaceType face)
322    {
323        vec2 BL = vec2(0.f);
324        vec2 TR = vec2(0.f);
325        if (m_texcoord_build_type[mt.ToScalar()] & 1
326             && face.ToScalar() < m_texcoord_custom_build[mt.ToScalar()].Count())
327        {
328            BL = m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m1;
329            TR = m_texcoord_custom_build[mt.ToScalar()][face.ToScalar()].m2;
330        }
331        else
332        {
333            /* unused for now, but will be if new BuildType are added. */
334            TexCoordBuildType tcbt = GetTexCoordBuildType(mt);
335            UNUSED(tcbt);
336            if (mt == MeshType::Triangle)
337                mt = mt;
338            else if (mt == MeshType::Quad)
339            {
340                // There's nothin' else than QuadDefault
341                BL = vec2(0.f);
342                TR = vec2(1.f);
343            }
344            else if (mt == MeshType::Box)
345            {
346                vec2 data[][2] =
347                { // TexCoordBuildType::BoxDefault
348                    { vec2(0.f), vec2(.5f) },
349                    { vec2(.5f, 0.f), vec2(1.f, .5f) },
350                    { vec2(0.f), vec2(.5f) },
351                    { vec2(.5f, 0.f), vec2(1.f, .5f) },
352                    { vec2(0.f, .5f), vec2(.5f, 1.f) },
353                    { vec2(.5f, .5f), vec2(1.f, 1.f) }
354                };
355                BL = data[face.ToScalar()][0]; // [tcbt]
356                TR = data[face.ToScalar()][1]; // [tcbt]
357            }
358            else if (mt == MeshType::Sphere)
359                mt = mt;
360            else if (mt == MeshType::Capsule)
361                mt = mt;
362            else if (mt == MeshType::Torus)
363                mt = mt;
364            else if (mt == MeshType::Cylinder)
365                mt = mt;
366            else if (mt == MeshType::Disc)
367                mt = mt;
368            else if (mt == MeshType::Star)
369                mt = mt;
370            else if (mt == MeshType::ExpandedStar)
371                mt = mt;
372            else if (mt == MeshType::Cog)
373                mt = mt;
374        }
375
376        vec2 res = vec2(.0f);
377        if (tcp == TexCoordPos::BL)
378            res = BL;
379        else if (tcp == TexCoordPos::BR)
380            res = vec2(TR.x, BL.y);
381        else if (tcp == TexCoordPos::TL)
382            res = vec2(BL.x, TR.y);
383        else if (tcp == TexCoordPos::TR)
384            res = TR;
385
386        return res * m_texcoord_scale + m_texcoord_offset2;
387    }
388
389    // UV2
390    void SetTexCoordBuildType2(MeshType mt, TexCoordBuildType tcbt) { m_texcoord_build_type2[mt.ToScalar()] = (1 << (tcbt.ToScalar() + 1)) | (m_texcoord_build_type2[mt.ToScalar()] & 1); }
391    TexCoordBuildType GetTexCoordBuildType2(MeshType mt)
392    {
393        uint32_t flag = ((m_texcoord_build_type2[mt.ToScalar()] & ~(1)) >> 1);
394        int i = 0;
395        while (flag >>= 1)
396            i++;
397        return TexCoordBuildType(i);
398    }
399    void SetTexCoordCustomBuild2(MeshType mt, MeshFaceType face, vec2 BL, vec2 TR)
400    {
401        if (face.ToScalar() >= m_texcoord_custom_build2[mt.ToScalar()].Count())
402            m_texcoord_custom_build2[mt.ToScalar()].Resize(face.ToScalar() + 1);
403        m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m1 = BL;
404        m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m2 = TR;
405        m_texcoord_build_type2[mt.ToScalar()] |= 1;
406    }
407    void ClearTexCoordCustomBuild2(MeshType mt) { m_texcoord_build_type2[mt.ToScalar()] &= ~1; }
408    vec2 TexCoord2(MeshType mt, TexCoordPos tcp, MeshFaceType face)
409    {
410        vec2 BL = vec2(0.f);
411        vec2 TR = vec2(0.f);
412        if (m_texcoord_build_type2[mt.ToScalar()] & 1
413             && face.ToScalar() < m_texcoord_custom_build2[mt.ToScalar()].Count())
414        {
415            BL = m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m1;
416            TR = m_texcoord_custom_build2[mt.ToScalar()][face.ToScalar()].m2;
417        }
418        else
419        {
420            TexCoordBuildType tcbt = GetTexCoordBuildType2(mt);
421            UNUSED(tcbt);
422            if (mt == MeshType::Triangle)
423                mt = mt;
424            else if (mt == MeshType::Quad)
425            {
426                // There's nothin' else than QuadDefault
427                BL = vec2(0.f);
428                TR = vec2(1.f);
429            }
430            else if (mt == MeshType::Box)
431            {
432                vec2 data[][2] =
433                { // TexCoordBuildType::BoxDefault
434                    { vec2(0.f), vec2(.5f) },
435                    { vec2(.5f, 0.f), vec2(1.f, .5f) },
436                    { vec2(0.f), vec2(.5f) },
437                    { vec2(.5f, 0.f), vec2(1.f, .5f) },
438                    { vec2(0.f, .5f), vec2(.5f, 1.f) },
439                    { vec2(.5f, .5f), vec2(1.f, 1.f) }
440                };
441                BL = data[face.ToScalar()][0]; // [tcbt]
442                TR = data[face.ToScalar()][1]; // [tcbt]
443            }
444            else if (mt == MeshType::Sphere)
445                mt = mt;
446            else if (mt == MeshType::Capsule)
447                mt = mt;
448            else if (mt == MeshType::Torus)
449                mt = mt;
450            else if (mt == MeshType::Cylinder)
451                mt = mt;
452            else if (mt == MeshType::Disc)
453                mt = mt;
454            else if (mt == MeshType::Star)
455                mt = mt;
456            else if (mt == MeshType::ExpandedStar)
457                mt = mt;
458            else if (mt == MeshType::Cog)
459                mt = mt;
460        }
461
462        vec2 res = vec2(.0f);
463        if (tcp == TexCoordPos::BL)
464            res = BL;
465        else if (tcp == TexCoordPos::BR)
466            res = vec2(TR.x, BL.y);
467        else if (tcp == TexCoordPos::TL)
468            res = vec2(BL.x, TR.y);
469        else if (tcp == TexCoordPos::TR)
470            res = TR;
471
472        return res * m_texcoord_scale + m_texcoord_offset2;
473    }
474
475    inline bool IsEnabled(MeshBuildOperation mbo) { return (m_build_flags & mbo.ToScalar()) != 0; }
476    inline void Enable(MeshBuildOperation mbo) { m_build_flags |= mbo.ToScalar(); }
477    inline void Disable(MeshBuildOperation mbo) { m_build_flags &= ~mbo.ToScalar(); }
478    inline void Toggle(MeshBuildOperation mbo) { m_build_flags ^= mbo.ToScalar(); }
479    inline void Set(MeshBuildOperation mbo, bool value) { if (value) Enable(mbo); else Disable(mbo); }
480
481public:
482    CommandStack        m_stack;
483    int                 m_i_cmd;
484    int                 m_exec_nb;
485    array<int, int>     m_loop_stack;
486    vec4                m_color_a;
487    vec4                m_color_b;
488    vec2                m_texcoord_offset;
489    vec2                m_texcoord_offset2;
490    vec2                m_texcoord_scale;
491    vec2                m_texcoord_scale2;
492    array<vec2, vec2>   m_texcoord_custom_build[MeshType::MAX];
493    array<vec2, vec2>   m_texcoord_custom_build2[MeshType::MAX];
494    uint32_t            m_texcoord_build_type[MeshType::MAX];
495    uint32_t            m_texcoord_build_type2[MeshType::MAX];
496    uint32_t            m_build_flags;
497};
498
499//VDictType -- A safe enum for VertexDictionnary operations. ------------------
500struct VDictTypeBase : public StructSafeEnum
501{
502    enum Type
503    {
504        DoesNotExist = -3,
505        Alone = -2,
506        Master = -1,
507    };
508protected:
509    virtual bool BuildEnumMap(map<int64_t, String>& enum_map)
510    {
511        enum_map[DoesNotExist] = "DoesNotExist";
512        enum_map[Alone] = "Alone";
513        enum_map[Master] = "Master";
514        return true;
515    }
516};
517typedef SafeEnum<VDictTypeBase> VDictType;
518
519/* TODO : replace VDict by a proper Half-edge system */
520//a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes
521class VertexDictionnary
522{
523public:
524    int FindVertexMaster(const int search_idx);
525    bool FindMatchingVertices(const int search_idx, array<int> &matching_ids);
526    bool FindConnectedVertices(const int search_idx, const array<uint16_t> &tri_list, const int tri0, array<int> &connected_vert, array<int> const *ignored_tri = nullptr);
527    bool FindConnectedTriangles(const int search_idx, const array<uint16_t> &tri_list, const int tri0, array<int> &connected_tri, array<int> const *ignored_tri = nullptr);
528    bool FindConnectedTriangles(const ivec2 &search_idx, const array<uint16_t> &tri_list, const int tri0, array<int> &connected_tri, array<int> const *ignored_tri = nullptr);
529    bool FindConnectedTriangles(const ivec3 &search_idx, const array<uint16_t> &tri_list, const int tri0, array<int> &connected_tri, array<int> const *ignored_tri = nullptr);
530    void RegisterVertex(int vert_id, vec3 vert_coord);
531    void RemoveVertex(int vert_id);
532    bool GetMasterList(array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.Count() > 0; }
533    void Clear() { vertex_list.Empty(); }
534private:
535    //<VertexId, VertexLocation, VertexMasterId>
536    array<int, vec3, int>   vertex_list;
537    //List of the master_ vertices
538    array<int>              master_list;
539};
540
541} /* namespace lol */
542
Note: See TracBrowser for help on using the repository browser.