Changeset 3843


Ignore:
Timestamp:
Feb 28, 2015, 6:34:34 PM (7 years ago)
Author:
touky
Message:

First pass of EasyMesh split & refactor
Big FAT pass on windows-warning. It is better now.

Location:
trunk
Files:
22 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/doc/samples/btphystest.cpp

    r3788 r3843  
    340340        m_target_timer = TARGET_TIMER;
    341341        if (m_cam_target == -1)
    342             m_cam_target = rand(m_physobj_list.Count());
     342            m_cam_target = rand((int)m_physobj_list.Count());
    343343        else
    344344            m_cam_target = -1;
  • trunk/doc/samples/physicobject.h

    r3788 r3843  
    174174#endif
    175175
    176         MeshLimit << MeshRand.Count();
     176        MeshLimit << (int)MeshRand.Count();
    177177        MeshType << 1;
    178178#endif //USE_SPHERE
     
    216216        int RandLimit = RandValue;
    217217        if (MeshLimit.Count() <= RandValue || RandValue < 0)
    218             RandLimit = rand(MeshLimit.Count() - 1);
     218            RandLimit = rand((int)MeshLimit.Count() - 1);
    219219        RandValue = rand(MeshLimit[RandLimit], MeshLimit[RandLimit + 1]);
    220220
  • trunk/doc/tutorial/01_triangle.cpp

    r3788 r3843  
    2424public:
    2525    Triangle()
    26       : m_vertices({ vec2( 0.0,  0.8),
    27                      vec2(-0.8, -0.8),
    28                      vec2( 0.8, -0.8) }),
     26      : m_vertices({ vec2( 0.0f,  0.8f),
     27                     vec2(-0.8f, -0.8f),
     28                     vec2( 0.8f, -0.8f) }),
    2929        m_ready(false)
    3030    {
  • trunk/doc/tutorial/02_cube.cpp

    r3788 r3843  
    103103        m_lines_ibo->Bind();
    104104        m_vdecl->DrawIndexedElements(MeshPrimitive::Lines, 0, 0,
    105                                      m_mesh.Count(), 0, m_lines_indices.Count());
     105                                    (int)m_mesh.Count(), 0, (int)m_lines_indices.Count());
    106106        m_lines_ibo->Unbind();
    107107
     
    109109        m_faces_ibo->Bind();
    110110        m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0,
    111                                      m_mesh.Count(), 0, m_faces_indices.Count());
     111                                    (int)m_mesh.Count(), 0, (int)m_faces_indices.Count());
    112112        m_faces_ibo->Unbind();
    113113
  • trunk/doc/tutorial/04_texture.cpp

    r3788 r3843  
    5151
    5252        int height = m_heightmap.Last();
    53         height = (height + 127 + 40 * lol::sin(m_frames * 0.03) + rand() % 97 - 38) / 2;
     53        height = (int)(height + 127 + 40 * lol::sin(m_frames * 0.03) + rand() % 97 - 38) / 2;
    5454        height = std::max(15, std::min(height, 240));
    5555        m_heightmap.Last() = height;
  • trunk/doc/tutorial/06_sprite.cpp

    r3788 r3843  
    3535        for (int i = 0; i < SPRITE_COUNT; ++i)
    3636        {
    37             m_sprites.Push(vec3(rand(-96, 640), rand(-96, 480), 0),
     37            m_sprites.Push(vec3((float)rand(-96, 640), (float)rand(-96, 480), 0.f),
    3838                           rand(0.f, 1.f));
    3939        }
     
    5757            m_sprites[i].m2 = lol::fmod(m_sprites[i].m2 + seconds, 1.f);
    5858            if (m_sprites[i].m1.y > 480 + 48)
    59                 m_sprites[i].m1.y = rand(-96, -48);
     59                m_sprites[i].m1.y = (float)rand(-96, -48);
    6060        }
    6161
  • trunk/doc/tutorial/07_input.cpp

    r3788 r3843  
    182182        m_lines_ibo->Bind();
    183183        m_vdecl->DrawIndexedElements(MeshPrimitive::Lines, 0, 0,
    184                                      m_mesh.Count(), 0, m_lines_indices.Count());
     184                                    (int)m_mesh.Count(), 0, (int)m_lines_indices.Count());
    185185        m_lines_ibo->Unbind();
    186186
     
    188188        m_faces_ibo->Bind();
    189189        m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0,
    190                                      m_mesh.Count(), 0, m_faces_indices.Count());
     190                                    (int)m_mesh.Count(), 0, (int)m_faces_indices.Count());
    191191        m_faces_ibo->Unbind();
    192192
  • trunk/doc/tutorial/11_fractal.cpp

    r3788 r3843  
    9494            }
    9595
    96             uint8_t red = r * 255.99f;
    97             uint8_t green = g * 255.99f;
    98             uint8_t blue = b * 255.99f;
     96            uint8_t red   = (uint8_t)r * 256;
     97            uint8_t green = (uint8_t)g * 256;
     98            uint8_t blue  = (uint8_t)b * 256;
    9999#if defined _XBOX
    100100            m_palette.Push(u8vec4(255, red, green, blue));
     
    108108#if !defined __native_client__
    109109        m_centertext = new Text(NULL, "data/font/ascii.png");
    110         m_centertext->SetPos(vec3(5, m_window_size.y - 15, 1));
     110        m_centertext->SetPos(vec3(5, (float)m_window_size.y - 15, 1));
    111111        Ticker::Ref(m_centertext);
    112112
    113113        m_mousetext = new Text(NULL, "data/font/ascii.png");
    114         m_mousetext->SetPos(vec3(5, m_window_size.y - 29, 1));
     114        m_mousetext->SetPos(vec3(5, (float)m_window_size.y - 29, 1));
    115115        Ticker::Ref(m_mousetext);
    116116
    117117        m_zoomtext = new Text(NULL, "data/font/ascii.png");
    118         m_zoomtext->SetPos(vec3(5, m_window_size.y - 43, 1));
     118        m_zoomtext->SetPos(vec3(5, (float)m_window_size.y - 43, 1));
    119119        Ticker::Ref(m_zoomtext);
    120120#endif
     
    286286        for (int i = 0; i < 4; i++)
    287287        {
    288             m_zoom_settings[i][0] += 0.5 * (1.0 - m_zoom_settings[i][2]);
    289             m_zoom_settings[i][1] -= 0.5 * (1.0 - m_zoom_settings[i][2]);
     288            m_zoom_settings[i][0] += 0.5f * (1.0f - m_zoom_settings[i][2]);
     289            m_zoom_settings[i][1] -= 0.5f * (1.0f - m_zoom_settings[i][2]);
    290290        }
    291291
     
    355355        {
    356356            double xr, yr, x0, y0, x1, y1, x2, y2, x3, y3;
    357             dcmplx z0 = c + TexelToWorldOffset(vec2(i, j));
     357            dcmplx z0 = c + TexelToWorldOffset(vec2(ivec2(i, j)));
    358358            //dcmplx r0(0.28693186889504513, 0.014286693904085048);
    359359            //dcmplx r0(0.001643721971153, 0.822467633298876);
     
    410410                double f = iter;
    411411                union { double n; uint64_t x; } u = { n };
    412                 double k = (u.x >> 42) - (((1 << 10) - 1) << 10);
     412                double k = (double)(u.x >> 42) - (((1 << 10) - 1) << 10);
    413413                k *= k1;
    414414
  • trunk/doc/tutorial/12_voronoi.cpp

    r3788 r3843  
    207207                float j = (float)i;
    208208                float f_time = (float)m_time;
    209                 voronoi_points.Push(vec3(256.f) + 196.f * vec3(lol::cos( f_time + j * 2.0 * F_PI / mi), lol::sin( f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
    210                 voronoi_points.Push(vec3(256.f) + 128.f * vec3(lol::cos(-f_time + j * 2.0 * F_PI / mi), lol::sin(-f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
    211                 voronoi_points.Push(vec3(256.f) + 64.f *  vec3(lol::cos( f_time + j * 2.0 * F_PI / mi), lol::sin( f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
    212                 voronoi_points.Push(vec3(256.f) + 32.f *  vec3(lol::cos(-f_time + j * 2.0 * F_PI / mi), lol::sin(-f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
    213             }
    214             voronoi_points.Push(vec3(256.f), vec2(.0f));
     209                voronoi_points.Push(vec3(256.f) + 196.f * vec3(lol::cos( f_time + j * 2.f * F_PI / mi), lol::sin( f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
     210                voronoi_points.Push(vec3(256.f) + 128.f * vec3(lol::cos(-f_time + j * 2.f * F_PI / mi), lol::sin(-f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
     211                voronoi_points.Push(vec3(256.f) +  64.f * vec3(lol::cos( f_time + j * 2.f * F_PI / mi), lol::sin( f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
     212                voronoi_points.Push(vec3(256.f) +  32.f * vec3(lol::cos(-f_time + j * 2.f * F_PI / mi), lol::sin(-f_time + j * 2.f * F_PI / mi), .0f), vec2(.0f));
     213            }
     214            voronoi_points.Push(vec3(256.f), vec2(0.f));
    215215        }
    216216
  • trunk/src/Makefile.am

    r3807 r3843  
    7171    easymesh/easymeshbuild.cpp easymesh/easymeshbuild.h \
    7272    easymesh/easymeshrender.cpp easymesh/easymeshrender.h \
    73     easymesh/easymesh.cpp easymesh/easymesh.h \
     73    easymesh/easymesh.cpp easymesh/easymeshprimitive.cpp \
     74    easymesh/easymeshtransform.cpp easymesh/easymesh.h \
    7475    easymesh/csgbsp.cpp easymesh/csgbsp.h \
    7576    easymesh/shiny.lolfx easymesh/shinyflat.lolfx \
  • trunk/src/easymesh/csgbsp.cpp

    r3577 r3843  
    3434    {
    3535        if (m_tree.Count() != 0)
    36             m_tree[above_idx].m_leaves[leaf_type] = m_tree.Count();
     36            m_tree[above_idx].m_leaves[leaf_type] = (int32_t)m_tree.Count();
    3737        m_tree.Push(CsgBspLeaf(origin, normal, above_idx));
    38         return m_tree.Count() - 1;
     38        return (int)m_tree.Count() - 1;
    3939    }
    4040
     
    134134            {
    135135                Leaf_to_add.Push(1 - leaf_type, leaf_idx, v[isec_base], v[((isec_base + 1) % 3)], isec_v[v_idx0], -1);
    136                 Leaf_to_add.Push(1 - leaf_type, leaf_idx, v[isec_base], isec_v[v_idx0], isec_v[v_idx1], Leaf_to_add.Count() - 1);
     136                Leaf_to_add.Push(1 - leaf_type, leaf_idx, v[isec_base], isec_v[v_idx0], isec_v[v_idx1], (int)Leaf_to_add.Count() - 1);
    137137            }
    138138            else
     
    345345                                    continue;
    346346#endif
    347                                 new_v_idx[k] = vert_list.Count();
     347                                new_v_idx[k] = (int)vert_list.Count();
    348348                                vec3 PmV0 = (isec_v[k] - vert_list[t[isec_i[k]]].m1);
    349349                                vec3 V1mV0 = (vert_list[t[(isec_i[k] + 1) % 3]].m1 - vert_list[t[isec_i[k]]].m1);
     
    359359                            //Leaf_type is the type for the triangle that is alone on its side.
    360360                            int leaf_type = res_side[(isec_base + 2) % 3];
    361                             int tri_to_remove = tri_to_process.Count() - 1;
     361                            int tri_to_remove = (int)tri_to_process.Count() - 1;
    362362
    363363#if 0
  • trunk/src/easymesh/easymesh.cpp

    r3779 r3843  
    22// Lol Engine
    33//
    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>
     4// Copyright: (c) 2010-2015 Sam Hocevar <sam@hocevar.net>
     5//            (c) 2009-2015 Cédric Lecacheur <jordx@free.fr>
     6//            (c) 2009-2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
    77//   This program is free software; you can redistribute it and/or
    88//   modify it under the terms of the Do What The Fuck You Want To
     
    200200
    201201    if (BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
    202         ComputeNormals(0, m_indices.Count());
     202        ComputeNormals(0, (int)m_indices.Count());
    203203
    204204    BD()->Disable(MeshBuildOperation::PostBuildComputeNormals);
     
    259259    }
    260260
    261     m_cursors.Push(m_vert.Count(), m_indices.Count());
     261    m_cursors.Push((int)m_vert.Count(), (int)m_indices.Count());
    262262}
    263263
     
    293293
    294294//-------------------
    295 // "Collisions" functions
     295//Mesh Cursor operations
    296296//-------------------
    297297
     
    328328    for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    329329    {
    330         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    331         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count());
    332         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1);
    333         for (int i = start_point; i < end_point; i += 3)
    334             mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord,
     330        ptrdiff_t start_point = (mesh_id == 0) ? (cursor_start) : (m_cursors.Last().m2);
     331        ptrdiff_t end_point   = (mesh_id == 0) ? (m_cursors.Last().m2) : (m_indices.Count());
     332        CsgBsp &mesh_bsp      = (mesh_id == 0) ? (mesh_bsp_0) : (mesh_bsp_1);
     333        for (ptrdiff_t i = start_point; i < end_point; i += 3)
     334            mesh_bsp.AddTriangleToTree((int)i, m_vert[m_indices[i]].m_coord,
    335335                                          m_vert[m_indices[i + 1]].m_coord,
    336336                                          m_vert[m_indices[i + 2]].m_coord);
     
    338338
    339339    //BSP Usage : let's crunch all triangles on the correct BSP
    340     int indices_count = m_indices.Count();
    341     for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    342     {
    343         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    344         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count);
    345         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0);
     340    ptrdiff_t indices_count = m_indices.Count();
     341    for (ptrdiff_t mesh_id = 0; mesh_id < 2; mesh_id++)
     342    {
     343        ptrdiff_t start_point = (mesh_id == 0) ? (cursor_start) : (m_cursors.Last().m2);
     344        ptrdiff_t end_point   = (mesh_id == 0) ? (m_cursors.Last().m2) : (indices_count);
     345        CsgBsp &mesh_bsp      = (mesh_id == 0) ? (mesh_bsp_1) : (mesh_bsp_0);
    346346        array< vec3, int, int, float > vert_list;
    347347        array< int, int, int, int > tri_list;
     
    353353        tri_list.Reserve(3);
    354354
    355         for (int i = start_point; i < end_point; i += 3)
     355        for (ptrdiff_t i = start_point; i < end_point; i += 3)
    356356        {
    357357            int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord,
    358358                                                     m_vert[m_indices[i + 1]].m_coord,
    359359                                                     m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list);
    360             int tri_base_idx = m_indices.Count();
     360            ptrdiff_t tri_base_idx = m_indices.Count();
    361361
    362362            //one split has been done, we need to had the new vertices & the new triangles.
    363363            if (Result == 1)
    364364            {
    365                 triangle_to_kill.Push(i);
     365                triangle_to_kill.Push((int)i);
    366366#if 1
    367                 int base_idx = m_vert.Count();
    368                 for (int k = 3; k < vert_list.Count(); k++)
     367                ptrdiff_t base_idx = m_vert.Count();
     368                for (ptrdiff_t k = 3; k < vert_list.Count(); k++)
    369369                {
    370                     int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3);
    371                     int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3);
    372 
    373                     AddVertex(vert_list[k].m1);
     370                    ptrdiff_t P0 = (vert_list[k].m2 < 3) ? (m_indices[i + vert_list[k].m2]) : (base_idx + vert_list[k].m2 - 3);
     371                    ptrdiff_t P1 = (vert_list[k].m3 < 3) ? (m_indices[i + vert_list[k].m3]) : (base_idx + vert_list[k].m3 - 3);
     372
     373                    InternalAddVertex(vert_list[k].m1);
    374374
    375375                    //Normal : bad calculations there.
     
    391391#endif
    392392                }
    393                 for (int k = 0; k < tri_list.Count(); k++)
     393                for (ptrdiff_t k = 0; k < tri_list.Count(); k++)
    394394                {
    395                     int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3));
    396                     int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3));
    397                     int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3));
    398                     AppendTriangle(P0, P1, P2, 0);
     395                    int P0 = (int)(tri_list[k].m2 < 3) ? (m_indices[i + tri_list[k].m2]) : ((int)base_idx + (tri_list[k].m2 - 3));
     396                    int P1 = (int)(tri_list[k].m3 < 3) ? (m_indices[i + tri_list[k].m3]) : ((int)base_idx + (tri_list[k].m3 - 3));
     397                    int P2 = (int)(tri_list[k].m4 < 3) ? (m_indices[i + tri_list[k].m4]) : ((int)base_idx + (tri_list[k].m4 - 3));
     398                    InternalAddTriangle(P0, P1, P2, 0);
    399399                }
    400400#endif
     
    406406                for (int k = 0; k < tri_list.Count(); k++)
    407407                {
    408                     int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3));
     408                    ptrdiff_t tri_idx = (ptrdiff_t)((tri_list.Count() == 1) ? (i) : ((int)tri_base_idx + k * 3));
    409409
    410410                    //Triangle Kill Test
     
    421421                        (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT))
    422422                    {
    423                         triangle_to_kill.Push(tri_idx);
     423                        triangle_to_kill.Push((int)tri_idx);
    424424                    }
    425425
     
    434434                        if (csg_operation == CSGUsage::Xor)
    435435                        {
    436                             for (int l = 0; l < 3; l++)
     436                            for (ptrdiff_t l = 0; l < 3; l++)
    437437                            {
    438438                                AddDuplicateVertex(m_indices[tri_idx + l]);
    439                                 m_indices[tri_idx + l] = m_vert.Count() - 1;
     439                                m_indices[tri_idx + l] = (uint16_t)m_vert.Count() - 1;
    440440                            }
    441441                        }
     
    443443                        m_indices[tri_idx + 2]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    444444                        m_indices[tri_idx + 1]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    445                         ComputeNormals(tri_idx, 3);
     445                        ComputeNormals((int)tri_idx, 3);
    446446                    }
    447447                }
     
    477477            dir = 1;
    478478    }
    479     for (int i = triangle_to_kill.Count() - 1; i >= 0; i--)
     479    for (ptrdiff_t i = triangle_to_kill.Count() - 1; i >= 0; i--)
    480480        m_indices.Remove(triangle_to_kill[i], 3);
    481481
    482     m_cursors.Last().m1 = m_vert.Count();
    483     m_cursors.Last().m2 = m_indices.Count();
     482    m_cursors.Last().m1 = (int)m_vert.Count();
     483    m_cursors.Last().m2 = (int)m_indices.Count();
    484484
    485485    VerticesCleanup();
     
    583583
    584584//-----------------------------------------------------------------------------
    585 void EasyMesh::AddVertex(vec3 const &coord)
     585void EasyMesh::InternalAddVertex(vec3 const &coord)
    586586{
    587587    m_vert.Push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->ColorA()));
     
    628628
    629629//-----------------------------------------------------------------------------
    630 void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
     630void EasyMesh::InternalAddQuad(int i1, int i2, int i3, int i4, int base)
    631631{
    632632    if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) &&
    633633        !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting))
    634634    {
    635         int i5 = m_vert.Count();
     635        int i5 = (int)m_vert.Count();
    636636        AddLerpVertex(GetLerpVertex(base + i1, base + i3, .5f),
    637637                      GetLerpVertex(base + i2, base + i4, .5f), .5f);
     
    665665
    666666//-----------------------------------------------------------------------------
    667 void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
    668 {
    669     int vbase = m_vert.Count();
     667void EasyMesh::InternalAddQuadDupVerts(int i1, int i2, int i3, int i4, int base)
     668{
     669    int vbase = (int)m_vert.Count();
    670670    AddDuplicateVertex(base + i1);
    671671    AddDuplicateVertex(base + i2);
     
    673673    AddDuplicateVertex(base + i4);
    674674
    675     AppendQuad(0, 1, 2, 3, vbase);
    676 }
    677 
    678 //-----------------------------------------------------------------------------
    679 void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
     675    InternalAddQuad(0, 1, 2, 3, vbase);
     676}
     677
     678//-----------------------------------------------------------------------------
     679void EasyMesh::InternalAddTriangle(int i1, int i2, int i3, int base)
    680680{
    681681    m_indices << base + i1;
     
    685685
    686686//-----------------------------------------------------------------------------
    687 void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
    688 {
    689     m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
    690     m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
    691     m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
     687void EasyMesh::InternalAddTriangleDupVerts(int i1, int i2, int i3, int base)
     688{
     689    m_indices << (uint16_t)m_vert.Count(); AddDuplicateVertex(base + i1);
     690    m_indices << (uint16_t)m_vert.Count(); AddDuplicateVertex(base + i2);
     691    m_indices << (uint16_t)m_vert.Count(); AddDuplicateVertex(base + i3);
    692692}
    693693
     
    790790    VertexDictionnary vert_dict;
    791791    for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    792         vert_dict.AddVertex(i, m_vert[i].m_coord);
     792        vert_dict.RegisterVertex(i, m_vert[i].m_coord);
    793793
    794794    //2: Update the indices
     
    823823    //2: Update the vertices
    824824    int vbase = m_cursors.Last().m1;
    825     int vcount = m_vert.Count();
     825    int vcount = (int)m_vert.Count();
    826826    new_ids.Resize(vcount);
    827827    for (int i = vbase; i < vcount; i++)
     
    830830        {
    831831            //Add duplicate
    832             new_ids[i] << m_vert.Count();
     832            new_ids[i] << (int)m_vert.Count();
    833833            AddDuplicateVertex(i);
    834834            vert_ids[i]--;
     
    861861    for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++)
    862862    {
    863         vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
     863        vert_dict.RegisterVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
    864864        tri_list << m_indices[i];
    865865    }
     
    10721072}
    10731073
    1074 //-----------------------------------------------------------------------------
    1075 void EasyMesh::Translate(vec3 const &v)
    1076 {
    1077     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1078     {
    1079         BD()->CmdStack().AddCmd(EasyMeshCmdType::Translate);
    1080         BD()->CmdStack() << v;
    1081         return;
    1082     }
    1083 
    1084     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1085         m_vert[i].m_coord += v;
    1086 }
    1087 
    1088 //-----------------------------------------------------------------------------
    1089 void EasyMesh::RotateX(float angle) { Rotate(angle, vec3(1, 0, 0)); }
    1090 void EasyMesh::RotateY(float angle) { Rotate(angle, vec3(0, 1, 0)); }
    1091 void EasyMesh::RotateZ(float angle) { Rotate(angle, vec3(0, 0, 1)); }
    1092 
    1093 //-----------------------------------------------------------------------------
    1094 void EasyMesh::Rotate(float angle, vec3 const &axis)
    1095 {
    1096     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1097     {
    1098         BD()->CmdStack().AddCmd(EasyMeshCmdType::Rotate);
    1099         BD()->CmdStack() << angle << axis;
    1100         return;
    1101     }
    1102 
    1103     mat3 m = mat3::rotate(angle, axis);
    1104     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1105     {
    1106         m_vert[i].m_coord  = m * m_vert[i].m_coord;
    1107         m_vert[i].m_normal = m * m_vert[i].m_normal;
    1108     }
    1109 }
    1110 
    1111 //-----------------------------------------------------------------------------
    1112 void EasyMesh::RadialJitter(float r)
    1113 {
    1114     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1115     {
    1116         BD()->CmdStack().AddCmd(EasyMeshCmdType::RadialJitter);
    1117         BD()->CmdStack() << r;
    1118         return;
    1119     }
    1120 
    1121     array<int> Welded;
    1122     Welded.Push(-1);
    1123     for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++)
    1124     {
    1125         int j, k;
    1126         for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++)
    1127         {
    1128             if(Welded[k] < 0)
    1129             {
    1130                 vec3 diff = m_vert[i].m_coord - m_vert[j].m_coord;
    1131 
    1132                 if(diff.x > 0.1f || diff.x < -0.1f)
    1133                     continue;
    1134 
    1135                 if(diff.y > 0.1f || diff.y < -0.1f)
    1136                     continue;
    1137 
    1138                 if(diff.z > 0.1f || diff.z < -0.1f)
    1139                     continue;
    1140 
    1141                 break;
    1142             }
    1143         }
    1144 
    1145         if(j == i)
    1146             Welded.Push(-1);
    1147         else
    1148             Welded.Push(j);
    1149     }
    1150 
    1151     int i, j;
    1152     for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++)
    1153     {
    1154         if(Welded[j] == -1)
    1155             m_vert[i].m_coord *= 1.0f + rand(r);
    1156         else
    1157             m_vert[i].m_coord = m_vert[Welded[j]].m_coord;
    1158     }
    1159 
    1160     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    1161 }
    1162 
    1163 //-----------------------------------------------------------------------------
    1164 void EasyMesh::TaperX(float ny, float nz, float xoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::X, Axis::X, ny, nz, xoff, absolute); }
    1165 void EasyMesh::TaperY(float nx, float nz, float yoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
    1166 void EasyMesh::TaperZ(float nx, float ny, float zoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
    1167 
    1168 //-----------------------------------------------------------------------------
    1169 void EasyMesh::TwistX(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::X, Axis::X, t, t, toff); }
    1170 void EasyMesh::TwistY(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Y, Axis::Y, t, t, toff); }
    1171 void EasyMesh::TwistZ(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Z, Axis::Z, t, t, toff); }
    1172 
    1173 //-----------------------------------------------------------------------------
    1174 void EasyMesh::ShearX(float ny, float nz, float xoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::X, Axis::X, ny, nz, xoff, absolute); }
    1175 void EasyMesh::ShearY(float nx, float nz, float yoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
    1176 void EasyMesh::ShearZ(float nx, float ny, float zoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
    1177 
    1178 //-----------------------------------------------------------------------------
    1179 void EasyMesh::StretchX(float ny, float nz, float xoff) { DoMeshTransform(MeshTransform::Stretch, Axis::X, Axis::X, ny, nz, xoff); }
    1180 void EasyMesh::StretchY(float nx, float nz, float yoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Y, Axis::Y, nz, nx, yoff); }
    1181 void EasyMesh::StretchZ(float nx, float ny, float zoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Z, Axis::Z, nx, ny, zoff); }
    1182 
    1183 //-----------------------------------------------------------------------------
    1184 void EasyMesh::BendXY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Y, t, t, toff); }
    1185 void EasyMesh::BendXZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Z, t, t, toff); }
    1186 void EasyMesh::BendYX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::X, t, t, toff); }
    1187 void EasyMesh::BendYZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::Z, t, t, toff); }
    1188 void EasyMesh::BendZX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::X, t, t, toff); }
    1189 void EasyMesh::BendZY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::Y, t, t, toff); }
    1190 
    1191 //-----------------------------------------------------------------------------
    1192 void EasyMesh::DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, bool absolute)
    1193 {
    1194     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1195     {
    1196         BD()->CmdStack().AddCmd(EasyMeshCmdType::MeshTranform);
    1197         BD()->CmdStack() << ct << axis0 << axis1 << n0 << n1 << noff << absolute;
    1198         return;
    1199     }
    1200 
    1201     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1202     {
    1203         switch (ct.ToScalar())
    1204         {
    1205             case MeshTransform::Taper:
    1206             {
    1207                 float value = m_vert[i].m_coord[axis0.ToScalar()];
    1208                 if (absolute) value = abs(value);
    1209                 m_vert[i].m_coord[(axis0.ToScalar() + 1) % 3] *= max(0.f, 1.f + (n0 * value + noff));
    1210                 m_vert[i].m_coord[(axis0.ToScalar() + 2) % 3] *= max(0.f, 1.f + (n1 * value + noff));
    1211                 break;
    1212             }
    1213             case MeshTransform::Twist:
    1214             {
    1215                 vec3 rotaxis = vec3(1.f); rotaxis[(axis0.ToScalar() + 1) % 3] = .0f; rotaxis[(axis0.ToScalar() + 2) % 3] = .0f;
    1216                 m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0.ToScalar()] * n0 + noff, rotaxis) * m_vert[i].m_coord;
    1217                 break;
    1218             }
    1219             case MeshTransform::Shear:
    1220             {
    1221                 float value = m_vert[i].m_coord[axis0.ToScalar()];
    1222                 if (absolute) value = abs(value);
    1223                 m_vert[i].m_coord[(axis0.ToScalar() + 1) % 3] += (n0 * value + noff);
    1224                 m_vert[i].m_coord[(axis0.ToScalar() + 2) % 3] += (n1 * value + noff);
    1225                 break;
    1226             }
    1227             case MeshTransform::Stretch:
    1228             {
    1229                 //float value = abs(m_vert[i].m1[axis0.ToScalar()]);
    1230                 //m_vert[i].m1[(axis0.ToScalar() + 1) % 3] += (lol::pow(value, n0) + noff);
    1231                 //m_vert[i].m1[(axis0.ToScalar() + 2) % 3] += (lol::pow(value, n1) + noff);
    1232                 break;
    1233             }
    1234             case MeshTransform::Bend:
    1235             {
    1236                 vec3 rotaxis = vec3(1.f); rotaxis[(axis1.ToScalar() + 1) % 3] = .0f; rotaxis[(axis1.ToScalar() + 2) % 3] = .0f;
    1237                 m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0.ToScalar()] * n0 + noff, rotaxis) * m_vert[i].m_coord;
    1238                 break;
    1239             }
    1240         }
    1241     }
    1242     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    1243 }
    1244 
    1245 //-----------------------------------------------------------------------------
    1246 void EasyMesh::Scale(vec3 const &s)
    1247 {
    1248     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1249     {
    1250         BD()->CmdStack().AddCmd(EasyMeshCmdType::Scale);
    1251         BD()->CmdStack() << s;
    1252         return;
    1253     }
    1254 
    1255     vec3 const invs = vec3(1) / s;
    1256 
    1257     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1258     {
    1259         m_vert[i].m_coord *= s;
    1260         m_vert[i].m_normal = normalize(m_vert[i].m_normal * invs);
    1261     }
    1262 
    1263     /* Flip winding if the scaling involves mirroring */
    1264     if (!BD()->IsEnabled(MeshBuildOperation::ScaleWinding) && s.x * s.y * s.z < 0)
    1265     {
    1266         for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3)
    1267         {
    1268             uint16_t tmp = m_indices[i + 0];
    1269             m_indices[i + 0] = m_indices[i + 1];
    1270             m_indices[i + 1] = tmp;
    1271         }
    1272     }
    1273 }
    1274 
    1275 //-----------------------------------------------------------------------------
    1276 void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
    1277 void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
    1278 void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
    1279 
    1280 //-----------------------------------------------------------------------------
    1281 void EasyMesh::DupAndScale(vec3 const &s, bool open_brace)
    1282 {
    1283     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1284     {
    1285         BD()->CmdStack().AddCmd(EasyMeshCmdType::DupAndScale);
    1286         BD()->CmdStack() << s << open_brace;
    1287         return;
    1288     }
    1289 
    1290     int vlen = m_vert.Count() - m_cursors.Last().m1;
    1291     int tlen = m_indices.Count() - m_cursors.Last().m2;
    1292 
    1293     for (int i = 0; i < vlen; i++)
    1294         AddDuplicateVertex(m_cursors.Last().m1++);
    1295 
    1296     for (int i = 0; i < tlen; i++)
    1297         m_indices << m_indices[m_cursors.Last().m2++] + vlen;
    1298 
    1299     Scale(s);
    1300 
    1301     m_cursors.Last().m1 -= vlen;
    1302     m_cursors.Last().m2 -= tlen;
    1303 
    1304     if (open_brace)
    1305     {
    1306         OpenBrace();
    1307 
    1308         m_cursors.Last().m1 -= vlen;
    1309         m_cursors.Last().m2 -= tlen;
    1310     }
    1311 }
    1312 
    1313 //-----------------------------------------------------------------------------
    1314 void EasyMesh::AppendCylinder(int nsides, float h, float d1, float d2,
    1315                               bool dualside, bool smooth, bool close)
    1316 {
    1317     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1318     {
    1319         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCylinder);
    1320         BD()->CmdStack() << nsides << h << d1 << d2 << dualside << smooth << close;
    1321         return;
    1322     }
    1323 
    1324     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1325     float r1 = d1 * .5f;
    1326     float r2 = d2 * .5f;
    1327 
    1328     //SAVE
    1329     vec4 Saved_ColorA = BD()->ColorA();
    1330     vec4 Saved_ColorB = BD()->ColorB();
    1331     vec2 Save_texcoord_offset = BD()->TexCoordOffset();
    1332     vec2 Save_texcoord_scale = BD()->TexCoordScale();
    1333 
    1334     int vbase = m_vert.Count();
    1335 
    1336     mat3 rotmat = mat3::rotate(360.0f / (float)nsides, 0.f, 1.f, 0.f);
    1337     vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
    1338     vec2 uv1(.0f, .0f), uv2(.0f, 1.0f), uvadd(1.0f / (float)nsides, .0f);
    1339     if (close)
    1340         SetTexCoordData(vec2(.0f), vec2(1.0f, .5f));
    1341 
    1342     /* Construct normal */
    1343     if (r2 != .0f)
    1344         n = vec3(r2, h * .5f, 0.f);
    1345     else
    1346         n = vec3(r1, h * .5f, 0.f);
    1347     n.y = r1 * (r1 - r2) / h;
    1348     if (!smooth)
    1349         n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
    1350     n = normalize(n);
    1351 
    1352     //Two passes necessary to ensure "weighted quad" compatibility
    1353     //First pass : Add vertices
    1354     for (int i = 0; i < nsides; i++)
    1355     {
    1356         /* FIXME: normals should be flipped in two-sided mode, but that
    1357          * means duplicating the vertices again... */
    1358         AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1359         AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    1360 
    1361         p1 = rotmat * p1; uv1 += uvadd;
    1362         p2 = rotmat * p2; uv2 += uvadd;
    1363 
    1364         if (!smooth)
    1365         {
    1366             AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1367             AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    1368         }
    1369 
    1370         n = rotmat * n;
    1371     }
    1372     //Second pass : Build quad
    1373     for (int i = 0; i < nsides; i++)
    1374     {
    1375         if (smooth)
    1376         {
    1377             int j = (i + 1) % nsides;
    1378             AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
    1379             if (dualside)
    1380                 AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
    1381         }
    1382         else
    1383         {
    1384             AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
    1385             if (dualside)
    1386                 AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
    1387         }
    1388 
    1389     }
    1390 
    1391     if (close)
    1392     {
    1393         //START
    1394         OpenBrace();
    1395         //LOWER DISC
    1396         SetTexCoordData(vec2(.0f, .5f), vec2(.5f, .5f));
    1397         SetCurColorA(BD()->ColorA());
    1398         AppendDisc(nsides, d1);
    1399         Translate(vec3(.0f, h, .0f));
    1400         RotateX(180.0f);
    1401         //UPPER DISC
    1402         SetTexCoordData(vec2(.5f, .5f), vec2(.5f, .5f));
    1403         SetCurColorA(BD()->ColorB());
    1404         AppendDisc(nsides, d2);
    1405         Translate(vec3(.0f, h * .5f, .0f));
    1406         CloseBrace();
    1407     }
    1408     //RESTORE
    1409     SetCurColorA(Saved_ColorA);
    1410     SetCurColorB(Saved_ColorB);
    1411     SetTexCoordData(Save_texcoord_offset, Save_texcoord_scale);
    1412 }
    1413 
    1414 //-----------------------------------------------------------------------------
    1415 void EasyMesh::AppendSphere(int ndivisions, float d)
    1416 {
    1417     AppendCapsule(ndivisions, 0.f, d);
    1418 }
    1419 
    1420 //-----------------------------------------------------------------------------
    1421 void EasyMesh::AppendCapsule(int ndivisions, float h, float d)
    1422 {
    1423     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1424     {
    1425         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCapsule);
    1426         BD()->CmdStack() << ndivisions << h << d;
    1427         return;
    1428     }
    1429 
    1430     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1431     float r = d * .5f;
    1432 
    1433     int ibase = m_indices.Count();
    1434 
    1435     array<vec3> vertices;
    1436     float uv_h = 0;
    1437     float uv_r = 0;
    1438 
    1439     /* FIXME: we don't know how to handle even-divided capsules, so we
    1440      * force the count to be odd. */
    1441     if (h)
    1442     {
    1443         ndivisions |= 1;
    1444         //calculate uv h&r percents
    1445         uv_h = (float)h / (float)(h + r * 2);
    1446         uv_r = (float)r / (float)(h + r * 2);
    1447     }
    1448 
    1449     /* Fill in the icosahedron vertices, rotating them so that there
    1450      * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */
    1451     float phi = 0.5f + 0.5f * sqrt(5.f);
    1452     mat3 m = mat3::rotate(degrees(asin(1.f / sqrt(2.f + phi))),
    1453                           vec3(0.f, 0.f, 1.f));
    1454     for (int i = 0; i < 4; i++)
    1455     {
    1456         float x = (i & 1) ? 0.5f : -0.5f;
    1457         float y = (i & 2) ? phi * 0.5f : phi * -0.5f;
    1458         vertices << m * vec3(x, y, 0.f);
    1459         vertices << m * vec3(0.f, x, y);
    1460         vertices << m * vec3(y, 0.f, x);
    1461     }
    1462 
    1463     static int const trilist[] =
    1464     {
    1465         0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8,
    1466         7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11,
    1467 
    1468         0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1,
    1469         2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6,
    1470         7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8
    1471     };
    1472 
    1473     for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3)
    1474     {
    1475         vec3 const &a = vertices[trilist[i]];
    1476         vec3 const &b = vertices[trilist[i + 1]];
    1477         vec3 const &c = vertices[trilist[i + 2]];
    1478 
    1479         vec3 const vb = 1.f / ndivisions * (b - a);
    1480         vec3 const vc = 1.f / ndivisions * (c - a);
    1481 
    1482         int line = ndivisions + 1;
    1483 
    1484         for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++)
    1485         {
    1486             vec3 p[] = { a + (float)x * vb + (float)y * vc,
    1487                          p[0] + vb,
    1488                          p[0] + vc,
    1489                          p[0] + vb + vc };
    1490             vec2 uv[4];
    1491 
    1492             /* FIXME: when we normalise here, we get a volume that is slightly
    1493              * smaller than the sphere of radius 1, since we are not using
    1494              * the midradius. */
    1495             for (int k = 0; k < 4; k++)
    1496             {
    1497                 //keep normalized until the end of the UV calculations
    1498                 p[k] = normalize(p[k]);
    1499 
    1500                 uv[k].x = (lol::atan2(p[k].z, p[k].x) + F_PI) / (F_PI * 2.f);
    1501                 if (abs(p[k].y) >= 1.0f)
    1502                     uv[k].x = -1.f;
    1503                 uv[k].y = lol::atan2(p[k].y, dot(p[k], normalize(p[k] * vec3(1.f,0.f,1.f)))) / F_PI + 0.5f;
    1504                 if (h)
    1505                 {
    1506                     if (uv[k].y > .5f)
    1507                         uv[k].y = uv_r + uv_h + (uv[k].y - .5f) * uv_r * 2.f;
    1508                     else
    1509                         uv[k].y *= uv_r * 2.f;
    1510                 }
    1511                 p[k] *= r;
    1512             }
    1513 
    1514             /* If this is a capsule, grow in the Y direction */
    1515             if (h > 0.f)
    1516             {
    1517                 for (int k = 0; k < 4; k++)
    1518                     p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h;
    1519             }
    1520 
    1521             /* Add zero, one or two triangles */
    1522             int id[] = { 0, 1, 2,
    1523                          1, 3 ,2 };
    1524             int l = 6;
    1525             while ((l -= 3) >= 0)
    1526             {
    1527                 if ((l == 0 && y < line - 1) || (l == 3 && y < line - 2))
    1528                 {
    1529                     int k = -1;
    1530                     while (++k < 3)
    1531                     {
    1532                         int rid[] = { id[k + l], id[(k + 1) % 3 + l] };
    1533                         if (uv[rid[0]].x >= .0f &&
    1534                             uv[rid[1]].x >= .0f &&
    1535                             abs(uv[rid[0]].x - uv[rid[1]].x) > .5f)
    1536                         {
    1537                             if (uv[rid[0]].x < uv[rid[1]].x)
    1538                                 uv[rid[0]].x += 1.0f;
    1539                             else
    1540                                 uv[rid[1]].x += 1.0f;
    1541                         }
    1542                     }
    1543                     k = -1;
    1544                     while (++k < 3)
    1545                     {
    1546                         int rid[] = { id[k + l], id[(k + 1) % 3 + l], id[(k + 2) % 3 + l] };
    1547                         AddVertex(p[rid[0]]);
    1548                         vec2 new_uv;
    1549                         if (uv[rid[0]].x < .0f)
    1550                             new_uv = vec2((uv[rid[1]].x + uv[rid[2]].x) * .5f, uv[rid[0]].y);
    1551                         else
    1552                             new_uv = uv[rid[0]];
    1553                         SetCurVertTexCoord(vec2(0.f, 1.f) - new_uv);
    1554                         SetCurVertTexCoord2(vec2(0.f, 1.f) - new_uv);
    1555                     }
    1556                     AppendTriangle(0, 2, 1, m_vert.Count() - 3);
    1557                 }
    1558             }
    1559 
    1560             y++;
    1561             if (y == line)
    1562             {
    1563                 x++;
    1564                 y = 0;
    1565                 line--;
    1566             }
    1567         }
    1568     }
    1569 
    1570     ComputeNormals(ibase, m_indices.Count() - ibase);
    1571 }
    1572 
    1573 //-----------------------------------------------------------------------------
    1574 void EasyMesh::AppendTorus(int ndivisions, float d1, float d2)
    1575 {
    1576     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1577     {
    1578         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendTorus);
    1579         BD()->CmdStack() << ndivisions << d1 << d2;
    1580         return;
    1581     }
    1582 
    1583     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1584     float r1 = d1 * .5f;
    1585     float r2 = d2 * .5f;
    1586 
    1587     int ibase = m_indices.Count();
    1588     int nidiv = ndivisions; /* Cross-section */
    1589     int njdiv = ndivisions; /* Full circumference */
    1590 
    1591     for (int j = 0; j < njdiv; j++)
    1592     for (int i = 0; i < 2 * nidiv; i++)
    1593     {
    1594         for (int di = 0; di < 2; di++)
    1595         for (int dj = 0; dj < 2; dj++)
    1596         {
    1597             int i2 = (i + di) % nidiv;
    1598             int j2 = (j + dj) % njdiv;
    1599 
    1600             //Location on the donut
    1601             float x = 0.5f * (r2 - r1) * (float)lol::cos(2.f * F_PI * i2 / nidiv) + 0.5f * (r1 + r2);
    1602             float y = 0.5f * (r2 - r1) * (float)lol::sin(2.f * F_PI * i2 / nidiv);
    1603             float z = 0.0f;
    1604 
    1605             //Center circle
    1606             float ca = (float)lol::cos(2.f * F_PI * j2 / njdiv);
    1607             float sa = (float)lol::sin(2.f * F_PI * j2 / njdiv);
    1608 
    1609             //Actual location
    1610             float x2 = x * ca - z * sa;
    1611             float z2 = z * ca + x * sa;
    1612 
    1613             AddVertex(vec3(x2, y, z2));
    1614             SetCurVertTexCoord(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1615             SetCurVertTexCoord2(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1616         }
    1617 
    1618         AppendTriangle(0, 2, 3, m_vert.Count() - 4);
    1619         AppendTriangle(0, 3, 1, m_vert.Count() - 4);
    1620     }
    1621 
    1622     ComputeNormals(ibase, m_indices.Count() - ibase);
    1623 }
    1624 
    1625 //-----------------------------------------------------------------------------
    1626 void EasyMesh::AppendBox(vec3 const &size, float chamf)
    1627 {
    1628     AppendBox(size, chamf, false);
    1629 }
    1630 
    1631 //-----------------------------------------------------------------------------
    1632 void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
    1633 {
    1634     AppendBox(size, chamf, true);
    1635 }
    1636 
    1637 //-----------------------------------------------------------------------------
    1638 void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
    1639 {
    1640     AppendBox(size, chamf, false);
    1641 }
    1642 
    1643 //-----------------------------------------------------------------------------
    1644 void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
    1645 {
    1646     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1647     {
    1648         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendBox);
    1649         BD()->CmdStack() << size << chamf << smooth;
    1650         return;
    1651     }
    1652 
    1653     if (chamf < 0.0f)
    1654     {
    1655         AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
    1656         return;
    1657     }
    1658 
    1659     int vbase = m_vert.Count();
    1660     int ibase = m_indices.Count();
    1661 
    1662     vec3 d = size * 0.5f;
    1663 
    1664     MeshType mt = MeshType::Box;
    1665     TexCoordPos bl = TexCoordPos::BL;
    1666     TexCoordPos br = TexCoordPos::BR;
    1667     TexCoordPos tl = TexCoordPos::TL;
    1668     TexCoordPos tr = TexCoordPos::TR;
    1669 
    1670     //--
    1671     //Side vertices
    1672     //--
    1673     MeshFaceType mft = MeshFaceType::BoxFront;
    1674     AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
    1675     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1676     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1677     //--
    1678     AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
    1679     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1680     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1681     //--
    1682     AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
    1683     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1684     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1685     //--
    1686     AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
    1687     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1688     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1689 
    1690     //--
    1691     mft = MeshFaceType::BoxLeft;
    1692     AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
    1693     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1694     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1695     //--
    1696     AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
    1697     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1698     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1699     //--
    1700     AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
    1701     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1702     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1703     //--
    1704     AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
    1705     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1706     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1707 
    1708     //--
    1709     mft = MeshFaceType::BoxBack;
    1710     AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
    1711     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1712     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1713     //--
    1714     AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
    1715     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1716     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1717     //--
    1718     AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
    1719     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1720     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1721     //--
    1722     AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
    1723     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1724     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1725 
    1726     //--
    1727     mft = MeshFaceType::BoxRight;
    1728     AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
    1729     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1730     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1731     //--
    1732     AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
    1733     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1734     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1735     //--
    1736     AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
    1737     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1738     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1739     //--
    1740     AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
    1741     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1742     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1743 
    1744     //--
    1745     //Bottom vertices
    1746     //--
    1747     mft = MeshFaceType::BoxBottom;
    1748     AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
    1749     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1750     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1751     //--
    1752     AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
    1753     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1754     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1755     //--
    1756     AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
    1757     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1758     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1759     //--
    1760     AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
    1761     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1762     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1763 
    1764     //--
    1765     //Top vertices
    1766     //--
    1767     mft = MeshFaceType::BoxTop;
    1768     AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
    1769     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1770     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1771     //--
    1772     AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
    1773     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1774     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1775     //--
    1776     AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
    1777     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1778     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1779     //--
    1780     AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
    1781     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1782     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1783 
    1784     ComputeNormals(ibase, m_indices.Count() - ibase);
    1785     ibase = m_indices.Count();
    1786 
    1787     //Build the box at the end : The 6 quads on each side of the box.
    1788     for (int i = 0; i < 24; i += 4)
    1789         AppendQuad(i, i + 1, i + 2, i + 3, vbase);
    1790 
    1791     /* The 8 quads at each edge of the box */
    1792     if (chamf)
    1793     {
    1794         static int const quadlist[48] =
    1795         {
    1796             0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
    1797             2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
    1798             1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
    1799         };
    1800 
    1801         for (int i = 0; i < 48; i += 4)
    1802         {
    1803             if (smooth)
    1804                 AppendQuad(quadlist[i],     quadlist[i + 1],
    1805                            quadlist[i + 2], quadlist[i + 3], vbase);
    1806             else
    1807                 AppendQuadDuplicateVerts(quadlist[i],     quadlist[i + 1],
    1808                                          quadlist[i + 2], quadlist[i + 3], vbase);
    1809         }
    1810     }
    1811 
    1812     /* The 8 triangles at each corner of the box */
    1813     if (chamf)
    1814     {
    1815         static int const trilist[24] =
    1816         {
    1817             3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
    1818             2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
    1819         };
    1820 
    1821         for (int i = 0; i < 24; i += 3)
    1822         {
    1823             if (smooth)
    1824                 AppendTriangle(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1825             else
    1826                 AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1827         }
    1828     }
    1829 
    1830     if (!smooth)
    1831         ComputeNormals(ibase, m_indices.Count() - ibase);
    1832 }
    1833 
    1834 //-----------------------------------------------------------------------------
    1835 void EasyMesh::AppendStar(int nbranches, float d1, float d2,
    1836                           bool fade, bool fade2)
    1837 {
    1838     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1839     {
    1840         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendStar);
    1841         BD()->CmdStack() << nbranches << d1 << d2 << fade << fade2;
    1842         return;
    1843     }
    1844 
    1845     //Should ignore quad weight, as it does not destroy star symmetry
    1846     BD()->Enable(MeshBuildOperation::IgnoreQuadWeighting);
    1847 
    1848     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1849     float r1 = d1 * .5f;
    1850     float r2 = d2 * .5f;
    1851 
    1852     //TODO: It would probably be good to think of another way of UV painting this, like "branch repeating"
    1853     int vbase = m_vert.Count();
    1854     float maxr = max(r1, r2);
    1855 
    1856     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1857 
    1858     mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
    1859     vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
    1860     vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
    1861          uv2(0.f, 0.f, -.5f * ((float)r2 / maxr));
    1862 
    1863     p2 = rotmat * p2; uv2 = rotmat * uv2;
    1864     rotmat = rotmat * rotmat;
    1865 
    1866     for (int i = 0; i < nbranches; i++)
    1867     {
    1868         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1869         if (fade2)
    1870             SetCurVertColor(BD()->ColorB());
    1871 
    1872         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1873         if (fade)
    1874             SetCurVertColor(BD()->ColorB());
    1875 
    1876         //Append quad at the end
    1877         AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches), vbase);
    1878 
    1879         p1 = rotmat * p1; uv1 = rotmat * uv1;
    1880         p2 = rotmat * p2; uv2 = rotmat * uv2;
    1881     }
    1882 
    1883     //Restore
    1884     BD()->Disable(MeshBuildOperation::IgnoreQuadWeighting);
    1885 }
    1886 
    1887 //-----------------------------------------------------------------------------
    1888 void EasyMesh::AppendExpandedStar(int nbranches, float d1, float d2, float extrad)
    1889 {
    1890     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1891     {
    1892         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendExpandedStar);
    1893         BD()->CmdStack() << nbranches << d1 << d2 << extrad;
    1894         return;
    1895     }
    1896 
    1897     //Should ignore quad weight, as it does not destroy star symmetry
    1898     BD()->Enable(MeshBuildOperation::IgnoreQuadWeighting);
    1899 
    1900     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1901     float r1 = d1 * .5f;
    1902     float r2 = d2 * .5f;
    1903     float extrar = extrad * .5f;
    1904 
    1905     int vbase = m_vert.Count();
    1906     float maxr = (float)max(max(r1, r2), max(r1 + extrar, r2 + extrar));
    1907 
    1908     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1909 
    1910     mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
    1911     vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
    1912          p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
    1913     vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
    1914          uv2(0.f, 0.f, -.5f * ((float)r2 / maxr)),
    1915          uv3(0.f, 0.f, -.5f * ((float)(r1 + extrar) / maxr)),
    1916          uv4(0.f, 0.f, -.5f * ((float)(r2 + extrar) / maxr));
    1917 
    1918     p2 = rotmat * p2; uv2 = rotmat * uv2;
    1919     p4 = rotmat * p4; uv4 = rotmat * uv4;
    1920     rotmat = rotmat * rotmat;
    1921 
    1922     for (int i = 0; i < nbranches; i++)
    1923     {
    1924         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1925         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1926         AddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1927         AddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1928 
    1929         int j = (i + 1) % nbranches;
    1930         //
    1931         AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
    1932         AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
    1933         AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
    1934 
    1935         p1 = rotmat * p1; uv1 = rotmat * uv1;
    1936         p2 = rotmat * p2; uv2 = rotmat * uv2;
    1937         p3 = rotmat * p3; uv3 = rotmat * uv3;
    1938         p4 = rotmat * p4; uv4 = rotmat * uv4;
    1939     }
    1940 
    1941     //Restore
    1942     BD()->Disable(MeshBuildOperation::IgnoreQuadWeighting);
    1943 }
    1944 
    1945 //-----------------------------------------------------------------------------
    1946 void EasyMesh::AppendDisc(int nsides, float d, bool fade)
    1947 {
    1948     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1949     {
    1950         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendDisc);
    1951         BD()->CmdStack() << nsides << d << fade;
    1952         return;
    1953     }
    1954 
    1955     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1956     float r = d * .5f;
    1957 
    1958     int vbase = m_vert.Count();
    1959 
    1960     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1961 
    1962     mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
    1963     vec3 p1(r, 0.f, 0.f);
    1964     vec3 uv(.5f, .0f, .0f);
    1965 
    1966     for (int i = 0; i < nsides; i++)
    1967     {
    1968         AddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f));
    1969         if (fade)
    1970             SetCurVertColor(BD()->ColorB());
    1971         AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
    1972         p1 = rotmat * p1;
    1973         uv = rotmat * uv;
    1974     }
    1975 }
    1976 
    1977 //-----------------------------------------------------------------------------
    1978 void EasyMesh::AppendSimpleTriangle(float d, bool fade)
    1979 {
    1980     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1981     {
    1982         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendSimpleTriangle);
    1983         BD()->CmdStack() << d << fade;
    1984         return;
    1985     }
    1986 
    1987     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1988     float size = d * .5f;
    1989 
    1990     mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
    1991     vec3 p(0.f, 0.f, size);
    1992 
    1993     AddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f));
    1994     p = m * p;
    1995     AddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f));
    1996     if (fade)
    1997         SetCurVertColor(BD()->ColorB());
    1998     p = m * p;
    1999     AddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f));
    2000     if (fade)
    2001         SetCurVertColor(BD()->ColorB());
    2002 
    2003     AppendTriangle(0, 1, 2, m_vert.Count() - 3);
    2004 }
    2005 
    2006 //-----------------------------------------------------------------------------
    2007 void EasyMesh::AppendSimpleQuad(float size, bool fade)
    2008 {
    2009     AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
    2010 }
    2011 
    2012 //-----------------------------------------------------------------------------
    2013 void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, bool fade)
    2014 {
    2015     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2016     {
    2017         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendSimpleQuad);
    2018         BD()->CmdStack() << p1 << p2 << z << fade;
    2019         return;
    2020     }
    2021 
    2022     MeshType mt = MeshType::Quad;
    2023     MeshFaceType mft = MeshFaceType::QuadDefault;
    2024 
    2025     //--
    2026     AddVertex(vec3(p2.x, z, -p1.y));
    2027     TexCoordPos br = TexCoordPos::BR;
    2028     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    2029     SetCurVertTexCoord2(BD()->TexCoord2(mt, br, mft));
    2030     //--
    2031     AddVertex(vec3(p2.x, z, -p2.y));
    2032     TexCoordPos bl = TexCoordPos::BL;
    2033     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    2034     SetCurVertTexCoord2(BD()->TexCoord2(mt, bl, mft));
    2035     //--
    2036     AddVertex(vec3(p1.x, z, -p2.y));
    2037     TexCoordPos tl = TexCoordPos::TL;
    2038     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    2039     SetCurVertTexCoord2(BD()->TexCoord2(mt, tl, mft));
    2040     if (fade) SetCurVertColor(BD()->ColorB());
    2041     //--
    2042     AddVertex(vec3(p1.x, z, -p1.y));
    2043     TexCoordPos tr = TexCoordPos::TR;
    2044     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    2045     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    2046     if (fade) SetCurVertColor(BD()->ColorB());
    2047 
    2048     AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
    2049     ComputeNormals(m_indices.Count() - 6, 6);
    2050 }
    2051 
    2052 //-----------------------------------------------------------------------------
    2053 void EasyMesh::AppendCog(int nbsides, float h, float d10, float d20,
    2054                          float d11, float d21, float d12, float d22,
    2055                          float sidemul, bool offset)
    2056 {
    2057     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2058     {
    2059         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCog);
    2060         BD()->CmdStack() << nbsides << h
    2061                          << d10 << d20
    2062                          << d11 << d21
    2063                          << d12 << d22
    2064                          << sidemul << offset;
    2065         return;
    2066     }
    2067 
    2068     //XXX : This operation is done to convert radius to diameter without changing all the code.
    2069     float r10 = d10 * .5f;
    2070     float r20 = d20 * .5f;
    2071     float r11 = d11 * .5f;
    2072     float r21 = d21 * .5f;
    2073     float r12 = d12 * .5f;
    2074     float r22 = d22 * .5f;
    2075 
    2076     int ibase = m_indices.Count();
    2077     int vbase = m_vert.Count();
    2078 
    2079     /* FIXME: enforce this some other way */
    2080     if (r12 < 0)
    2081         h = -h;
    2082 
    2083     mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
    2084     mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
    2085     mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
    2086 
    2087     vec3 p[12];
    2088 
    2089     //Upper points
    2090     p[0] = vec3(r10, h * .5f, 0.f);
    2091     p[1] = rotmat * p[0];
    2092     p[2] = vec3(r11, h * .5f, 0.f);
    2093     p[3] = rotmat * p[2];
    2094     p[4] = smat1 * (rotmat * vec3(r11 + r12, h * .5f, 0.f));
    2095     p[5] = smat2 * (rotmat * p[4]);
    2096 
    2097     //Lower points
    2098     p[6] = vec3(r20, h * -.5f, 0.f);
    2099     p[7] = rotmat * p[6];
    2100     p[8] = vec3(r21, h * -.5f, 0.f);
    2101     p[9] = rotmat * p[8];
    2102     p[10] = smat1 * (rotmat * vec3(r21 + r22, h * -.5f, 0.f));
    2103     p[11] = smat2 * (rotmat * p[10]);
    2104 
    2105     if (offset)
    2106         for (int n = 0; n < 12; n++)
    2107             p[n] = rotmat * p[n];
    2108 
    2109     rotmat = rotmat * rotmat;
    2110 
    2111     //UV base computation
    2112     float maxr = max(max(r11 + r12, r21 + r22), max(r10, r20));
    2113     float InLn = length(p[1] - p[0]);
    2114     float CogLn[8] = { .0f, .0f, .0f, .0f, .0f, .0f, .0f, .0f };
    2115     for (int i = 0; i < 3; i++)
    2116     {
    2117         for (int j = 0, k = 2; j < 8 && k < 12; j += 4, k += 6)
    2118         {
    2119             CogLn[j + i] = length(p[k + i + 1] - p[k + i]);
    2120             CogLn[j + 3] += CogLn[j + i];
    2121             if (i == 1) //Add 3to4 twice since it's automatically completed by +1 loop.
    2122                 CogLn[j + 3] += CogLn[j + i];
    2123         }
    2124     }
    2125 
    2126     //Choose the biggest cog length
    2127     int CogSrc = (CogLn[7] > CogLn[3])?(4):(0);
    2128     CogLn[3] = CogLn[CogSrc + 3];
    2129     for (int i = 0; i < 3; i++)
    2130         CogLn[i] = CogLn[CogSrc + i] / CogLn[CogSrc + 3];
    2131 
    2132     //Calculate Cog Modifiers
    2133     vec2 InUV[2] = { vec2(.0f), vec2(.5f) };
    2134     vec2 CogUV[2] = { vec2(.0f), vec2(.5f) };
    2135     vec2 upadd = vec2(.25f, .75f);
    2136     vec2 lowadd = vec2(.75f, .75f);
    2137     {
    2138         if (h < InLn)
    2139         {
    2140             InUV[0].x  = 1.0f;
    2141             InUV[0].y  = h / InLn;
    2142             InUV[1].x  = .0f;
    2143             InUV[1].y -= InUV[0].y * .5f;
    2144         }
    2145         else
    2146         {
    2147             InUV[0].x  = InLn / h;
    2148             InUV[0].y  = 1.0f;
    2149             InUV[1].x -= InUV[0].x * .5f;
    2150             InUV[1].y = .0f;
    2151         }
    2152         if (h < CogLn[3])
    2153         {
    2154             CogUV[0].x  = 1.0f;
    2155             CogUV[0].y  = h / CogLn[3];
    2156             CogUV[1].x  = .0f;
    2157             CogUV[1].y -= CogUV[0].y * .5f;
    2158         }
    2159         else
    2160         {
    2161             CogUV[0].x  = CogLn[3] / h;
    2162             CogUV[0].y  = 1.0f;
    2163             CogUV[1].x -= CogUV[0].x * .5f;
    2164             CogUV[1].y  = .0f;
    2165         }
    2166         if (InUV[0].x + CogUV[0].x < .5f)
    2167         {
    2168             InUV[1].x = .0f;
    2169             CogUV[1].x = .5f - CogUV[0].x;
    2170             upadd  = vec2(.75f, .25f);
    2171             lowadd = vec2(.75f, .75f);
    2172         }
    2173         else if (InUV[0].y + CogUV[0].y < .5f)
    2174         {
    2175             InUV[1].y = .0f;
    2176             CogUV[1].y = .5f - CogUV[0].y;
    2177         }
    2178         else
    2179         {
    2180             InUV[0] *= .5f;
    2181             InUV[1] *= .5f;
    2182             CogUV[0] *= .5f;
    2183             CogUV[1] *= .5f;
    2184             InUV[1] += vec2(.5f, .0f);
    2185         }
    2186     }
    2187 
    2188     //Build UV tab
    2189     vec2 uv[12]; float CogSz;
    2190     //Upper points
    2191     CogSz = 1.0f - CogLn[1];
    2192     uv[0]  = vec2(0.f,   0.f) * InUV[0]  + InUV[1];
    2193     uv[1]  = vec2(1.f,   0.f) * InUV[0]  + InUV[1];
    2194     uv[5]  = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2];
    2195     uv[4]  = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1];
    2196     uv[3]  = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0];
    2197     uv[2]  = vec2(0.f,   0.f) * CogUV[0] + CogUV[1];
    2198 
    2199     //Lower points
    2200     CogSz = 1.0f - CogLn[1];
    2201     uv[6]  = vec2(0.f,   1.f) * InUV[0]  + InUV[1];
    2202     uv[7]  = vec2(1.f,   1.f) * InUV[0]  + InUV[1];
    2203     uv[11] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2];
    2204     uv[10] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1];
    2205     uv[ 9] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0];
    2206     uv[ 8] = vec2(0.f,   1.f) * CogUV[0] + CogUV[1];
    2207 
    2208 #define DEF_J_K_Q                         \
    2209     int j = 3 * 12 * i,                   \
    2210         k = 3 * 12 * ((i + 1) % nbsides); \
    2211     int q[] = {                \
    2212 /* The top and bottom faces */ \
    2213                 j, j, j, j, \
    2214                 j, j, j, j, \
    2215                 j, j, k, k, \
    2216                 k, k, j, j, \
    2217                 j, j, j, k, \
    2218                 k, j, j, j, \
    2219 /* The inner side quads */  \
    2220                 j, j, j, j, \
    2221                 j, k, k, j, \
    2222 /* The outer side quads */  \
    2223                 j, j, j, j, \
    2224                 j, j, j, j, \
    2225                 j, j, j, j, \
    2226                 k, j, j, k  \
    2227                 };          \
    2228     UNUSED(q);
    2229     int m[] = { /* The top and bottom faces */
    2230                 0,  2,  3,  1,
    2231                 7,  9,  8,  6,
    2232                 1,  3,  2,  0,
    2233                 6,  8,  9,  7,
    2234                 3,  4,  5,  2,
    2235                 8, 11, 10,  9,
    2236                 /* The inner side quads */
    2237                 0,  1,  7,  6,
    2238                 1,  0,  6,  7,
    2239                 /* The outer side quads */
    2240                 3,  2,  8,  9,
    2241                 4,  3,  9, 10,
    2242                 5,  4, 10, 11,
    2243                 2,  5, 11, 8
    2244                 };
    2245     int a[] = { /* The top and bottom faces */
    2246                 0, 0, 0, 0,
    2247                 0, 0, 0, 0,
    2248                 0, 0, 0, 0,
    2249                 0, 0, 0, 0,
    2250                 0, 0, 0, 0,
    2251                 0, 0, 0, 0,
    2252                 /* The inner side quads */
    2253                 1, 1, 1, 1,
    2254                 2, 2, 2, 2,
    2255                 /* The outer side quads */
    2256                 1, 1, 1, 1,
    2257                 1, 2, 2, 1,
    2258                 1, 2, 2, 1,
    2259                 2, 2, 2, 2
    2260                 };
    2261     //Gear generation loop
    2262     //Two passes necessary to ensure "weighted quad" compatibility
    2263     //First pass : Add vertices
    2264     for (int i = 0; i < nbsides; i++)
    2265     {
    2266         DEF_J_K_Q;
    2267 
    2268         /* Each vertex will share three faces, so three different
    2269          * normals, therefore we add each vertex three times. */
    2270         for (int n = 0; n < 3 * 12; n++)
    2271         {
    2272             int d = n / 3;
    2273             int e = d % 6;
    2274             AddVertex(p[d]);
    2275             if (n % 3 == 0) //Top-Bottom logic
    2276             {
    2277                 vec2 tmp = (p[d].xz / maxr);
    2278                 vec2 add;
    2279                 if (d >= 6)
    2280                 {
    2281                     tmp *= -1.0f;
    2282                     add = lowadd;
    2283                 }
    2284                 else
    2285                     add = upadd;
    2286                 SetCurVertTexCoord(tmp * vec2(.25f) + add);
    2287                 SetCurVertTexCoord2(tmp * vec2(.25f) + add);
    2288             }
    2289             else if (e == 0 || e == 1) //inner Logic
    2290             {
    2291                 SetCurVertTexCoord(uv[d]);
    2292                 SetCurVertTexCoord2(uv[d]);
    2293             }
    2294             else //Cog logic
    2295             {
    2296                 if (e == 2 && n % 3 == 2)
    2297                 {
    2298                     SetCurVertTexCoord(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]);
    2299                     SetCurVertTexCoord2(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]);
    2300                 }
    2301                 else
    2302                 {
    2303                     SetCurVertTexCoord(uv[d]);
    2304                     SetCurVertTexCoord2(uv[d]);
    2305                 }
    2306             }
    2307             if (d >= 6)
    2308                 SetCurVertColor(BD()->ColorB());
    2309         }
    2310 
    2311         for (int n = 0; n < 12; n++)
    2312             p[n] = rotmat * p[n];
    2313     }
    2314     //Second pass : Build quad
    2315     for (int i = 0; i < nbsides; i++)
    2316     {
    2317         DEF_J_K_Q;
    2318         int l = -4;
    2319         while ((l += 4) < 48)
    2320             AppendQuad(q[l + 0] + m[l + 0] * 3 + a[l + 0],
    2321                        q[l + 1] + m[l + 1] * 3 + a[l + 1],
    2322                        q[l + 2] + m[l + 2] * 3 + a[l + 2],
    2323                        q[l + 3] + m[l + 3] * 3 + a[l + 3],
    2324                        vbase);
    2325     }
    2326 
    2327     ComputeNormals(ibase, m_indices.Count() - ibase);
    2328 }
    2329 
    2330 //-----------------------------------------------------------------------------
    2331 void EasyMesh::Chamfer(float f)
    2332 {
    2333     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2334     {
    2335         BD()->CmdStack().AddCmd(EasyMeshCmdType::Chamfer);
    2336         BD()->CmdStack() << f;
    2337         return;
    2338     }
    2339 
    2340     int vlen = m_vert.Count() - m_cursors.Last().m1;
    2341     int ilen = m_indices.Count() - m_cursors.Last().m2;
    2342 
    2343     /* Step 1: enumerate all faces. This is done by merging triangles
    2344      * that are coplanar and share an edge. */
    2345     int *triangle_classes = new int[ilen / 3];
    2346     for (int i = 0; i < ilen / 3; i++)
    2347         triangle_classes[i] = -1;
    2348 
    2349     for (int i = 0; i < ilen / 3; i++)
    2350     {
    2351 
    2352     }
    2353 
    2354     /* Fun shit: reduce all triangles */
    2355     int *vertices = new int[vlen];
    2356     memset(vertices, 0, vlen * sizeof(int));
    2357     for (int i = 0; i < ilen; i++)
    2358         vertices[m_indices[i]]++;
    2359 
    2360     for (int i = 0; i < ilen / 3; i++)
    2361 
    2362     {
    2363     #if 0
    2364         if (vertices[m_indices[i * 3]] > 1)
    2365             continue;
    2366         if (vertices[m_indices[i * 3 + 1]] > 1)
    2367             continue;
    2368         if (vertices[m_indices[i * 3 + 2]] > 1)
    2369             continue;
    2370     #endif
    2371 
    2372         vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m_coord +
    2373                                  m_vert[m_indices[i * 3 + 1]].m_coord +
    2374                                  m_vert[m_indices[i * 3 + 2]].m_coord);
    2375         for (int k = 0; k < 3; k++)
    2376         {
    2377             vec3 &p = m_vert[m_indices[i * 3 + k]].m_coord;
    2378             p -= normalize(p - bary) * f;
    2379         }
    2380     }
    2381 }
    2382 
    2383 //-----------------------------------------------------------------------------
    2384 void EasyMesh::SplitTriangles(int pass)
    2385 {
    2386     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2387     {
    2388         BD()->CmdStack().AddCmd(EasyMeshCmdType::SplitTriangles);
    2389         BD()->CmdStack() << pass;
    2390         return;
    2391     }
    2392 
    2393     SplitTriangles(pass, nullptr);
    2394 }
    2395 
    2396 //-----------------------------------------------------------------------------
    2397 void EasyMesh::SplitTriangles(int pass, VertexDictionnary *vert_dict)
    2398 {
    2399     while (pass--)
    2400     {
    2401         int trimax = m_indices.Count();
    2402         for (int i = m_cursors.Last().m2; i < trimax; i += 3)
    2403         {
    2404             int vbase = m_vert.Count();
    2405             int j = -1;
    2406             while (++j < 3)
    2407             {
    2408                 AddLerpVertex(m_indices[i + j], m_indices[i + (j + 1) % 3], .5f);
    2409                 if (vert_dict)
    2410                     vert_dict->AddVertex(vbase + j, m_vert[vbase + j].m_coord);
    2411             }
    2412             //Add new triangles
    2413             AppendTriangle(vbase, m_indices[i + 1], vbase + 1, 0);
    2414             AppendTriangle(vbase + 2, vbase + 1, m_indices[i + 2], 0);
    2415             AppendTriangle(vbase, vbase + 1, vbase + 2, 0);
    2416             //Change current triangle
    2417             m_indices[i + 1] = vbase;
    2418             m_indices[i + 2] = vbase + 2;
    2419         }
    2420     }
    2421     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    2422 }
    2423 
    2424 //-----------------------------------------------------------------------------
    2425 //TODO : Add an half-edges implementation to refine smooth.
    2426 //TODO : Smooth should only use connected vertices that are on edges of the mesh (See box).
    2427 void EasyMesh::SmoothMesh(int main_pass, int split_per_main_pass, int smooth_per_main_pass)
    2428 {
    2429     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2430     {
    2431         BD()->CmdStack().AddCmd(EasyMeshCmdType::SmoothMesh);
    2432         BD()->CmdStack() << main_pass << split_per_main_pass << smooth_per_main_pass;
    2433         return;
    2434     }
    2435 
    2436     VertexDictionnary vert_dict;
    2437     array<vec3> smooth_buf[2];
    2438     array<int> master_list;
    2439     array<int> matching_ids;
    2440     array<int> connected_vert;
    2441     int smbuf = 0;
    2442 
    2443     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    2444         vert_dict.AddVertex(i, m_vert[i].m_coord);
    2445 
    2446     while (main_pass--)
    2447     {
    2448         int split_pass = split_per_main_pass;
    2449         int smooth_pass = smooth_per_main_pass;
    2450 
    2451         SplitTriangles(split_pass, &vert_dict);
    2452 
    2453         matching_ids.Reserve(m_vert.Count() - m_cursors.Last().m1);
    2454         connected_vert.Reserve(m_vert.Count() - m_cursors.Last().m1);
    2455         smooth_buf[0].Resize(m_vert.Count() - m_cursors.Last().m1);
    2456         smooth_buf[1].Resize(m_vert.Count() - m_cursors.Last().m1);
    2457 
    2458         for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    2459             smooth_buf[smbuf][i - m_cursors.Last().m1] = m_vert[i].m_coord;
    2460 
    2461         while (smooth_pass--)
    2462         {
    2463             master_list.Empty();
    2464             if (vert_dict.GetMasterList(master_list))
    2465             {
    2466                 for (int i = 0; i < master_list.Count(); i++)
    2467                 {
    2468                     connected_vert.Empty();
    2469                     if (vert_dict.FindConnectedVertices(master_list[i], m_indices, m_cursors.Last().m2, connected_vert))
    2470                     {
    2471                         //Calculate vertices sum
    2472                         vec3 vert_sum = vec3(.0f);
    2473                         for (int j = 0; j < connected_vert.Count(); j++)
    2474                             vert_sum += smooth_buf[smbuf][connected_vert[j] - m_cursors.Last().m1];
    2475 
    2476                         //Calculate new master vertex
    2477                         float n = (float)connected_vert.Count();
    2478                         //b(n) = 5/4 - pow(3 + 2 * cos(2.f * F_PI / n), 2) / 32
    2479                         float beta = 3.f + 2.f * cos(2.f * F_PI / n);
    2480                         beta = 5.f / 4.f - beta * beta / 32.f;
    2481                         //a(n) = n * (1 - b(n)) / b(n)
    2482                         float alpha = (n * (1 - beta)) / beta;
    2483                         //V = (a(n) * v + v1 + ... + vn) / (a(n) + n)
    2484                         vec3 new_vert = (alpha * smooth_buf[smbuf][master_list[i] - m_cursors.Last().m1] + vert_sum) / (alpha + n);
    2485 
    2486                         //Set all matching vertices to new value
    2487                         matching_ids.Empty();
    2488                         matching_ids << master_list[i];
    2489                         vert_dict.FindMatchingVertices(master_list[i], matching_ids);
    2490                         for (int j = 0; j < matching_ids.Count(); j++)
    2491                             smooth_buf[1 - smbuf][matching_ids[j] - m_cursors.Last().m1] = new_vert;
    2492                     }
    2493                 }
    2494             }
    2495             smbuf = 1 - smbuf;
    2496         }
    2497 
    2498         for (int i = 0; i < smooth_buf[smbuf].Count(); i++)
    2499             m_vert[i + m_cursors.Last().m1].m_coord = smooth_buf[smbuf][i];
    2500     }
    2501 }
    2502 
    25031074} /* namespace lol */
  • trunk/src/easymesh/easymesh.h

    r3816 r3843  
    111111
    112112    //-------------------------------------------------------------------------
    113     //Mesh Base operations
     113    //Mesh Cursor operations
    114114    //-------------------------------------------------------------------------
    115115public:
     
    143143    //-------------------------------------------------------------------------
    144144private:
    145     void AddVertex(vec3 const &coord);
     145    void InternalAddVertex(vec3 const &coord);
    146146    void AddDuplicateVertex(int i);
    147147    void AddLerpVertex(int i, int j, float alpha);
     
    149149    VertexData GetLerpVertex(int i, int j, float alpha);
    150150    VertexData GetLerpVertex(VertexData const &vi, VertexData const &vj, float alpha);
    151     void AppendQuad(int i1, int i2, int i3, int i4, int base);
    152     void AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base);
    153     void AppendTriangle(int i1, int i2, int i3, int base);
    154     void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base);
     151    void InternalAddQuad(int i1, int i2, int i3, int i4, int base);
     152    void InternalAddQuadDupVerts(int i1, int i2, int i3, int i4, int base);
     153    void InternalAddTriangle(int i1, int i2, int i3, int base);
     154    void InternalAddTriangleDupVerts(int i1, int i2, int i3, int base);
    155155    void ComputeNormals(int start, int vcount);
    156156public:
     
    180180    //Mesh transform operations
    181181    //-------------------------------------------------------------------------
    182 
    183182    /* [cmd:t/tx/ty/tz] Translate vertices
    184183        - v : Translation quantity.
     
    262261        - s : scale quantity.
    263262     */
     263    void Scale(float s);
    264264    void Scale(vec3 const &s);
    265     void Scale(float s) { Scale(vec3(s)); }
    266     /* [cmd:mx] Mirror vertices through X-plane
     265    /* [cmd:m*] Mirror vertices through *-plane
    267266        Acts as an OpenBrace
    268267     */
    269268    void MirrorX();
    270     /* [cmd:my] Mirror vertices through Y-plane
    271         Acts as an OpenBrace
    272      */
    273269    void MirrorY();
    274     /* [cmd:mz] Mirror vertices through Z-plane
    275         Acts as an OpenBrace
    276      */
    277270    void MirrorZ();
    278271    /* [no-cmd] Duplicates vertices and scale duplicate
     
    299292
    300293    //-------------------------------------------------------------------------
    301     //Mesh shape operations
    302     //-------------------------------------------------------------------------
    303 
     294    //Mesh shape primitive operations
     295    //-------------------------------------------------------------------------
    304296    /* [cmd:ac] Cylinder centered on (0,0,0) with BBox [-.5*max(d1, d2), -.5*h, -.5*max(d1, d2)]
    305297        - nbsides : Number of sides.                   [+.5*max(d1, d2), +.5*h, +.5*max(d1, d2)]
  • trunk/src/easymesh/easymeshbuild.cpp

    r3577 r3843  
    145145//-----------------------------------------------------------------------------
    146146//Will update the given list with all the vertices on the same spot.
    147 void VertexDictionnary::AddVertex(const int vert_id, const vec3 vert_coord)
     147void VertexDictionnary::RegisterVertex(const int vert_id, const vec3 vert_coord)
    148148{
    149149    for (int j = 0; j < vertex_list.Count(); j++)
     
    173173
    174174    //We're here because we couldn't find any matching vertex
    175     master_list.Push(vertex_list.Count());
     175    master_list.Push((int)vertex_list.Count());
    176176    vertex_list.Push(vert_id, vert_coord, VDictType::Alone);
    177177}
  • trunk/src/easymesh/easymeshbuild.h

    r3816 r3843  
    533533    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);
    534534    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);
    535     void AddVertex(int vert_id, vec3 vert_coord);
     535    void RegisterVertex(int vert_id, vec3 vert_coord);
    536536    void RemoveVertex(int vert_id);
    537537    bool GetMasterList(array<int> &ret_master_list) { ret_master_list = master_list; return ret_master_list.Count() > 0; }
  • trunk/src/easymesh/easymeshprimitive.cpp

    r3837 r3843  
    22// Lol Engine
    33//
    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>
     4// Copyright: (c) 2010-2015 Sam Hocevar <sam@hocevar.net>
     5//            (c) 2009-2015 Cédric Lecacheur <jordx@free.fr>
     6//            (c) 2009-2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
    77//   This program is free software; you can redistribute it and/or
    88//   modify it under the terms of the Do What The Fuck You Want To
     
    1818#include <lol/engine-internal.h>
    1919
    20 LOLFX_RESOURCE_DECLARE(shiny);
    21 
    2220namespace lol
    2321{
    24 
    25 //-----------------------------------------------------------------------------
    26 EasyMesh::EasyMesh()
    27   : m_build_data(nullptr)
    28 {
    29     m_cursors.Push(0, 0);
    30     m_state = MeshRender::NeedData;
    31 }
    32 
    33 //-----------------------------------------------------------------------------
    34 EasyMesh::EasyMesh(const EasyMesh& em)
    35 {
    36     m_indices = em.m_indices;
    37     m_vert = em.m_vert;
    38     m_cursors = em.m_cursors;
    39     m_build_data = nullptr;
    40     if (em.m_build_data)
    41         m_build_data = new EasyMeshBuildData(*em.m_build_data);
    42     if (m_indices.Count() && m_vert.Count() && m_cursors.Count())
    43         m_state = MeshRender::NeedConvert;
    44     else
    45         m_state = MeshRender::NeedData;
    46 }
    47 
    48 //-----------------------------------------------------------------------------
    49 bool EasyMesh::Compile(char const *command, bool Execute)
    50 {
    51     bool res = false;
    52     // FIXME: make this work again
    53 #if 0
    54     EasyMeshCompiler mc(*this);
    55     BD()->Enable(MeshBuildOperation::CommandRecording);
    56     if ((res = mc.ParseString(command)))
    57     {
    58         BD()->Disable(MeshBuildOperation::CommandRecording);
    59         if (Execute)
    60             ExecuteCmdStack();
    61     }
    62 #endif
    63     return res;
    64 }
    65 
    66 void EasyMesh::MeshConvert()
    67 {
    68     /* Default material */
    69     Shader *shader = Shader::Create(LOLFX_RESOURCE_NAME(shiny));
    70 
    71     /* Push index buffer to GPU */
    72     IndexBuffer *ibo = new IndexBuffer(m_indices.Count() * sizeof(uint16_t));
    73     uint16_t *indices = (uint16_t *)ibo->Lock(0, 0);
    74     for (int i = 0; i < m_indices.Count(); ++i)
    75         indices[i] = m_indices[i];
    76     ibo->Unlock();
    77 
    78     /* Push vertex buffer to GPU */
    79     struct Vertex
    80     {
    81         vec3 pos, normal;
    82         u8vec4 color;
    83         vec4 texcoord;
    84     };
    85 
    86     VertexDeclaration *vdecl = new VertexDeclaration(
    87         VertexStream<vec3, vec3, u8vec4, vec4>(VertexUsage::Position,
    88                                                VertexUsage::Normal,
    89                                                VertexUsage::Color,
    90                                                VertexUsage::TexCoord));
    91 
    92     VertexBuffer *vbo = new VertexBuffer(m_vert.Count() * sizeof(Vertex));
    93     Vertex *vert = (Vertex *)vbo->Lock(0, 0);
    94     for (int i = 0; i < m_vert.Count(); ++i)
    95     {
    96         vert[i].pos = m_vert[i].m_coord,
    97         vert[i].normal = m_vert[i].m_normal,
    98         vert[i].color = (u8vec4)(m_vert[i].m_color * 255.f);
    99         vert[i].texcoord = m_vert[i].m_texcoord;
    100     }
    101     vbo->Unlock();
    102 
    103     /* Reference our new data in our submesh */
    104     m_submeshes.Push(new SubMesh(shader, vdecl));
    105     m_submeshes.Last()->SetIndexBuffer(ibo);
    106     m_submeshes.Last()->SetVertexBuffer(0, vbo);
    107 
    108     m_state = MeshRender::CanRender;
    109 }
    110 
    111 //-----------------------------------------------------------------------------
    112 #define EZSET(M0)                                               BD()->CmdStack().GetValue(M0);
    113 #define EZDEF_1(T0)                                             T0 m0; EZSET(m0)
    114 #define EZDEF_2(T0, T1)                                         EZDEF_1(T0) T1 m1; EZSET(m1)
    115 #define EZDEF_3(T0, T1, T2)                                     EZDEF_2(T0, T1) T2 m2; EZSET(m2)
    116 #define EZDEF_4(T0, T1, T2, T3)                                 EZDEF_3(T0, T1, T2) T3 m3; EZSET(m3)
    117 #define EZDEF_5(T0, T1, T2, T3, T4)                             EZDEF_4(T0, T1, T2, T3) T4 m4; EZSET(m4)
    118 #define EZDEF_6(T0, T1, T2, T3, T4, T5)                         EZDEF_5(T0, T1, T2, T3, T4) T5 m5; EZSET(m5)
    119 #define EZDEF_7(T0, T1, T2, T3, T4, T5, T6)                     EZDEF_6(T0, T1, T2, T3, T4, T5) T6 m6; EZSET(m6)
    120 #define EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7)                 EZDEF_7(T0, T1, T2, T3, T4, T5, T6) T7 m7; EZSET(m7)
    121 #define EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8)             EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7) T8 m8; EZSET(m8)
    122 #define EZDEF_10(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)        EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9 m9; EZSET(m9)
    123 
    124 //----
    125 #define EZCALL_1(F)                                             F();
    126 #define EZCALL_2(F, T0)                                         EZDEF_1(T0) F(m0);
    127 #define EZCALL_3(F, T0, T1)                                     EZDEF_2(T0, T1) F(m0, m1);
    128 #define EZCALL_4(F, T0, T1, T2)                                 EZDEF_3(T0, T1, T2) F(m0, m1, m2);
    129 #define EZCALL_5(F, T0, T1, T2, T3)                             EZDEF_4(T0, T1, T2, T3) F(m0, m1, m2, m3);
    130 #define EZCALL_6(F, T0, T1, T2, T3, T4)                         EZDEF_5(T0, T1, T2, T3, T4) F(m0, m1, m2, m3, m4);
    131 #define EZCALL_7(F, T0, T1, T2, T3, T4, T5)                     EZDEF_6(T0, T1, T2, T3, T4, T5) F(m0, m1, m2, m3, m4, m5);
    132 #define EZCALL_8(F, T0, T1, T2, T3, T4, T5, T6)                 EZDEF_7(T0, T1, T2, T3, T4, T5, T6) F(m0, m1, m2, m3, m4, m5, m6);
    133 #define EZCALL_9(F, T0, T1, T2, T3, T4, T5, T6, T7)             EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7) F(m0, m1, m2, m3, m4, m5, m6, m7);
    134 #define EZCALL_10(F, T0, T1, T2, T3, T4, T5, T6, T7, T8)        EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8) F(m0, m1, m2, m3, m4, m5, m6, m7, m8);
    135 #define EZCALL_11(F, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)    EZDEF_10(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) F(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9);
    136 
    137 //----
    138 #define EZM_CALL_FUNC(...) \
    139             LOL_CALL(LOL_CAT(EZCALL_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__))
    140 
    141 //-----------------------------------------------------------------------------
    142 void EasyMesh::ExecuteCmdStack(bool ExecAllStack)
    143 {
    144 #define DO_EXEC_CMD(MESH_CMD, FUNC_PARAMS)  \
    145         case EasyMeshCmdType::MESH_CMD:     \
    146         { EZM_CALL_FUNC FUNC_PARAMS; break; }
    147 
    148     BD()->Enable(MeshBuildOperation::CommandExecution);
    149     if (ExecAllStack)
    150         BD()->Cmdi() = 0;
    151 
    152     for (; BD()->Cmdi() < BD()->CmdStack().GetCmdNb() && BD()->CmdExecNb() != 0; ++BD()->Cmdi())
    153     {
    154         if (BD()->CmdExecNb() > 0)
    155             --BD()->CmdExecNb();
    156 
    157         switch (BD()->CmdStack().GetCmd(BD()->Cmdi()))
    158         {
    159             DO_EXEC_CMD(MeshCsg,                (MeshCsg, CSGUsage))
    160             DO_EXEC_CMD(LoopStart,              (LoopStart, int))
    161             DO_EXEC_CMD(LoopEnd,                (LoopEnd))
    162             DO_EXEC_CMD(OpenBrace,              (OpenBrace))
    163             DO_EXEC_CMD(CloseBrace,             (CloseBrace))
    164             DO_EXEC_CMD(ScaleWinding,           (ToggleScaleWinding))
    165             DO_EXEC_CMD(QuadWeighting,          (ToggleQuadWeighting))
    166             DO_EXEC_CMD(PostBuildNormal,        (TogglePostBuildNormal))
    167             DO_EXEC_CMD(PreventVertCleanup,     (ToggleVerticeNoCleanup))
    168             DO_EXEC_CMD(VerticesMerge,          (VerticesMerge))
    169             DO_EXEC_CMD(VerticesSeparate,       (VerticesSeparate))
    170             DO_EXEC_CMD(SetColorA,              (SetCurColorA, vec4))
    171             DO_EXEC_CMD(SetColorB,              (SetCurColorB, vec4))
    172             DO_EXEC_CMD(SetVertColor,           (SetVertColor, vec4))
    173             DO_EXEC_CMD(Translate,              (Translate, vec3))
    174             DO_EXEC_CMD(Rotate,                 (Rotate, float, vec3))
    175             DO_EXEC_CMD(RadialJitter,           (RadialJitter, float))
    176             DO_EXEC_CMD(MeshTranform,           (DoMeshTransform, MeshTransform, Axis, Axis, float, float, float, bool))
    177             DO_EXEC_CMD(Scale,                  (Scale, vec3))
    178             DO_EXEC_CMD(DupAndScale,            (DupAndScale, vec3, bool))
    179             DO_EXEC_CMD(Chamfer,                (Chamfer, float))
    180             DO_EXEC_CMD(SplitTriangles,         (SplitTriangles, int))
    181             DO_EXEC_CMD(SmoothMesh,             (SmoothMesh, int, int, int))
    182             DO_EXEC_CMD(AppendCylinder,         (AppendCylinder, int, float, float, float, bool, bool, bool))
    183             DO_EXEC_CMD(AppendCapsule,          (AppendCapsule, int, float, float))
    184             DO_EXEC_CMD(AppendTorus,            (AppendTorus, int, float, float))
    185             DO_EXEC_CMD(AppendBox,              (AppendBox, vec3, float, bool))
    186             DO_EXEC_CMD(AppendStar,             (AppendStar, int, float, float, bool, bool))
    187             DO_EXEC_CMD(AppendExpandedStar,     (AppendExpandedStar, int, float, float, float))
    188             DO_EXEC_CMD(AppendDisc,             (AppendDisc, int, float, bool))
    189             DO_EXEC_CMD(AppendSimpleTriangle,   (AppendSimpleTriangle, float, bool))
    190             DO_EXEC_CMD(AppendSimpleQuad,       (AppendSimpleQuad, vec2, vec2, float, bool))
    191             DO_EXEC_CMD(AppendCog,              (AppendCog, int, float, float, float, float, float, float, float, float, bool))
    192             default:
    193                 ASSERT(0, "Unknown command pseudo bytecode");
    194         }
    195     }
    196     BD()->Disable(MeshBuildOperation::CommandExecution);
    197 
    198     if (!BD()->IsEnabled(MeshBuildOperation::PreventVertCleanup))
    199         VerticesCleanup();
    200 
    201     if (BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
    202         ComputeNormals(0, m_indices.Count());
    203 
    204     BD()->Disable(MeshBuildOperation::PostBuildComputeNormals);
    205     BD()->Disable(MeshBuildOperation::PreventVertCleanup);
    206 
    207     if (BD()->CmdExecNb() > 0)
    208         BD()->CmdExecNb() = -1;
    209 }
    210 
    211 //-----------------------------------------------------------------------------
    212 void EasyMesh::LoopStart(int loopnb)
    213 {
    214     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    215     {
    216         BD()->CmdStack().AddCmd(EasyMeshCmdType::LoopStart);
    217         BD()->CmdStack() << loopnb;
    218         return;
    219     }
    220     //Loop is only available when executing a command recording
    221     else if (BD()->IsEnabled(MeshBuildOperation::CommandExecution))
    222     {
    223         //Only register if we're not the current loop command
    224         if (!BD()->LoopStack().Count() || BD()->LoopStack().Last().m1 != BD()->Cmdi())
    225             BD()->LoopStack().Push(BD()->Cmdi(), loopnb);
    226     }
    227 }
    228 
    229 //-----------------------------------------------------------------------------
    230 void EasyMesh::LoopEnd()
    231 {
    232     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    233     {
    234         BD()->CmdStack().AddCmd(EasyMeshCmdType::LoopEnd);
    235         return;
    236     }
    237     //Loop is only available when executing a command recording
    238     else if (BD()->IsEnabled(MeshBuildOperation::CommandExecution))
    239     {
    240         //Only register if we're not the current loop command
    241         if (BD()->LoopStack().Count())
    242         {
    243             BD()->LoopStack().Last().m2--;
    244             if (BD()->LoopStack().Last().m2 > 0)
    245                 BD()->Cmdi() = BD()->LoopStack().Last().m1 - 1;
    246             else
    247                 BD()->LoopStack().Pop();
    248         }
    249     }
    250 }
    251 
    252 //-----------------------------------------------------------------------------
    253 void EasyMesh::OpenBrace()
    254 {
    255     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    256     {
    257         BD()->CmdStack().AddCmd(EasyMeshCmdType::OpenBrace);
    258         return;
    259     }
    260 
    261     m_cursors.Push(m_vert.Count(), m_indices.Count());
    262 }
    263 
    264 //-----------------------------------------------------------------------------
    265 void EasyMesh::CloseBrace()
    266 {
    267     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    268     {
    269         BD()->CmdStack().AddCmd(EasyMeshCmdType::CloseBrace);
    270         return;
    271     }
    272 
    273     m_cursors.Pop();
    274 }
    275 
    276 //-----------------------------------------------------------------------------
    277 bool EasyMesh::SetRender(bool should_render)
    278 {
    279     if (m_state == MeshRender::CanRender)
    280     {
    281         if (!should_render)
    282             m_state = MeshRender::IgnoreRender;
    283         return true;
    284     }
    285     else if (m_state == MeshRender::IgnoreRender)
    286     {
    287         if (should_render)
    288             m_state = MeshRender::CanRender;
    289         return true;
    290     }
    291     return false;
    292 }
    293 
    294 //-------------------
    295 // "Collisions" functions
    296 //-------------------
    297 
    298 //-----------------------------------------------------------------------------
    299 void EasyMesh::MeshCsg(CSGUsage csg_operation)
    300 {
    301     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    302     {
    303         BD()->CmdStack().AddCmd(EasyMeshCmdType::MeshCsg);
    304         BD()->CmdStack() << csg_operation;
    305         return;
    306     }
    307 
    308     //A vertex dictionnary for vertices on the same spot.
    309     array< int, int > vertex_dict;
    310     //This list keeps track of the triangle that will need deletion at the end.
    311     array< int > triangle_to_kill;
    312     //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>>
    313     array< int, array< vec3, vec3, vec3 > > triangle_isec;
    314     //keep a track of the intersection point on the triangle. <pos, side_id>
    315     array< vec3, int > triangle_vertex;
    316     for (int k = 0; k < 10; k++)
    317         triangle_vertex.Push(vec3(.0f), 0);
    318 
    319     //bsp infos
    320     CsgBsp mesh_bsp_0;
    321     CsgBsp mesh_bsp_1;
    322 
    323     if (m_cursors.Count() == 0)
    324         return;
    325 
    326     //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]"
    327     int cursor_start = (m_cursors.Count() < 2)?(0):(m_cursors[(m_cursors.Count() - 2)].m2);
    328     for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    329     {
    330         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    331         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count());
    332         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1);
    333         for (int i = start_point; i < end_point; i += 3)
    334             mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord,
    335                                           m_vert[m_indices[i + 1]].m_coord,
    336                                           m_vert[m_indices[i + 2]].m_coord);
    337     }
    338 
    339     //BSP Usage : let's crunch all triangles on the correct BSP
    340     int indices_count = m_indices.Count();
    341     for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    342     {
    343         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    344         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count);
    345         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0);
    346         array< vec3, int, int, float > vert_list;
    347         array< int, int, int, int > tri_list;
    348         vec3 n0(.0f); vec3 n1(.0f);
    349         vec4 c0(.0f); vec4 c1(.0f);
    350 
    351         //Reserve some memory
    352         vert_list.Reserve(3);
    353         tri_list.Reserve(3);
    354 
    355         for (int i = start_point; i < end_point; i += 3)
    356         {
    357             int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord,
    358                                                      m_vert[m_indices[i + 1]].m_coord,
    359                                                      m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list);
    360             int tri_base_idx = m_indices.Count();
    361 
    362             //one split has been done, we need to had the new vertices & the new triangles.
    363             if (Result == 1)
    364             {
    365                 triangle_to_kill.Push(i);
    366 #if 1
    367                 int base_idx = m_vert.Count();
    368                 for (int k = 3; k < vert_list.Count(); k++)
    369                 {
    370                     int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3);
    371                     int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3);
    372 
    373                     AddVertex(vert_list[k].m1);
    374 
    375                     //Normal : bad calculations there.
    376                     n0 = m_vert[P0].m_normal;
    377                     n1 = m_vert[P1].m_normal;
    378                     SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4));
    379 
    380 #if 1
    381                     //Color
    382                     c0 = m_vert[P0].m_color;
    383                     c1 = m_vert[P1].m_color;
    384                     vec4 res = c0 + ((c1 - c0) * vert_list[k].m4);
    385                     SetCurVertColor(res);
    386 #else
    387                     if (mesh_id == 0)
    388                         SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f));
    389                     else
    390                         SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f));
    391 #endif
    392                 }
    393                 for (int k = 0; k < tri_list.Count(); k++)
    394                 {
    395                     int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3));
    396                     int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3));
    397                     int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3));
    398                     AppendTriangle(P0, P1, P2, 0);
    399                 }
    400 #endif
    401             }
    402 #if 1
    403             //Main case
    404             if (Result >= 0)
    405             {
    406                 for (int k = 0; k < tri_list.Count(); k++)
    407                 {
    408                     int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3));
    409 
    410                     //Triangle Kill Test
    411                     if (//csgu : CSGUnion() -> m0_Outside + m1_Outside
    412                         (csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) ||
    413                         //csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
    414                         (csg_operation == CSGUsage::Substract &&
    415                             ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) ||
    416                             (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) ||
    417                         //csgs : CsgSubL() -> m0_Outside
    418                         (csg_operation == CSGUsage::SubstractLoss &&
    419                             ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) ||
    420                         //csga : CSGAnd() -> m0_Inside + m1_Inside
    421                         (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT))
    422                     {
    423                         triangle_to_kill.Push(tri_idx);
    424                     }
    425 
    426                     //Triangle Invert Test
    427                     if (//csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
    428                         (csg_operation == CSGUsage::Substract && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) ||
    429                         //csgx : CSGXor() -> m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted
    430                         (csg_operation == CSGUsage::Xor && tri_list[k].m1 == LEAF_BACK))
    431                     {
    432                         //a Xor means we will share vertices with the outside, so duplicate the vertices.
    433                         //TODO : This operation disconnect all triangle, in some cases, not a good thing.
    434                         if (csg_operation == CSGUsage::Xor)
    435                         {
    436                             for (int l = 0; l < 3; l++)
    437                             {
    438                                 AddDuplicateVertex(m_indices[tri_idx + l]);
    439                                 m_indices[tri_idx + l] = m_vert.Count() - 1;
    440                             }
    441                         }
    442                         m_indices[tri_idx + 1] += m_indices[tri_idx + 2];
    443                         m_indices[tri_idx + 2]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    444                         m_indices[tri_idx + 1]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    445                         ComputeNormals(tri_idx, 3);
    446                     }
    447                 }
    448             }
    449 #endif
    450             vert_list.Empty();
    451             tri_list.Empty();
    452         }
    453     }
    454 
    455     for (int i = 0; i < m_vert.Count(); i++)
    456         if (length(m_vert[i].m_normal) < 1.0f)
    457             i = i;
    458 
    459     int dir = 1;
    460     for (int i = 0; i >= 0 && i < triangle_to_kill.Count() - 1; i += dir)
    461     {
    462         if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0)
    463             dir = 1;
    464         if (triangle_to_kill[i] == triangle_to_kill[i + 1])
    465         {
    466             triangle_to_kill.Remove(i);
    467             dir = -1;
    468         }
    469         if (triangle_to_kill[i] > triangle_to_kill[i + 1])
    470         {
    471             triangle_to_kill[i]     += triangle_to_kill[i + 1];
    472             triangle_to_kill[i + 1]  = triangle_to_kill[i] - triangle_to_kill[i + 1];
    473             triangle_to_kill[i]      = triangle_to_kill[i] - triangle_to_kill[i + 1];
    474             dir = -1;
    475         }
    476         if (i == 0 && dir == -1)
    477             dir = 1;
    478     }
    479     for (int i = triangle_to_kill.Count() - 1; i >= 0; i--)
    480         m_indices.Remove(triangle_to_kill[i], 3);
    481 
    482     m_cursors.Last().m1 = m_vert.Count();
    483     m_cursors.Last().m2 = m_indices.Count();
    484 
    485     VerticesCleanup();
    486     //DONE for the splitting !
    487 }
    488 
    489 //-----------------------------------------------------------------------------
    490 void EasyMesh::ToggleScaleWinding()
    491 {
    492     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    493     {
    494         BD()->CmdStack().AddCmd(EasyMeshCmdType::ScaleWinding);
    495         return;
    496     }
    497 
    498     BD()->Toggle(MeshBuildOperation::ScaleWinding);
    499 }
    500 
    501 //-----------------------------------------------------------------------------
    502 void EasyMesh::ToggleQuadWeighting()
    503 {
    504     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    505     {
    506         BD()->CmdStack().AddCmd(EasyMeshCmdType::QuadWeighting);
    507         return;
    508     }
    509 
    510     BD()->Toggle(MeshBuildOperation::QuadWeighting);
    511 }
    512 
    513 //-----------------------------------------------------------------------------
    514 void EasyMesh::TogglePostBuildNormal()
    515 {
    516     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    517     {
    518         BD()->CmdStack().AddCmd(EasyMeshCmdType::PostBuildNormal);
    519         return;
    520     }
    521 
    522     BD()->Toggle(MeshBuildOperation::PostBuildComputeNormals);
    523 }
    524 
    525 //-----------------------------------------------------------------------------
    526 void EasyMesh::ToggleVerticeNoCleanup()
    527 {
    528     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    529     {
    530         BD()->CmdStack().AddCmd(EasyMeshCmdType::PreventVertCleanup);
    531         return;
    532     }
    533 
    534     BD()->Toggle(MeshBuildOperation::PreventVertCleanup);
    535 }
    536 
    537 //-----------------------------------------------------------------------------
    538 void EasyMesh::SetCurColor(vec4 const &color)
    539 {
    540     SetCurColorA(color);
    541     SetCurColorB(color);
    542 }
    543 
    544 //-----------------------------------------------------------------------------
    545 void EasyMesh::SetCurColorA(vec4 const &color)
    546 {
    547     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    548     {
    549         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetColorA);
    550         BD()->CmdStack() << color;
    551         return;
    552     }
    553 
    554     BD()->ColorA() = color;
    555 }
    556 
    557 //-----------------------------------------------------------------------------
    558 void EasyMesh::SetCurColorB(vec4 const &color)
    559 {
    560     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    561     {
    562         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetColorB);
    563         BD()->CmdStack() << color;
    564         return;
    565     }
    566 
    567     BD()->ColorB() = color;
    568 }
    569 
    570 //-----------------------------------------------------------------------------
    571 void EasyMesh::SetVertColor(vec4 const &color)
    572 {
    573     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    574     {
    575         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetVertColor);
    576         BD()->CmdStack() << color;
    577         return;
    578     }
    579 
    580     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    581         m_vert[i].m_color = color;
    582 }
    583 
    584 //-----------------------------------------------------------------------------
    585 void EasyMesh::AddVertex(vec3 const &coord)
    586 {
    587     m_vert.Push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->ColorA()));
    588     m_state = MeshRender::NeedConvert;
    589 }
    590 
    591 //-----------------------------------------------------------------------------
    592 void EasyMesh::AddDuplicateVertex(int i)
    593 {
    594     m_vert << m_vert[i];
    595     m_state = MeshRender::NeedConvert;
    596 }
    597 
    598 //-----------------------------------------------------------------------------
    599 void EasyMesh::AddLerpVertex(int i, int j, float alpha)
    600 {
    601     AddLerpVertex(m_vert[i], m_vert[j], alpha);
    602 
    603 }
    604 //-----------------------------------------------------------------------------
    605 void EasyMesh::AddLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
    606 {
    607     m_vert.Push(GetLerpVertex(vi, vj, alpha));
    608     m_state = MeshRender::NeedConvert;
    609 }
    610 
    611 //-----------------------------------------------------------------------------
    612 VertexData EasyMesh::GetLerpVertex(int i, int j, float alpha)
    613 {
    614     return GetLerpVertex(m_vert[i], m_vert[j], alpha);
    615 }
    616 
    617 //-----------------------------------------------------------------------------
    618 VertexData EasyMesh::GetLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
    619 {
    620     return VertexData(
    621         lol::lerp(vi.m_coord,    vj.m_coord,      alpha),
    622         lol::lerp(vi.m_normal,   vj.m_normal,     alpha),
    623         lol::lerp(vi.m_color,    vj.m_color,      alpha),
    624         lol::lerp(vi.m_texcoord, vj.m_texcoord,   alpha),
    625         ((alpha < .5f) ? (vi.m_bone_id) : (vj.m_bone_id)), /* FIXME ? */
    626         lol::lerp(vi.m_bone_weight, vj.m_bone_weight, alpha));
    627 }
    628 
    629 //-----------------------------------------------------------------------------
    630 void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
    631 {
    632     if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) &&
    633         !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting))
    634     {
    635         int i5 = m_vert.Count();
    636         AddLerpVertex(GetLerpVertex(base + i1, base + i3, .5f),
    637                       GetLerpVertex(base + i2, base + i4, .5f), .5f);
    638         m_indices << i1 + base;
    639         m_indices << i2 + base;
    640         m_indices << i5;
    641 
    642         m_indices << i2 + base;
    643         m_indices << i3 + base;
    644         m_indices << i5;
    645 
    646         m_indices << i4 + base;
    647         m_indices << i1 + base;
    648         m_indices << i5;
    649 
    650         m_indices << i5;
    651         m_indices << i3 + base;
    652         m_indices << i4 + base;
    653     }
    654     else
    655     {
    656         m_indices << base + i1;
    657         m_indices << base + i2;
    658         m_indices << base + i3;
    659 
    660         m_indices << base + i4;
    661         m_indices << base + i1;
    662         m_indices << base + i3;
    663     }
    664 }
    665 
    666 //-----------------------------------------------------------------------------
    667 void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
    668 {
    669     int vbase = m_vert.Count();
    670     AddDuplicateVertex(base + i1);
    671     AddDuplicateVertex(base + i2);
    672     AddDuplicateVertex(base + i3);
    673     AddDuplicateVertex(base + i4);
    674 
    675     AppendQuad(0, 1, 2, 3, vbase);
    676 }
    677 
    678 //-----------------------------------------------------------------------------
    679 void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
    680 {
    681     m_indices << base + i1;
    682     m_indices << base + i2;
    683     m_indices << base + i3;
    684 }
    685 
    686 //-----------------------------------------------------------------------------
    687 void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
    688 {
    689     m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
    690     m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
    691     m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
    692 }
    693 
    694 //-----------------------------------------------------------------------------
    695 void EasyMesh::ComputeNormals(int start, int vcount)
    696 {
    697 
    698     if (BD()->IsEnabled(MeshBuildOperation::CommandExecution) &&
    699         BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
    700         return;
    701 
    702     array< array<vec3> > normals;
    703     normals.Resize(m_vert.Count());
    704     for (int i = 0; i < vcount; i += 3)
    705     {
    706         vec3 v0 = m_vert[m_indices[start + i + 2]].m_coord
    707                 - m_vert[m_indices[start + i + 0]].m_coord;
    708         vec3 v1 = m_vert[m_indices[start + i + 1]].m_coord
    709                 - m_vert[m_indices[start + i + 0]].m_coord;
    710         vec3 n = normalize(cross(v1, v0));
    711 
    712         for (int j = 0; j < 3; j++)
    713             normals[m_indices[start + i + j]] << n;
    714     }
    715 
    716     for (int i = 0; i < normals.Count(); i++)
    717     {
    718         if (normals[i].Count() > 0)
    719         {
    720             //remove doubles
    721             for (int j = 0; j < normals[i].Count(); ++j)
    722                 for (int k = j + 1; k < normals[i].Count(); ++k)
    723                     if (1.f - dot(normals[i][k], normals[i][j]) < .00001f)
    724                         normals[i].Remove(k--);
    725 
    726             vec3 newv = vec3::zero;
    727             for (int j = 0; j < normals[i].Count(); ++j)
    728                 newv += normals[i][j];
    729             m_vert[i].m_normal = normalize(newv / (float)normals[i].Count());
    730         }
    731     }
    732 }
    733 
    734 //-----------------------------------------------------------------------------
    735 void EasyMesh::VerticesCleanup()
    736 {
    737     array<int> vert_ids;
    738     vert_ids.Resize(m_vert.Count(), 0);
    739 
    740     //1: Remove triangles with two vertices on each other
    741     for (int i = 0; i < m_indices.Count(); i += 3)
    742     {
    743         bool remove = false;
    744         for (int j = 0; !remove && j < 3; ++j)
    745             if (length(m_vert[m_indices[i + j]].m_coord - m_vert[m_indices[i + (j + 1) % 3]].m_coord) < .00001f)
    746                 remove = true;
    747         if (remove)
    748         {
    749             m_indices.RemoveSwap(i, 3);
    750             i -= 3;
    751         }
    752         else
    753         {
    754             //1.5: Mark all used vertices
    755             for (int j = 0; j < 3; ++j)
    756                 vert_ids[m_indices[i + j]] = 1;
    757         }
    758     }
    759 
    760     //2: Remove all unused vertices
    761     array<VertexData> old_vert = m_vert;
    762     int shift = 0;
    763     m_vert.Empty();
    764     for (int i = 0; i < vert_ids.Count(); ++i)
    765     {
    766         //Unused vertex, update the shift quantity instead of keeping it.
    767         if (vert_ids[i] == 0)
    768             shift++;
    769         else
    770             m_vert << old_vert[i];
    771         //Always mark it with the shift quantity
    772         vert_ids[i] = shift;
    773     }
    774 
    775     //3: Update the indices
    776     for (int i = 0; i < m_indices.Count(); ++i)
    777         m_indices[i] -= vert_ids[m_indices[i]];
    778 }
    779 
    780 //-----------------------------------------------------------------------------
    781 void EasyMesh::VerticesMerge()
    782 {
    783     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    784     {
    785         BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesMerge);
    786         return;
    787     }
    788 
    789     //1: Crunch all vertices in the dictionnary
    790     VertexDictionnary vert_dict;
    791     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    792         vert_dict.AddVertex(i, m_vert[i].m_coord);
    793 
    794     //2: Update the indices
    795     for (int i = 0; i < m_indices.Count(); ++i)
    796     {
    797         int master = vert_dict.FindVertexMaster(m_indices[i]);
    798         if (master >= 0)
    799             m_indices[i] = master;
    800     }
    801 
    802     //2: Cleanup
    803     VerticesCleanup();
    804 }
    805 
    806 //-----------------------------------------------------------------------------
    807 void EasyMesh::VerticesSeparate()
    808 {
    809     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    810     {
    811         BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesSeparate);
    812         return;
    813     }
    814 
    815     array< array<int> > new_ids;
    816     array<int> vert_ids;
    817     vert_ids.Resize(m_vert.Count(), 0);
    818 
    819     //1: Mark all used vertices
    820     for (int i = 0; i < m_indices.Count(); ++i)
    821         vert_ids[m_indices[i]]++;
    822 
    823     //2: Update the vertices
    824     int vbase = m_cursors.Last().m1;
    825     int vcount = m_vert.Count();
    826     new_ids.Resize(vcount);
    827     for (int i = vbase; i < vcount; i++)
    828     {
    829         while (vert_ids[i] > 1)
    830         {
    831             //Add duplicate
    832             new_ids[i] << m_vert.Count();
    833             AddDuplicateVertex(i);
    834             vert_ids[i]--;
    835         }
    836     }
    837 
    838     //3: Update the indices
    839     for (int i = 0; i < m_indices.Count(); ++i)
    840     {
    841         if (new_ids[m_indices[i]].Count())
    842         {
    843             int j = new_ids[m_indices[i]].Pop();
    844             m_indices[i] = j;
    845         }
    846     }
    847 
    848     //4: Cleanup
    849     VerticesCleanup();
    850 }
    851 
    852 //-----------------------------------------------------------------------------
    853 void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset)
    854 {
    855     UNUSED(uv_scale, uv_offset);
    856 #if 0
    857     VertexDictionnary vert_dict;
    858     array<int> tri_list;
    859 
    860     tri_list.Reserve(m_indices.Count() - m_cursors.Last().m2);
    861     for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++)
    862     {
    863         vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
    864         tri_list << m_indices[i];
    865     }
    866 
    867     //full triangle count
    868     array<int> tri_done;
    869     array<int> tri_check;
    870     int tri_count = (m_indices.Count() - m_cursors.Last().m2) / 3;
    871 
    872     tri_check << tri_list[0];
    873 
    874     while (tri_check.Count())
    875     {
    876         int cur_tri = tri_check[0];
    877         int v[3]   = { tri_list[cur_tri + uv_offset % 3], tri_list[cur_tri + (1 + uv_offset) % 3], tri_list[cur_tri + (2 + uv_offset) % 3] };
    878         vec2 uv[3] = { m_vert[tri_list[cur_tri]].m_texcoord.xy, m_vert[tri_list[cur_tri + 1]].m_texcoord.xy, m_vert[tri_list[cur_tri + 2]].m_texcoord.xy };
    879         for (int j = 0; j < 3; j++)
    880         {
    881             if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3])
    882             {
    883                 uv[0] = vec2(-1.0f);
    884                 uv[1] = vec2(-1.0f);
    885                 uv[2] = vec2(-1.0f);
    886                 break;
    887             }
    888         }
    889         int uv_set = 0;
    890         for (int j = 0; j < 3; j++)
    891             uv_set += (uv[j].x < 0.f)?(0):(1);
    892 
    893         //this case shouldn't happen.
    894         if (uv_set == 1)
    895         {
    896             /*
    897             for (int j = 0; j < 3; j++)
    898             {
    899                 if (uv[j] != vec2(-1.0f))
    900                 {
    901                     uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(m_vert[v[j]].m1 - m_vert[v[(j + 1) % 3]].m1));
    902                     uv_set = 2;
    903                     break;
    904                 }
    905             }
    906             */
    907         }
    908         //No UV is set, let's do the arbitrary set and use the basic method.
    909         if (uv_set == 0)
    910         {
    911             float new_dot = FLT_MAX;
    912             int base_i = 0;
    913             for (int j = 0; j < 3; j++)
    914             {
    915                 float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m_coord - m_vert[v[j]].m_coord),
    916                                         normalize(m_vert[v[(j + 2) % 3]].m_coord - m_vert[v[j]].m_coord)));
    917                 if (tmp_dot < new_dot)
    918                 {
    919                     base_i = j;
    920                     new_dot = tmp_dot;
    921                 }
    922             }
    923             uv[base_i] = vec2(.0f);
    924             uv[(base_i + 1) % 3] = vec2(.0f, uv_scale * length(m_vert[v[base_i]].m_coord - m_vert[v[(base_i + 1) % 3]].m_coord));
    925             uv_set = 2;
    926         }
    927         //2 points have been set, let's figure the third
    928         if (uv_set == 2)
    929         {
    930             {
    931                 //invert values so the two set uv are in [0, 1] slots.
    932                 int new_v[3];
    933                 vec2 new_uv[3];
    934                 bool ignore_set = false;
    935                 if (uv[0].x >= 0.f && uv[1].x < 0.f)
    936                 {
    937                     new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1];
    938                     new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1];
    939                 }
    940                 else if (uv[0].x < 0.f && uv[1].x >= 0.f)
    941                 {
    942                     new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0];
    943                     new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0];
    944                 }
    945                 else
    946                     ignore_set = true;
    947                 if (!ignore_set)
    948                 {
    949                     v[0]  = new_v[0];  v[1]  = new_v[1];  v[2]  = new_v[2];
    950                     uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2];
    951                 }
    952             }
    953 
    954             //Do this to be sure the normal is OK.
    955             ComputeNormals(cur_tri, 3);
    956             vec3 v01 = normalize(m_vert[v[1]].m_coord - m_vert[v[0]].m_coord);
    957             vec3 v02 = m_vert[v[2]].m_coord - m_vert[v[0]].m_coord;
    958             vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m_normal, v01));
    959             vec2 texu_dir = uv[1] - uv[0];
    960             vec2 texv_dir = vec2(texu_dir.y, texu_dir.x);
    961             //Final calculations
    962             uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02);
    963 
    964             //Set UV on ALL matching vertices!
    965             array<int> matching_vert;
    966             for (int i = 0; i < 3; i++)
    967             {
    968 #if 1
    969                 //This marks all same position UV to the same values
    970                 //Deactivation is a test.
    971                 matching_vert << v[i];
    972                 vert_dict.FindMatchingVertices(v[i], matching_vert);
    973                 for (int j = 0; j < matching_vert.Count(); j++)
    974                     if (m_vert[matching_vert[j]].m_texcoord.xy == vec2(-1.0f))
    975                         m_vert[matching_vert[j]].m_texcoord = vec4(abs(uv[i]), m_vert[matching_vert[j]].m_texcoord.zw);
    976 #else
    977                 m_vert[v[i]].m_texcoord = abs(uv[i]);
    978 #endif
    979             }
    980 
    981             tri_done << cur_tri;
    982             tri_check.Remove(0);
    983 
    984             //Get connected triangles and go from there.
    985             for (int j = 0; j < 3; j++)
    986             {
    987 #if 1
    988                 //This finds triangle that are connected to this triangle
    989                 vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done);
    990 #else
    991                 //This finds triangle that are connected to the vertices of this triangle
    992                 vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done);
    993 #endif
    994             }
    995         }
    996         else if (uv_set == 3)
    997         {
    998             for (int j = 0; j < 3; j++)
    999             {
    1000                 m_vert[tri_list[cur_tri]].m_texcoord     = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri]].m_texcoord.zw);
    1001                 m_vert[tri_list[cur_tri + 1]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 1]].m_texcoord.zw);
    1002                 m_vert[tri_list[cur_tri + 2]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 2]].m_texcoord.zw);
    1003             }
    1004 
    1005             //uv[0] = vec2(-1.0f);
    1006             //uv[1] = vec2(-1.0f);
    1007             //uv[2] = vec2(-1.0f);
    1008             /*
    1009             bool tri_present = false;
    1010             for (int j = 0; j < tri_done.Count(); j++)
    1011                 if (cur_tri == tri_done[j])
    1012                     tri_present = true;
    1013             if (!tri_present)
    1014                 tri_done << cur_tri;
    1015             tri_check.Remove(0);
    1016             */
    1017         }
    1018 
    1019         if (tri_check.Count() == 0 && tri_done.Count() != tri_count)
    1020         {
    1021             //look for unset triangle
    1022             for (int i = 0; !tri_check.Count() && i < tri_list.Count(); i += 3)
    1023             {
    1024                 bool tri_present = false;
    1025                 for (int j = 0; j < tri_done.Count(); j++)
    1026                     if (i == tri_done[j])
    1027                         tri_present = true;
    1028                 if (!tri_present)
    1029                     tri_check << i;
    1030             }
    1031         }
    1032     }
    1033 #endif
    1034 }
    1035 
    1036 //-----------------------------------------------------------------------------
    1037 void EasyMesh::SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale)
    1038 {
    1039     BD()->TexCoordOffset() = new_offset;
    1040     BD()->TexCoordScale() = new_scale;
    1041 }
    1042 
    1043 //-----------------------------------------------------------------------------
    1044 void EasyMesh::SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale)
    1045 {
    1046     BD()->TexCoordOffset2() = new_offset;
    1047     BD()->TexCoordScale2() = new_scale;
    1048 }
    1049 
    1050 //-----------------------------------------------------------------------------
    1051 void EasyMesh::SetCurVertNormal(vec3 const &normal)
    1052 {
    1053     m_vert[m_vert.Count() - 1].m_normal = normal;
    1054 }
    1055 
    1056 //-----------------------------------------------------------------------------
    1057 void EasyMesh::SetCurVertColor(vec4 const &color)
    1058 {
    1059     m_vert[m_vert.Count() - 1].m_color = color;
    1060 }
    1061 
    1062 //-----------------------------------------------------------------------------
    1063 void EasyMesh::SetCurVertTexCoord(vec2 const &texcoord)
    1064 {
    1065     m_vert[m_vert.Count() - 1].m_texcoord = vec4(texcoord, m_vert[m_vert.Count() - 1].m_texcoord.zw);
    1066 }
    1067 
    1068 //-----------------------------------------------------------------------------
    1069 void EasyMesh::SetCurVertTexCoord2(vec2 const &texcoord)
    1070 {
    1071     m_vert[m_vert.Count() - 1].m_texcoord = vec4(m_vert[m_vert.Count() - 1].m_texcoord.xy, texcoord);
    1072 }
    1073 
    1074 //-----------------------------------------------------------------------------
    1075 void EasyMesh::Translate(vec3 const &v)
    1076 {
    1077     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1078     {
    1079         BD()->CmdStack().AddCmd(EasyMeshCmdType::Translate);
    1080         BD()->CmdStack() << v;
    1081         return;
    1082     }
    1083 
    1084     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1085         m_vert[i].m_coord += v;
    1086 }
    1087 
    1088 //-----------------------------------------------------------------------------
    1089 void EasyMesh::RotateX(float angle) { Rotate(angle, vec3(1, 0, 0)); }
    1090 void EasyMesh::RotateY(float angle) { Rotate(angle, vec3(0, 1, 0)); }
    1091 void EasyMesh::RotateZ(float angle) { Rotate(angle, vec3(0, 0, 1)); }
    1092 
    1093 //-----------------------------------------------------------------------------
    1094 void EasyMesh::Rotate(float angle, vec3 const &axis)
    1095 {
    1096     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1097     {
    1098         BD()->CmdStack().AddCmd(EasyMeshCmdType::Rotate);
    1099         BD()->CmdStack() << angle << axis;
    1100         return;
    1101     }
    1102 
    1103     mat3 m = mat3::rotate(angle, axis);
    1104     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1105     {
    1106         m_vert[i].m_coord  = m * m_vert[i].m_coord;
    1107         m_vert[i].m_normal = m * m_vert[i].m_normal;
    1108     }
    1109 }
    1110 
    1111 //-----------------------------------------------------------------------------
    1112 void EasyMesh::RadialJitter(float r)
    1113 {
    1114     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1115     {
    1116         BD()->CmdStack().AddCmd(EasyMeshCmdType::RadialJitter);
    1117         BD()->CmdStack() << r;
    1118         return;
    1119     }
    1120 
    1121     array<int> Welded;
    1122     Welded.Push(-1);
    1123     for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++)
    1124     {
    1125         int j, k;
    1126         for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++)
    1127         {
    1128             if(Welded[k] < 0)
    1129             {
    1130                 vec3 diff = m_vert[i].m_coord - m_vert[j].m_coord;
    1131 
    1132                 if(diff.x > 0.1f || diff.x < -0.1f)
    1133                     continue;
    1134 
    1135                 if(diff.y > 0.1f || diff.y < -0.1f)
    1136                     continue;
    1137 
    1138                 if(diff.z > 0.1f || diff.z < -0.1f)
    1139                     continue;
    1140 
    1141                 break;
    1142             }
    1143         }
    1144 
    1145         if(j == i)
    1146             Welded.Push(-1);
    1147         else
    1148             Welded.Push(j);
    1149     }
    1150 
    1151     int i, j;
    1152     for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++)
    1153     {
    1154         if(Welded[j] == -1)
    1155             m_vert[i].m_coord *= 1.0f + rand(r);
    1156         else
    1157             m_vert[i].m_coord = m_vert[Welded[j]].m_coord;
    1158     }
    1159 
    1160     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    1161 }
    1162 
    1163 //-----------------------------------------------------------------------------
    1164 void EasyMesh::TaperX(float ny, float nz, float xoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::X, Axis::X, ny, nz, xoff, absolute); }
    1165 void EasyMesh::TaperY(float nx, float nz, float yoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
    1166 void EasyMesh::TaperZ(float nx, float ny, float zoff, bool absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
    1167 
    1168 //-----------------------------------------------------------------------------
    1169 void EasyMesh::TwistX(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::X, Axis::X, t, t, toff); }
    1170 void EasyMesh::TwistY(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Y, Axis::Y, t, t, toff); }
    1171 void EasyMesh::TwistZ(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Z, Axis::Z, t, t, toff); }
    1172 
    1173 //-----------------------------------------------------------------------------
    1174 void EasyMesh::ShearX(float ny, float nz, float xoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::X, Axis::X, ny, nz, xoff, absolute); }
    1175 void EasyMesh::ShearY(float nx, float nz, float yoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Y, Axis::Y, nz, nx, yoff, absolute); }
    1176 void EasyMesh::ShearZ(float nx, float ny, float zoff, bool absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Z, Axis::Z, nx, ny, zoff, absolute); }
    1177 
    1178 //-----------------------------------------------------------------------------
    1179 void EasyMesh::StretchX(float ny, float nz, float xoff) { DoMeshTransform(MeshTransform::Stretch, Axis::X, Axis::X, ny, nz, xoff); }
    1180 void EasyMesh::StretchY(float nx, float nz, float yoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Y, Axis::Y, nz, nx, yoff); }
    1181 void EasyMesh::StretchZ(float nx, float ny, float zoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Z, Axis::Z, nx, ny, zoff); }
    1182 
    1183 //-----------------------------------------------------------------------------
    1184 void EasyMesh::BendXY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Y, t, t, toff); }
    1185 void EasyMesh::BendXZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Z, t, t, toff); }
    1186 void EasyMesh::BendYX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::X, t, t, toff); }
    1187 void EasyMesh::BendYZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::Z, t, t, toff); }
    1188 void EasyMesh::BendZX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::X, t, t, toff); }
    1189 void EasyMesh::BendZY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::Y, t, t, toff); }
    1190 
    1191 //-----------------------------------------------------------------------------
    1192 void EasyMesh::DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, bool absolute)
    1193 {
    1194     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1195     {
    1196         BD()->CmdStack().AddCmd(EasyMeshCmdType::MeshTranform);
    1197         BD()->CmdStack() << ct << axis0 << axis1 << n0 << n1 << noff << absolute;
    1198         return;
    1199     }
    1200 
    1201     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1202     {
    1203         switch (ct.ToScalar())
    1204         {
    1205             case MeshTransform::Taper:
    1206             {
    1207                 float value = m_vert[i].m_coord[axis0.ToScalar()];
    1208                 if (absolute) value = abs(value);
    1209                 m_vert[i].m_coord[(axis0.ToScalar() + 1) % 3] *= max(0.f, 1.f + (n0 * value + noff));
    1210                 m_vert[i].m_coord[(axis0.ToScalar() + 2) % 3] *= max(0.f, 1.f + (n1 * value + noff));
    1211                 break;
    1212             }
    1213             case MeshTransform::Twist:
    1214             {
    1215                 vec3 rotaxis = vec3(1.f); rotaxis[(axis0.ToScalar() + 1) % 3] = .0f; rotaxis[(axis0.ToScalar() + 2) % 3] = .0f;
    1216                 m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0.ToScalar()] * n0 + noff, rotaxis) * m_vert[i].m_coord;
    1217                 break;
    1218             }
    1219             case MeshTransform::Shear:
    1220             {
    1221                 float value = m_vert[i].m_coord[axis0.ToScalar()];
    1222                 if (absolute) value = abs(value);
    1223                 m_vert[i].m_coord[(axis0.ToScalar() + 1) % 3] += (n0 * value + noff);
    1224                 m_vert[i].m_coord[(axis0.ToScalar() + 2) % 3] += (n1 * value + noff);
    1225                 break;
    1226             }
    1227             case MeshTransform::Stretch:
    1228             {
    1229                 //float value = abs(m_vert[i].m1[axis0.ToScalar()]);
    1230                 //m_vert[i].m1[(axis0.ToScalar() + 1) % 3] += (lol::pow(value, n0) + noff);
    1231                 //m_vert[i].m1[(axis0.ToScalar() + 2) % 3] += (lol::pow(value, n1) + noff);
    1232                 break;
    1233             }
    1234             case MeshTransform::Bend:
    1235             {
    1236                 vec3 rotaxis = vec3(1.f); rotaxis[(axis1.ToScalar() + 1) % 3] = .0f; rotaxis[(axis1.ToScalar() + 2) % 3] = .0f;
    1237                 m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0.ToScalar()] * n0 + noff, rotaxis) * m_vert[i].m_coord;
    1238                 break;
    1239             }
    1240         }
    1241     }
    1242     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    1243 }
    1244 
    1245 //-----------------------------------------------------------------------------
    1246 void EasyMesh::Scale(vec3 const &s)
    1247 {
    1248     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1249     {
    1250         BD()->CmdStack().AddCmd(EasyMeshCmdType::Scale);
    1251         BD()->CmdStack() << s;
    1252         return;
    1253     }
    1254 
    1255     vec3 const invs = vec3(1) / s;
    1256 
    1257     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    1258     {
    1259         m_vert[i].m_coord *= s;
    1260         m_vert[i].m_normal = normalize(m_vert[i].m_normal * invs);
    1261     }
    1262 
    1263     /* Flip winding if the scaling involves mirroring */
    1264     if (!BD()->IsEnabled(MeshBuildOperation::ScaleWinding) && s.x * s.y * s.z < 0)
    1265     {
    1266         for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3)
    1267         {
    1268             uint16_t tmp = m_indices[i + 0];
    1269             m_indices[i + 0] = m_indices[i + 1];
    1270             m_indices[i + 1] = tmp;
    1271         }
    1272     }
    1273 }
    1274 
    1275 //-----------------------------------------------------------------------------
    1276 void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
    1277 void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
    1278 void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }
    1279 
    1280 //-----------------------------------------------------------------------------
    1281 void EasyMesh::DupAndScale(vec3 const &s, bool open_brace)
    1282 {
    1283     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1284     {
    1285         BD()->CmdStack().AddCmd(EasyMeshCmdType::DupAndScale);
    1286         BD()->CmdStack() << s << open_brace;
    1287         return;
    1288     }
    1289 
    1290     int vlen = m_vert.Count() - m_cursors.Last().m1;
    1291     int tlen = m_indices.Count() - m_cursors.Last().m2;
    1292 
    1293     for (int i = 0; i < vlen; i++)
    1294         AddDuplicateVertex(m_cursors.Last().m1++);
    1295 
    1296     for (int i = 0; i < tlen; i++)
    1297         m_indices << m_indices[m_cursors.Last().m2++] + vlen;
    1298 
    1299     Scale(s);
    1300 
    1301     m_cursors.Last().m1 -= vlen;
    1302     m_cursors.Last().m2 -= tlen;
    1303 
    1304     if (open_brace)
    1305     {
    1306         OpenBrace();
    1307 
    1308         m_cursors.Last().m1 -= vlen;
    1309         m_cursors.Last().m2 -= tlen;
    1310     }
    1311 }
    131222
    131323//-----------------------------------------------------------------------------
     
    133242    vec2 Save_texcoord_scale = BD()->TexCoordScale();
    133343
    1334     int vbase = m_vert.Count();
     44    int vbase = (int)m_vert.Count();
    133545
    133646    mat3 rotmat = mat3::rotate(360.0f / (float)nsides, 0.f, 1.f, 0.f);
     
    135666        /* FIXME: normals should be flipped in two-sided mode, but that
    135767         * means duplicating the vertices again... */
    1358         AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1359         AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
     68        InternalAddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
     69        InternalAddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    136070
    136171        p1 = rotmat * p1; uv1 += uvadd;
     
    136474        if (!smooth)
    136575        {
    1366             AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1367             AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
     76            InternalAddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
     77            InternalAddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    136878        }
    136979
     
    137686        {
    137787            int j = (i + 1) % nsides;
    1378             AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
     88            InternalAddQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
    137989            if (dualside)
    1380                 AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
     90                InternalAddQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
    138191        }
    138292        else
    138393        {
    1384             AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
     94            InternalAddQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
    138595            if (dualside)
    1386                 AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
     96                InternalAddQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
    138797        }
    138898
     
    1431141    float r = d * .5f;
    1432142
    1433     int ibase = m_indices.Count();
     143    int ibase = (int)m_indices.Count();
    1434144
    1435145    array<vec3> vertices;
     
    1545255                    {
    1546256                        int rid[] = { id[k + l], id[(k + 1) % 3 + l], id[(k + 2) % 3 + l] };
    1547                         AddVertex(p[rid[0]]);
     257                        InternalAddVertex(p[rid[0]]);
    1548258                        vec2 new_uv;
    1549259                        if (uv[rid[0]].x < .0f)
     
    1554264                        SetCurVertTexCoord2(vec2(0.f, 1.f) - new_uv);
    1555265                    }
    1556                     AppendTriangle(0, 2, 1, m_vert.Count() - 3);
     266                    InternalAddTriangle(0, 2, 1, (int)m_vert.Count() - 3);
    1557267                }
    1558268            }
     
    1568278    }
    1569279
    1570     ComputeNormals(ibase, m_indices.Count() - ibase);
     280    ComputeNormals(ibase, (int)m_indices.Count() - ibase);
    1571281}
    1572282
     
    1585295    float r2 = d2 * .5f;
    1586296
    1587     int ibase = m_indices.Count();
     297    int ibase = (int)m_indices.Count();
    1588298    int nidiv = ndivisions; /* Cross-section */
    1589299    int njdiv = ndivisions; /* Full circumference */
     
    1611321            float z2 = z * ca + x * sa;
    1612322
    1613             AddVertex(vec3(x2, y, z2));
     323            InternalAddVertex(vec3(x2, y, z2));
    1614324            SetCurVertTexCoord(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1615325            SetCurVertTexCoord2(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1616326        }
    1617327
    1618         AppendTriangle(0, 2, 3, m_vert.Count() - 4);
    1619         AppendTriangle(0, 3, 1, m_vert.Count() - 4);
    1620     }
    1621 
    1622     ComputeNormals(ibase, m_indices.Count() - ibase);
     328        InternalAddTriangle(0, 2, 3, (int)m_vert.Count() - 4);
     329        InternalAddTriangle(0, 3, 1, (int)m_vert.Count() - 4);
     330    }
     331
     332    ComputeNormals(ibase, (int)m_indices.Count() - ibase);
    1623333}
    1624334
     
    1657367    }
    1658368
    1659     int vbase = m_vert.Count();
    1660     int ibase = m_indices.Count();
     369    int vbase = (int)m_vert.Count();
     370    int ibase = (int)m_indices.Count();
    1661371
    1662372    vec3 d = size * 0.5f;
     
    1672382    //--
    1673383    MeshFaceType mft = MeshFaceType::BoxFront;
    1674     AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
     384    InternalAddVertex(vec3(-d.x, -d.y, -d.z - chamf));
    1675385    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1676386    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1677387    //--
    1678     AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
     388    InternalAddVertex(vec3(-d.x, +d.y, -d.z - chamf));
    1679389    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1680390    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1681391    //--
    1682     AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
     392    InternalAddVertex(vec3(+d.x, +d.y, -d.z - chamf));
    1683393    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1684394    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1685395    //--
    1686     AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
     396    InternalAddVertex(vec3(+d.x, -d.y, -d.z - chamf));
    1687397    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1688398    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
     
    1690400    //--
    1691401    mft = MeshFaceType::BoxLeft;
    1692     AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
     402    InternalAddVertex(vec3(-d.x - chamf, -d.y, +d.z));
    1693403    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1694404    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1695405    //--
    1696     AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
     406    InternalAddVertex(vec3(-d.x - chamf, +d.y, +d.z));
    1697407    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1698408    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1699409    //--
    1700     AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
     410    InternalAddVertex(vec3(-d.x - chamf, +d.y, -d.z));
    1701411    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1702412    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1703413    //--
    1704     AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
     414    InternalAddVertex(vec3(-d.x - chamf, -d.y, -d.z));
    1705415    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1706416    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
     
    1708418    //--
    1709419    mft = MeshFaceType::BoxBack;
    1710     AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
     420    InternalAddVertex(vec3(+d.x, -d.y, +d.z + chamf));
    1711421    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1712422    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1713423    //--
    1714     AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
     424    InternalAddVertex(vec3(+d.x, +d.y, +d.z + chamf));
    1715425    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1716426    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1717427    //--
    1718     AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
     428    InternalAddVertex(vec3(-d.x, +d.y, +d.z + chamf));
    1719429    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1720430    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1721431    //--
    1722     AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
     432    InternalAddVertex(vec3(-d.x, -d.y, +d.z + chamf));
    1723433    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1724434    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
     
    1726436    //--
    1727437    mft = MeshFaceType::BoxRight;
    1728     AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
     438    InternalAddVertex(vec3(+d.x + chamf, -d.y, -d.z));
    1729439    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1730440    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1731441    //--
    1732     AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
     442    InternalAddVertex(vec3(+d.x + chamf, +d.y, -d.z));
    1733443    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1734444    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1735445    //--
    1736     AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
     446    InternalAddVertex(vec3(+d.x + chamf, +d.y, +d.z));
    1737447    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1738448    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1739449    //--
    1740     AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
     450    InternalAddVertex(vec3(+d.x + chamf, -d.y, +d.z));
    1741451    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1742452    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
     
    1746456    //--
    1747457    mft = MeshFaceType::BoxBottom;
    1748     AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
     458    InternalAddVertex(vec3(-d.x, -d.y - chamf, +d.z));
    1749459    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1750460    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1751461    //--
    1752     AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
     462    InternalAddVertex(vec3(-d.x, -d.y - chamf, -d.z));
    1753463    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1754464    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1755465    //--
    1756     AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
     466    InternalAddVertex(vec3(+d.x, -d.y - chamf, -d.z));
    1757467    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1758468    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1759469    //--
    1760     AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
     470    InternalAddVertex(vec3(+d.x, -d.y - chamf, +d.z));
    1761471    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1762472    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
     
    1766476    //--
    1767477    mft = MeshFaceType::BoxTop;
    1768     AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
     478    InternalAddVertex(vec3(-d.x, +d.y + chamf, -d.z));
    1769479    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1770480    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1771481    //--
    1772     AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
     482    InternalAddVertex(vec3(-d.x, +d.y + chamf, +d.z));
    1773483    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1774484    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1775485    //--
    1776     AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
     486    InternalAddVertex(vec3(+d.x, +d.y + chamf, +d.z));
    1777487    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1778488    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1779489    //--
    1780     AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
     490    InternalAddVertex(vec3(+d.x, +d.y + chamf, -d.z));
    1781491    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1782492    SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1783493
    1784     ComputeNormals(ibase, m_indices.Count() - ibase);
    1785     ibase = m_indices.Count();
     494    ComputeNormals(ibase, (int)m_indices.Count() - ibase);
     495    ibase = (int)m_indices.Count();
    1786496
    1787497    //Build the box at the end : The 6 quads on each side of the box.
    1788498    for (int i = 0; i < 24; i += 4)
    1789         AppendQuad(i, i + 1, i + 2, i + 3, vbase);
     499        InternalAddQuad(i, i + 1, i + 2, i + 3, vbase);
    1790500
    1791501    /* The 8 quads at each edge of the box */
     
    1802512        {
    1803513            if (smooth)
    1804                 AppendQuad(quadlist[i],     quadlist[i + 1],
     514                InternalAddQuad(quadlist[i],     quadlist[i + 1],
    1805515                           quadlist[i + 2], quadlist[i + 3], vbase);
    1806516            else
    1807                 AppendQuadDuplicateVerts(quadlist[i],     quadlist[i + 1],
     517                InternalAddQuadDupVerts(quadlist[i],     quadlist[i + 1],
    1808518                                         quadlist[i + 2], quadlist[i + 3], vbase);
    1809519        }
     
    1822532        {
    1823533            if (smooth)
    1824                 AppendTriangle(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
     534                InternalAddTriangle(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1825535            else
    1826                 AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
     536                InternalAddTriangleDupVerts(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1827537        }
    1828538    }
    1829539
    1830540    if (!smooth)
    1831         ComputeNormals(ibase, m_indices.Count() - ibase);
     541        ComputeNormals(ibase, (int)m_indices.Count() - ibase);
    1832542}
    1833543
     
    1851561
    1852562    //TODO: It would probably be good to think of another way of UV painting this, like "branch repeating"
    1853     int vbase = m_vert.Count();
     563    int vbase = (int)m_vert.Count();
    1854564    float maxr = max(r1, r2);
    1855565
    1856     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
     566    InternalAddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1857567
    1858568    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
     
    1866576    for (int i = 0; i < nbranches; i++)
    1867577    {
    1868         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
     578        InternalAddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1869579        if (fade2)
    1870580            SetCurVertColor(BD()->ColorB());
    1871581
    1872         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
     582        InternalAddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1873583        if (fade)
    1874584            SetCurVertColor(BD()->ColorB());
    1875585
    1876586        //Append quad at the end
    1877         AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches), vbase);
     587        InternalAddQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches), vbase);
    1878588
    1879589        p1 = rotmat * p1; uv1 = rotmat * uv1;
     
    1903613    float extrar = extrad * .5f;
    1904614
    1905     int vbase = m_vert.Count();
    1906     float maxr = (float)max(max(r1, r2), max(r1 + extrar, r2 + extrar));
    1907 
    1908     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
     615    int vbase = (int)m_vert.Count();
     616    float maxr = lol::max(lol::max(r1, r2), lol::max(r1 + extrar, r2 + extrar));
     617
     618    InternalAddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1909619
    1910620    mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
     
    1922632    for (int i = 0; i < nbranches; i++)
    1923633    {
    1924         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1925         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1926         AddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1927         AddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
     634        InternalAddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
     635        InternalAddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
     636        InternalAddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
     637        InternalAddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1928638
    1929639        int j = (i + 1) % nbranches;
    1930640        //
    1931         AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
    1932         AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
    1933         AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
     641        InternalAddQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
     642        InternalAddQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
     643        InternalAddQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
    1934644
    1935645        p1 = rotmat * p1; uv1 = rotmat * uv1;
     
    1956666    float r = d * .5f;
    1957667
    1958     int vbase = m_vert.Count();
    1959 
    1960     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
     668    int vbase = (int)m_vert.Count();
     669
     670    InternalAddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1961671
    1962672    mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
     
    1966676    for (int i = 0; i < nsides; i++)
    1967677    {
    1968         AddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f));
     678        InternalAddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f));
    1969679        if (fade)
    1970680            SetCurVertColor(BD()->ColorB());
    1971         AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
     681        InternalAddTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
    1972682        p1 = rotmat * p1;
    1973683        uv = rotmat * uv;
     
    1991701    vec3 p(0.f, 0.f, size);
    1992702
    1993     AddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f));
     703    InternalAddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f));
    1994704    p = m * p;
    1995     AddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f));
     705    InternalAddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f));
    1996706    if (fade)
    1997707        SetCurVertColor(BD()->ColorB());
    1998708    p = m * p;
    1999     AddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f));
     709    InternalAddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f));
    2000710    if (fade)
    2001711        SetCurVertColor(BD()->ColorB());
    2002712
    2003     AppendTriangle(0, 1, 2, m_vert.Count() - 3);
     713    InternalAddTriangle(0, 1, 2, (int)m_vert.Count() - 3);
    2004714}
    2005715
     
    2024734
    2025735    //--
    2026     AddVertex(vec3(p2.x, z, -p1.y));
     736    InternalAddVertex(vec3(p2.x, z, -p1.y));
    2027737    TexCoordPos br = TexCoordPos::BR;
    2028738    SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    2029739    SetCurVertTexCoord2(BD()->TexCoord2(mt, br, mft));
    2030740    //--
    2031     AddVertex(vec3(p2.x, z, -p2.y));
     741    InternalAddVertex(vec3(p2.x, z, -p2.y));
    2032742    TexCoordPos bl = TexCoordPos::BL;
    2033743    SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    2034744    SetCurVertTexCoord2(BD()->TexCoord2(mt, bl, mft));
    2035745    //--
    2036     AddVertex(vec3(p1.x, z, -p2.y));
     746    InternalAddVertex(vec3(p1.x, z, -p2.y));
    2037747    TexCoordPos tl = TexCoordPos::TL;
    2038748    SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
     
    2040750    if (fade) SetCurVertColor(BD()->ColorB());
    2041751    //--
    2042     AddVertex(vec3(p1.x, z, -p1.y));
     752    InternalAddVertex(vec3(p1.x, z, -p1.y));
    2043753    TexCoordPos tr = TexCoordPos::TR;
    2044754    SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
     
    2046756    if (fade) SetCurVertColor(BD()->ColorB());
    2047757
    2048     AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
    2049     ComputeNormals(m_indices.Count() - 6, 6);
     758    InternalAddQuad(0, 1, 2, 3, (int)m_vert.Count() - 4);
     759    ComputeNormals((int)m_indices.Count() - 6, 6);
    2050760}
    2051761
     
    2074784    float r22 = d22 * .5f;
    2075785
    2076     int ibase = m_indices.Count();
    2077     int vbase = m_vert.Count();
     786    int ibase = (int)m_indices.Count();
     787    int vbase = (int)m_vert.Count();
    2078788
    2079789    /* FIXME: enforce this some other way */
     
    2272982            int d = n / 3;
    2273983            int e = d % 6;
    2274             AddVertex(p[d]);
     984            InternalAddVertex(p[d]);
    2275985            if (n % 3 == 0) //Top-Bottom logic
    2276986            {
     
    23181028        int l = -4;
    23191029        while ((l += 4) < 48)
    2320             AppendQuad(q[l + 0] + m[l + 0] * 3 + a[l + 0],
     1030            InternalAddQuad(q[l + 0] + m[l + 0] * 3 + a[l + 0],
    23211031                       q[l + 1] + m[l + 1] * 3 + a[l + 1],
    23221032                       q[l + 2] + m[l + 2] * 3 + a[l + 2],
     
    23251035    }
    23261036
    2327     ComputeNormals(ibase, m_indices.Count() - ibase);
    2328 }
    2329 
    2330 //-----------------------------------------------------------------------------
    2331 void EasyMesh::Chamfer(float f)
    2332 {
    2333     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2334     {
    2335         BD()->CmdStack().AddCmd(EasyMeshCmdType::Chamfer);
    2336         BD()->CmdStack() << f;
    2337         return;
    2338     }
    2339 
    2340     int vlen = m_vert.Count() - m_cursors.Last().m1;
    2341     int ilen = m_indices.Count() - m_cursors.Last().m2;
    2342 
    2343     /* Step 1: enumerate all faces. This is done by merging triangles
    2344      * that are coplanar and share an edge. */
    2345     int *triangle_classes = new int[ilen / 3];
    2346     for (int i = 0; i < ilen / 3; i++)
    2347         triangle_classes[i] = -1;
    2348 
    2349     for (int i = 0; i < ilen / 3; i++)
    2350     {
    2351 
    2352     }
    2353 
    2354     /* Fun shit: reduce all triangles */
    2355     int *vertices = new int[vlen];
    2356     memset(vertices, 0, vlen * sizeof(int));
    2357     for (int i = 0; i < ilen; i++)
    2358         vertices[m_indices[i]]++;
    2359 
    2360     for (int i = 0; i < ilen / 3; i++)
    2361 
    2362     {
    2363     #if 0
    2364         if (vertices[m_indices[i * 3]] > 1)
    2365             continue;
    2366         if (vertices[m_indices[i * 3 + 1]] > 1)
    2367             continue;
    2368         if (vertices[m_indices[i * 3 + 2]] > 1)
    2369             continue;
    2370     #endif
    2371 
    2372         vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m_coord +
    2373                                  m_vert[m_indices[i * 3 + 1]].m_coord +
    2374                                  m_vert[m_indices[i * 3 + 2]].m_coord);
    2375         for (int k = 0; k < 3; k++)
    2376         {
    2377             vec3 &p = m_vert[m_indices[i * 3 + k]].m_coord;
    2378             p -= normalize(p - bary) * f;
    2379         }
    2380     }
    2381 }
    2382 
    2383 //-----------------------------------------------------------------------------
    2384 void EasyMesh::SplitTriangles(int pass)
    2385 {
    2386     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2387     {
    2388         BD()->CmdStack().AddCmd(EasyMeshCmdType::SplitTriangles);
    2389         BD()->CmdStack() << pass;
    2390         return;
    2391     }
    2392 
    2393     SplitTriangles(pass, nullptr);
    2394 }
    2395 
    2396 //-----------------------------------------------------------------------------
    2397 void EasyMesh::SplitTriangles(int pass, VertexDictionnary *vert_dict)
    2398 {
    2399     while (pass--)
    2400     {
    2401         int trimax = m_indices.Count();
    2402         for (int i = m_cursors.Last().m2; i < trimax; i += 3)
    2403         {
    2404             int vbase = m_vert.Count();
    2405             int j = -1;
    2406             while (++j < 3)
    2407             {
    2408                 AddLerpVertex(m_indices[i + j], m_indices[i + (j + 1) % 3], .5f);
    2409                 if (vert_dict)
    2410                     vert_dict->AddVertex(vbase + j, m_vert[vbase + j].m_coord);
    2411             }
    2412             //Add new triangles
    2413             AppendTriangle(vbase, m_indices[i + 1], vbase + 1, 0);
    2414             AppendTriangle(vbase + 2, vbase + 1, m_indices[i + 2], 0);
    2415             AppendTriangle(vbase, vbase + 1, vbase + 2, 0);
    2416             //Change current triangle
    2417             m_indices[i + 1] = vbase;
    2418             m_indices[i + 2] = vbase + 2;
    2419         }
    2420     }
    2421     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    2422 }
    2423 
    2424 //-----------------------------------------------------------------------------
    2425 //TODO : Add an half-edges implementation to refine smooth.
    2426 //TODO : Smooth should only use connected vertices that are on edges of the mesh (See box).
    2427 void EasyMesh::SmoothMesh(int main_pass, int split_per_main_pass, int smooth_per_main_pass)
    2428 {
    2429     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2430     {
    2431         BD()->CmdStack().AddCmd(EasyMeshCmdType::SmoothMesh);
    2432         BD()->CmdStack() << main_pass << split_per_main_pass << smooth_per_main_pass;
    2433         return;
    2434     }
    2435 
    2436     VertexDictionnary vert_dict;
    2437     array<vec3> smooth_buf[2];
    2438     array<int> master_list;
    2439     array<int> matching_ids;
    2440     array<int> connected_vert;
    2441     int smbuf = 0;
    2442 
    2443     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    2444         vert_dict.AddVertex(i, m_vert[i].m_coord);
    2445 
    2446     while (main_pass--)
    2447     {
    2448         int split_pass = split_per_main_pass;
    2449         int smooth_pass = smooth_per_main_pass;
    2450 
    2451         SplitTriangles(split_pass, &vert_dict);
    2452 
    2453         matching_ids.Reserve(m_vert.Count() - m_cursors.Last().m1);
    2454         connected_vert.Reserve(m_vert.Count() - m_cursors.Last().m1);
    2455         smooth_buf[0].Resize(m_vert.Count() - m_cursors.Last().m1);
    2456         smooth_buf[1].Resize(m_vert.Count() - m_cursors.Last().m1);
    2457 
    2458         for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    2459             smooth_buf[smbuf][i - m_cursors.Last().m1] = m_vert[i].m_coord;
    2460 
    2461         while (smooth_pass--)
    2462         {
    2463             master_list.Empty();
    2464             if (vert_dict.GetMasterList(master_list))
    2465             {
    2466                 for (int i = 0; i < master_list.Count(); i++)
    2467                 {
    2468                     connected_vert.Empty();
    2469                     if (vert_dict.FindConnectedVertices(master_list[i], m_indices, m_cursors.Last().m2, connected_vert))
    2470                     {
    2471                         //Calculate vertices sum
    2472                         vec3 vert_sum = vec3(.0f);
    2473                         for (int j = 0; j < connected_vert.Count(); j++)
    2474                             vert_sum += smooth_buf[smbuf][connected_vert[j] - m_cursors.Last().m1];
    2475 
    2476                         //Calculate new master vertex
    2477                         float n = (float)connected_vert.Count();
    2478                         //b(n) = 5/4 - pow(3 + 2 * cos(2.f * F_PI / n), 2) / 32
    2479                         float beta = 3.f + 2.f * cos(2.f * F_PI / n);
    2480                         beta = 5.f / 4.f - beta * beta / 32.f;
    2481                         //a(n) = n * (1 - b(n)) / b(n)
    2482                         float alpha = (n * (1 - beta)) / beta;
    2483                         //V = (a(n) * v + v1 + ... + vn) / (a(n) + n)
    2484                         vec3 new_vert = (alpha * smooth_buf[smbuf][master_list[i] - m_cursors.Last().m1] + vert_sum) / (alpha + n);
    2485 
    2486                         //Set all matching vertices to new value
    2487                         matching_ids.Empty();
    2488                         matching_ids << master_list[i];
    2489                         vert_dict.FindMatchingVertices(master_list[i], matching_ids);
    2490                         for (int j = 0; j < matching_ids.Count(); j++)
    2491                             smooth_buf[1 - smbuf][matching_ids[j] - m_cursors.Last().m1] = new_vert;
    2492                     }
    2493                 }
    2494             }
    2495             smbuf = 1 - smbuf;
    2496         }
    2497 
    2498         for (int i = 0; i < smooth_buf[smbuf].Count(); i++)
    2499             m_vert[i + m_cursors.Last().m1].m_coord = smooth_buf[smbuf][i];
    2500     }
     1037    ComputeNormals(ibase, (int)m_indices.Count() - ibase);
    25011038}
    25021039
  • trunk/src/easymesh/easymeshrender.cpp

    r3604 r3843  
    157157    /* FIXME: GetUniform("blabla") is costly */
    158158    for (int i = 0; i < lights.Count(); ++i)
    159         light_data << vec4(lights[i]->GetPosition(), lights[i]->GetType()) << lights[i]->GetColor();
     159        light_data << vec4(lights[i]->GetPosition(), (float)lights[i]->GetType()) << lights[i]->GetColor();
    160160    while (light_data.Count() < LOL_MAX_LIGHT_COUNT)
    161161        light_data << vec4::zero << vec4::zero;
     
    234234        m_ibo->Unlock();
    235235
    236         m_indexcount = indexlist.Count();
     236        m_indexcount = (int)indexlist.Count();
    237237    }
    238238
     
    240240    if (m_gpudatas.Count() <= gpudata->m_render_mode)
    241241    {
    242         int i = m_gpudatas.Count();
     242        int i = (int)m_gpudatas.Count();
    243243        int max = gpudata->m_render_mode + 1;
    244244        m_gpudatas.Reserve(max);
     
    263263#define COPY_VBO \
    264264    vbo_data = &vertexlist[0]; \
    265     vbo_bytes = vertexlist.Bytes(); \
    266     m_vertexcount = vertexlist.Count(); \
     265    vbo_bytes = (int)vertexlist.Bytes(); \
     266    m_vertexcount = (int)vertexlist.Count(); \
    267267    new_vbo = new VertexBuffer(vbo_bytes); \
    268268    void *mesh = new_vbo->Lock(0, 0); \
  • trunk/src/easymesh/easymeshtransform.cpp

    <
    r3837 r3843  
    22// Lol Engine
    33//
    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>
     4// Copyright: (c) 2010-2015 Sam Hocevar <sam@hocevar.net>
     5//            (c) 2009-2015 Cédric Lecacheur <jordx@free.fr>
     6//            (c) 2009-2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
    77//   This program is free software; you can redistribute it and/or
    88//   modify it under the terms of the Do What The Fuck You Want To
     
    1818#include <lol/engine-internal.h>
    1919
    20 LOLFX_RESOURCE_DECLARE(shiny);
    21 
    2220namespace lol
    2321{
    24 
    25 //-----------------------------------------------------------------------------
    26 EasyMesh::EasyMesh()
    27   : m_build_data(nullptr)
    28 {
    29     m_cursors.Push(0, 0);
    30     m_state = MeshRender::NeedData;
    31 }
    32 
    33 //-----------------------------------------------------------------------------
    34 EasyMesh::EasyMesh(const EasyMesh& em)
    35 {
    36     m_indices = em.m_indices;
    37     m_vert = em.m_vert;
    38     m_cursors = em.m_cursors;
    39     m_build_data = nullptr;
    40     if (em.m_build_data)
    41         m_build_data = new EasyMeshBuildData(*em.m_build_data);
    42     if (m_indices.Count() && m_vert.Count() && m_cursors.Count())
    43         m_state = MeshRender::NeedConvert;
    44     else
    45         m_state = MeshRender::NeedData;
    46 }
    47 
    48 //-----------------------------------------------------------------------------
    49 bool EasyMesh::Compile(char const *command, bool Execute)
    50 {
    51     bool res = false;
    52     // FIXME: make this work again
    53 #if 0
    54     EasyMeshCompiler mc(*this);
    55     BD()->Enable(MeshBuildOperation::CommandRecording);
    56     if ((res = mc.ParseString(command)))
    57     {
    58         BD()->Disable(MeshBuildOperation::CommandRecording);
    59         if (Execute)
    60             ExecuteCmdStack();
    61     }
    62 #endif
    63     return res;
    64 }
    65 
    66 void EasyMesh::MeshConvert()
    67 {
    68     /* Default material */
    69     Shader *shader = Shader::Create(LOLFX_RESOURCE_NAME(shiny));
    70 
    71     /* Push index buffer to GPU */
    72     IndexBuffer *ibo = new IndexBuffer(m_indices.Count() * sizeof(uint16_t));
    73     uint16_t *indices = (uint16_t *)ibo->Lock(0, 0);
    74     for (int i = 0; i < m_indices.Count(); ++i)
    75         indices[i] = m_indices[i];
    76     ibo->Unlock();
    77 
    78     /* Push vertex buffer to GPU */
    79     struct Vertex
    80     {
    81         vec3 pos, normal;
    82         u8vec4 color;
    83         vec4 texcoord;
    84     };
    85 
    86     VertexDeclaration *vdecl = new VertexDeclaration(
    87         VertexStream<vec3, vec3, u8vec4, vec4>(VertexUsage::Position,
    88                                                VertexUsage::Normal,
    89                                                VertexUsage::Color,
    90                                                VertexUsage::TexCoord));
    91 
    92     VertexBuffer *vbo = new VertexBuffer(m_vert.Count() * sizeof(Vertex));
    93     Vertex *vert = (Vertex *)vbo->Lock(0, 0);
    94     for (int i = 0; i < m_vert.Count(); ++i)
    95     {
    96         vert[i].pos = m_vert[i].m_coord,
    97         vert[i].normal = m_vert[i].m_normal,
    98         vert[i].color = (u8vec4)(m_vert[i].m_color * 255.f);
    99         vert[i].texcoord = m_vert[i].m_texcoord;
    100     }
    101     vbo->Unlock();
    102 
    103     /* Reference our new data in our submesh */
    104     m_submeshes.Push(new SubMesh(shader, vdecl));
    105     m_submeshes.Last()->SetIndexBuffer(ibo);
    106     m_submeshes.Last()->SetVertexBuffer(0, vbo);
    107 
    108     m_state = MeshRender::CanRender;
    109 }
    110 
    111 //-----------------------------------------------------------------------------
    112 #define EZSET(M0)                                               BD()->CmdStack().GetValue(M0);
    113 #define EZDEF_1(T0)                                             T0 m0; EZSET(m0)
    114 #define EZDEF_2(T0, T1)                                         EZDEF_1(T0) T1 m1; EZSET(m1)
    115 #define EZDEF_3(T0, T1, T2)                                     EZDEF_2(T0, T1) T2 m2; EZSET(m2)
    116 #define EZDEF_4(T0, T1, T2, T3)                                 EZDEF_3(T0, T1, T2) T3 m3; EZSET(m3)
    117 #define EZDEF_5(T0, T1, T2, T3, T4)                             EZDEF_4(T0, T1, T2, T3) T4 m4; EZSET(m4)
    118 #define EZDEF_6(T0, T1, T2, T3, T4, T5)                         EZDEF_5(T0, T1, T2, T3, T4) T5 m5; EZSET(m5)
    119 #define EZDEF_7(T0, T1, T2, T3, T4, T5, T6)                     EZDEF_6(T0, T1, T2, T3, T4, T5) T6 m6; EZSET(m6)
    120 #define EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7)                 EZDEF_7(T0, T1, T2, T3, T4, T5, T6) T7 m7; EZSET(m7)
    121 #define EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8)             EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7) T8 m8; EZSET(m8)
    122 #define EZDEF_10(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)        EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9 m9; EZSET(m9)
    123 
    124 //----
    125 #define EZCALL_1(F)                                             F();
    126 #define EZCALL_2(F, T0)                                         EZDEF_1(T0) F(m0);
    127 #define EZCALL_3(F, T0, T1)                                     EZDEF_2(T0, T1) F(m0, m1);
    128 #define EZCALL_4(F, T0, T1, T2)                                 EZDEF_3(T0, T1, T2) F(m0, m1, m2);
    129 #define EZCALL_5(F, T0, T1, T2, T3)                             EZDEF_4(T0, T1, T2, T3) F(m0, m1, m2, m3);
    130 #define EZCALL_6(F, T0, T1, T2, T3, T4)                         EZDEF_5(T0, T1, T2, T3, T4) F(m0, m1, m2, m3, m4);
    131 #define EZCALL_7(F, T0, T1, T2, T3, T4, T5)                     EZDEF_6(T0, T1, T2, T3, T4, T5) F(m0, m1, m2, m3, m4, m5);
    132 #define EZCALL_8(F, T0, T1, T2, T3, T4, T5, T6)                 EZDEF_7(T0, T1, T2, T3, T4, T5, T6) F(m0, m1, m2, m3, m4, m5, m6);
    133 #define EZCALL_9(F, T0, T1, T2, T3, T4, T5, T6, T7)             EZDEF_8(T0, T1, T2, T3, T4, T5, T6, T7) F(m0, m1, m2, m3, m4, m5, m6, m7);
    134 #define EZCALL_10(F, T0, T1, T2, T3, T4, T5, T6, T7, T8)        EZDEF_9(T0, T1, T2, T3, T4, T5, T6, T7, T8) F(m0, m1, m2, m3, m4, m5, m6, m7, m8);
    135 #define EZCALL_11(F, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)    EZDEF_10(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) F(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9);
    136 
    137 //----
    138 #define EZM_CALL_FUNC(...) \
    139             LOL_CALL(LOL_CAT(EZCALL_, LOL_CALL(LOL_COUNT_TO_12, (__VA_ARGS__))), (__VA_ARGS__))
    140 
    141 //-----------------------------------------------------------------------------
    142 void EasyMesh::ExecuteCmdStack(bool ExecAllStack)
    143 {
    144 #define DO_EXEC_CMD(MESH_CMD, FUNC_PARAMS)  \
    145         case EasyMeshCmdType::MESH_CMD:     \
    146         { EZM_CALL_FUNC FUNC_PARAMS; break; }
    147 
    148     BD()->Enable(MeshBuildOperation::CommandExecution);
    149     if (ExecAllStack)
    150         BD()->Cmdi() = 0;
    151 
    152     for (; BD()->Cmdi() < BD()->CmdStack().GetCmdNb() && BD()->CmdExecNb() != 0; ++BD()->Cmdi())
    153     {
    154         if (BD()->CmdExecNb() > 0)
    155             --BD()->CmdExecNb();
    156 
    157         switch (BD()->CmdStack().GetCmd(BD()->Cmdi()))
    158         {
    159             DO_EXEC_CMD(MeshCsg,                (MeshCsg, CSGUsage))
    160             DO_EXEC_CMD(LoopStart,              (LoopStart, int))
    161             DO_EXEC_CMD(LoopEnd,                (LoopEnd))
    162             DO_EXEC_CMD(OpenBrace,              (OpenBrace))
    163             DO_EXEC_CMD(CloseBrace,             (CloseBrace))
    164             DO_EXEC_CMD(ScaleWinding,           (ToggleScaleWinding))
    165             DO_EXEC_CMD(QuadWeighting,          (ToggleQuadWeighting))
    166             DO_EXEC_CMD(PostBuildNormal,        (TogglePostBuildNormal))
    167             DO_EXEC_CMD(PreventVertCleanup,     (ToggleVerticeNoCleanup))
    168             DO_EXEC_CMD(VerticesMerge,          (VerticesMerge))
    169             DO_EXEC_CMD(VerticesSeparate,       (VerticesSeparate))
    170             DO_EXEC_CMD(SetColorA,              (SetCurColorA, vec4))
    171             DO_EXEC_CMD(SetColorB,              (SetCurColorB, vec4))
    172             DO_EXEC_CMD(SetVertColor,           (SetVertColor, vec4))
    173             DO_EXEC_CMD(Translate,              (Translate, vec3))
    174             DO_EXEC_CMD(Rotate,                 (Rotate, float, vec3))
    175             DO_EXEC_CMD(RadialJitter,           (RadialJitter, float))
    176             DO_EXEC_CMD(MeshTranform,           (DoMeshTransform, MeshTransform, Axis, Axis, float, float, float, bool))
    177             DO_EXEC_CMD(Scale,                  (Scale, vec3))
    178             DO_EXEC_CMD(DupAndScale,            (DupAndScale, vec3, bool))
    179             DO_EXEC_CMD(Chamfer,                (Chamfer, float))
    180             DO_EXEC_CMD(SplitTriangles,         (SplitTriangles, int))
    181             DO_EXEC_CMD(SmoothMesh,             (SmoothMesh, int, int, int))
    182             DO_EXEC_CMD(AppendCylinder,         (AppendCylinder, int, float, float, float, bool, bool, bool))
    183             DO_EXEC_CMD(AppendCapsule,          (AppendCapsule, int, float, float))
    184             DO_EXEC_CMD(AppendTorus,            (AppendTorus, int, float, float))
    185             DO_EXEC_CMD(AppendBox,              (AppendBox, vec3, float, bool))
    186             DO_EXEC_CMD(AppendStar,             (AppendStar, int, float, float, bool, bool))
    187             DO_EXEC_CMD(AppendExpandedStar,     (AppendExpandedStar, int, float, float, float))
    188             DO_EXEC_CMD(AppendDisc,             (AppendDisc, int, float, bool))
    189             DO_EXEC_CMD(AppendSimpleTriangle,   (AppendSimpleTriangle, float, bool))
    190             DO_EXEC_CMD(AppendSimpleQuad,       (AppendSimpleQuad, vec2, vec2, float, bool))
    191             DO_EXEC_CMD(AppendCog,              (AppendCog, int, float, float, float, float, float, float, float, float, bool))
    192             default:
    193                 ASSERT(0, "Unknown command pseudo bytecode");
    194         }
    195     }
    196     BD()->Disable(MeshBuildOperation::CommandExecution);
    197 
    198     if (!BD()->IsEnabled(MeshBuildOperation::PreventVertCleanup))
    199         VerticesCleanup();
    200 
    201     if (BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
    202         ComputeNormals(0, m_indices.Count());
    203 
    204     BD()->Disable(MeshBuildOperation::PostBuildComputeNormals);
    205     BD()->Disable(MeshBuildOperation::PreventVertCleanup);
    206 
    207     if (BD()->CmdExecNb() > 0)
    208         BD()->CmdExecNb() = -1;
    209 }
    210 
    211 //-----------------------------------------------------------------------------
    212 void EasyMesh::LoopStart(int loopnb)
    213 {
    214     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    215     {
    216         BD()->CmdStack().AddCmd(EasyMeshCmdType::LoopStart);
    217         BD()->CmdStack() << loopnb;
    218         return;
    219     }
    220     //Loop is only available when executing a command recording
    221     else if (BD()->IsEnabled(MeshBuildOperation::CommandExecution))
    222     {
    223         //Only register if we're not the current loop command
    224         if (!BD()->LoopStack().Count() || BD()->LoopStack().Last().m1 != BD()->Cmdi())
    225             BD()->LoopStack().Push(BD()->Cmdi(), loopnb);
    226     }
    227 }
    228 
    229 //-----------------------------------------------------------------------------
    230 void EasyMesh::LoopEnd()
    231 {
    232     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    233     {
    234         BD()->CmdStack().AddCmd(EasyMeshCmdType::LoopEnd);
    235         return;
    236     }
    237     //Loop is only available when executing a command recording
    238     else if (BD()->IsEnabled(MeshBuildOperation::CommandExecution))
    239     {
    240         //Only register if we're not the current loop command
    241         if (BD()->LoopStack().Count())
    242         {
    243             BD()->LoopStack().Last().m2--;
    244             if (BD()->LoopStack().Last().m2 > 0)
    245                 BD()->Cmdi() = BD()->LoopStack().Last().m1 - 1;
    246             else
    247                 BD()->LoopStack().Pop();
    248         }
    249     }
    250 }
    251 
    252 //-----------------------------------------------------------------------------
    253 void EasyMesh::OpenBrace()
    254 {
    255     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    256     {
    257         BD()->CmdStack().AddCmd(EasyMeshCmdType::OpenBrace);
    258         return;
    259     }
    260 
    261     m_cursors.Push(m_vert.Count(), m_indices.Count());
    262 }
    263 
    264 //-----------------------------------------------------------------------------
    265 void EasyMesh::CloseBrace()
    266 {
    267     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    268     {
    269         BD()->CmdStack().AddCmd(EasyMeshCmdType::CloseBrace);
    270         return;
    271     }
    272 
    273     m_cursors.Pop();
    274 }
    275 
    276 //-----------------------------------------------------------------------------
    277 bool EasyMesh::SetRender(bool should_render)
    278 {
    279     if (m_state == MeshRender::CanRender)
    280     {
    281         if (!should_render)
    282             m_state = MeshRender::IgnoreRender;
    283         return true;
    284     }
    285     else if (m_state == MeshRender::IgnoreRender)
    286     {
    287         if (should_render)
    288             m_state = MeshRender::CanRender;
    289         return true;
    290     }
    291     return false;
    292 }
    293 
    294 //-------------------
    295 // "Collisions" functions
    296 //-------------------
    297 
    298 //-----------------------------------------------------------------------------
    299 void EasyMesh::MeshCsg(CSGUsage csg_operation)
    300 {
    301     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    302     {
    303         BD()->CmdStack().AddCmd(EasyMeshCmdType::MeshCsg);
    304         BD()->CmdStack() << csg_operation;
    305         return;
    306     }
    307 
    308     //A vertex dictionnary for vertices on the same spot.
    309     array< int, int > vertex_dict;
    310     //This list keeps track of the triangle that will need deletion at the end.
    311     array< int > triangle_to_kill;
    312     //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>>
    313     array< int, array< vec3, vec3, vec3 > > triangle_isec;
    314     //keep a track of the intersection point on the triangle. <pos, side_id>
    315     array< vec3, int > triangle_vertex;
    316     for (int k = 0; k < 10; k++)
    317         triangle_vertex.Push(vec3(.0f), 0);
    318 
    319     //bsp infos
    320     CsgBsp mesh_bsp_0;
    321     CsgBsp mesh_bsp_1;
    322 
    323     if (m_cursors.Count() == 0)
    324         return;
    325 
    326     //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]"
    327     int cursor_start = (m_cursors.Count() < 2)?(0):(m_cursors[(m_cursors.Count() - 2)].m2);
    328     for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    329     {
    330         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    331         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count());
    332         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1);
    333         for (int i = start_point; i < end_point; i += 3)
    334             mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord,
    335                                           m_vert[m_indices[i + 1]].m_coord,
    336                                           m_vert[m_indices[i + 2]].m_coord);
    337     }
    338 
    339     //BSP Usage : let's crunch all triangles on the correct BSP
    340     int indices_count = m_indices.Count();
    341     for (int mesh_id = 0; mesh_id < 2; mesh_id++)
    342     {
    343         int start_point     = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2);
    344         int end_point       = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count);
    345         CsgBsp &mesh_bsp  = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0);
    346         array< vec3, int, int, float > vert_list;
    347         array< int, int, int, int > tri_list;
    348         vec3 n0(.0f); vec3 n1(.0f);
    349         vec4 c0(.0f); vec4 c1(.0f);
    350 
    351         //Reserve some memory
    352         vert_list.Reserve(3);
    353         tri_list.Reserve(3);
    354 
    355         for (int i = start_point; i < end_point; i += 3)
    356         {
    357             int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord,
    358                                                      m_vert[m_indices[i + 1]].m_coord,
    359                                                      m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list);
    360             int tri_base_idx = m_indices.Count();
    361 
    362             //one split has been done, we need to had the new vertices & the new triangles.
    363             if (Result == 1)
    364             {
    365                 triangle_to_kill.Push(i);
    366 #if 1
    367                 int base_idx = m_vert.Count();
    368                 for (int k = 3; k < vert_list.Count(); k++)
    369                 {
    370                     int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3);
    371                     int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3);
    372 
    373                     AddVertex(vert_list[k].m1);
    374 
    375                     //Normal : bad calculations there.
    376                     n0 = m_vert[P0].m_normal;
    377                     n1 = m_vert[P1].m_normal;
    378                     SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4));
    379 
    380 #if 1
    381                     //Color
    382                     c0 = m_vert[P0].m_color;
    383                     c1 = m_vert[P1].m_color;
    384                     vec4 res = c0 + ((c1 - c0) * vert_list[k].m4);
    385                     SetCurVertColor(res);
    386 #else
    387                     if (mesh_id == 0)
    388                         SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f));
    389                     else
    390                         SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f));
    391 #endif
    392                 }
    393                 for (int k = 0; k < tri_list.Count(); k++)
    394                 {
    395                     int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3));
    396                     int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3));
    397                     int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3));
    398                     AppendTriangle(P0, P1, P2, 0);
    399                 }
    400 #endif
    401             }
    402 #if 1
    403             //Main case
    404             if (Result >= 0)
    405             {
    406                 for (int k = 0; k < tri_list.Count(); k++)
    407                 {
    408                     int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3));
    409 
    410                     //Triangle Kill Test
    411                     if (//csgu : CSGUnion() -> m0_Outside + m1_Outside
    412                         (csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) ||
    413                         //csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
    414                         (csg_operation == CSGUsage::Substract &&
    415                             ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) ||
    416                             (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) ||
    417                         //csgs : CsgSubL() -> m0_Outside
    418                         (csg_operation == CSGUsage::SubstractLoss &&
    419                             ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) ||
    420                         //csga : CSGAnd() -> m0_Inside + m1_Inside
    421                         (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT))
    422                     {
    423                         triangle_to_kill.Push(tri_idx);
    424                     }
    425 
    426                     //Triangle Invert Test
    427                     if (//csgs : CsgSub() -> m0_Outside + m1_Inside-inverted
    428                         (csg_operation == CSGUsage::Substract && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) ||
    429                         //csgx : CSGXor() -> m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted
    430                         (csg_operation == CSGUsage::Xor && tri_list[k].m1 == LEAF_BACK))
    431                     {
    432                         //a Xor means we will share vertices with the outside, so duplicate the vertices.
    433                         //TODO : This operation disconnect all triangle, in some cases, not a good thing.
    434                         if (csg_operation == CSGUsage::Xor)
    435                         {
    436                             for (int l = 0; l < 3; l++)
    437                             {
    438                                 AddDuplicateVertex(m_indices[tri_idx + l]);
    439                                 m_indices[tri_idx + l] = m_vert.Count() - 1;
    440                             }
    441                         }
    442                         m_indices[tri_idx + 1] += m_indices[tri_idx + 2];
    443                         m_indices[tri_idx + 2]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    444                         m_indices[tri_idx + 1]  = m_indices[tri_idx + 1] - m_indices[tri_idx + 2];
    445                         ComputeNormals(tri_idx, 3);
    446                     }
    447                 }
    448             }
    449 #endif
    450             vert_list.Empty();
    451             tri_list.Empty();
    452         }
    453     }
    454 
    455     for (int i = 0; i < m_vert.Count(); i++)
    456         if (length(m_vert[i].m_normal) < 1.0f)
    457             i = i;
    458 
    459     int dir = 1;
    460     for (int i = 0; i >= 0 && i < triangle_to_kill.Count() - 1; i += dir)
    461     {
    462         if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0)
    463             dir = 1;
    464         if (triangle_to_kill[i] == triangle_to_kill[i + 1])
    465         {
    466             triangle_to_kill.Remove(i);
    467             dir = -1;
    468         }
    469         if (triangle_to_kill[i] > triangle_to_kill[i + 1])
    470         {
    471             triangle_to_kill[i]     += triangle_to_kill[i + 1];
    472             triangle_to_kill[i + 1]  = triangle_to_kill[i] - triangle_to_kill[i + 1];
    473             triangle_to_kill[i]      = triangle_to_kill[i] - triangle_to_kill[i + 1];
    474             dir = -1;
    475         }
    476         if (i == 0 && dir == -1)
    477             dir = 1;
    478     }
    479     for (int i = triangle_to_kill.Count() - 1; i >= 0; i--)
    480         m_indices.Remove(triangle_to_kill[i], 3);
    481 
    482     m_cursors.Last().m1 = m_vert.Count();
    483     m_cursors.Last().m2 = m_indices.Count();
    484 
    485     VerticesCleanup();
    486     //DONE for the splitting !
    487 }
    488 
    489 //-----------------------------------------------------------------------------
    490 void EasyMesh::ToggleScaleWinding()
    491 {
    492     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    493     {
    494         BD()->CmdStack().AddCmd(EasyMeshCmdType::ScaleWinding);
    495         return;
    496     }
    497 
    498     BD()->Toggle(MeshBuildOperation::ScaleWinding);
    499 }
    500 
    501 //-----------------------------------------------------------------------------
    502 void EasyMesh::ToggleQuadWeighting()
    503 {
    504     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    505     {
    506         BD()->CmdStack().AddCmd(EasyMeshCmdType::QuadWeighting);
    507         return;
    508     }
    509 
    510     BD()->Toggle(MeshBuildOperation::QuadWeighting);
    511 }
    512 
    513 //-----------------------------------------------------------------------------
    514 void EasyMesh::TogglePostBuildNormal()
    515 {
    516     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    517     {
    518         BD()->CmdStack().AddCmd(EasyMeshCmdType::PostBuildNormal);
    519         return;
    520     }
    521 
    522     BD()->Toggle(MeshBuildOperation::PostBuildComputeNormals);
    523 }
    524 
    525 //-----------------------------------------------------------------------------
    526 void EasyMesh::ToggleVerticeNoCleanup()
    527 {
    528     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    529     {
    530         BD()->CmdStack().AddCmd(EasyMeshCmdType::PreventVertCleanup);
    531         return;
    532     }
    533 
    534     BD()->Toggle(MeshBuildOperation::PreventVertCleanup);
    535 }
    536 
    537 //-----------------------------------------------------------------------------
    538 void EasyMesh::SetCurColor(vec4 const &color)
    539 {
    540     SetCurColorA(color);
    541     SetCurColorB(color);
    542 }
    543 
    544 //-----------------------------------------------------------------------------
    545 void EasyMesh::SetCurColorA(vec4 const &color)
    546 {
    547     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    548     {
    549         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetColorA);
    550         BD()->CmdStack() << color;
    551         return;
    552     }
    553 
    554     BD()->ColorA() = color;
    555 }
    556 
    557 //-----------------------------------------------------------------------------
    558 void EasyMesh::SetCurColorB(vec4 const &color)
    559 {
    560     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    561     {
    562         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetColorB);
    563         BD()->CmdStack() << color;
    564         return;
    565     }
    566 
    567     BD()->ColorB() = color;
    568 }
    569 
    570 //-----------------------------------------------------------------------------
    571 void EasyMesh::SetVertColor(vec4 const &color)
    572 {
    573     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    574     {
    575         BD()->CmdStack().AddCmd(EasyMeshCmdType::SetVertColor);
    576         BD()->CmdStack() << color;
    577         return;
    578     }
    579 
    580     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    581         m_vert[i].m_color = color;
    582 }
    583 
    584 //-----------------------------------------------------------------------------
    585 void EasyMesh::AddVertex(vec3 const &coord)
    586 {
    587     m_vert.Push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->ColorA()));
    588     m_state = MeshRender::NeedConvert;
    589 }
    590 
    591 //-----------------------------------------------------------------------------
    592 void EasyMesh::AddDuplicateVertex(int i)
    593 {
    594     m_vert << m_vert[i];
    595     m_state = MeshRender::NeedConvert;
    596 }
    597 
    598 //-----------------------------------------------------------------------------
    599 void EasyMesh::AddLerpVertex(int i, int j, float alpha)
    600 {
    601     AddLerpVertex(m_vert[i], m_vert[j], alpha);
    602 
    603 }
    604 //-----------------------------------------------------------------------------
    605 void EasyMesh::AddLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
    606 {
    607     m_vert.Push(GetLerpVertex(vi, vj, alpha));
    608     m_state = MeshRender::NeedConvert;
    609 }
    610 
    611 //-----------------------------------------------------------------------------
    612 VertexData EasyMesh::GetLerpVertex(int i, int j, float alpha)
    613 {
    614     return GetLerpVertex(m_vert[i], m_vert[j], alpha);
    615 }
    616 
    617 //-----------------------------------------------------------------------------
    618 VertexData EasyMesh::GetLerpVertex(VertexData const &vi, VertexData const &vj, float alpha)
    619 {
    620     return VertexData(
    621         lol::lerp(vi.m_coord,    vj.m_coord,      alpha),
    622         lol::lerp(vi.m_normal,   vj.m_normal,     alpha),
    623         lol::lerp(vi.m_color,    vj.m_color,      alpha),
    624         lol::lerp(vi.m_texcoord, vj.m_texcoord,   alpha),
    625         ((alpha < .5f) ? (vi.m_bone_id) : (vj.m_bone_id)), /* FIXME ? */
    626         lol::lerp(vi.m_bone_weight, vj.m_bone_weight, alpha));
    627 }
    628 
    629 //-----------------------------------------------------------------------------
    630 void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
    631 {
    632     if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) &&
    633         !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting))
    634     {
    635         int i5 = m_vert.Count();
    636         AddLerpVertex(GetLerpVertex(base + i1, base + i3, .5f),
    637                       GetLerpVertex(base + i2, base + i4, .5f), .5f);
    638         m_indices << i1 + base;
    639         m_indices << i2 + base;
    640         m_indices << i5;
    641 
    642         m_indices << i2 + base;
    643         m_indices << i3 + base;
    644         m_indices << i5;
    645 
    646         m_indices << i4 + base;
    647         m_indices << i1 + base;
    648         m_indices << i5;
    649 
    650         m_indices << i5;
    651         m_indices << i3 + base;
    652         m_indices << i4 + base;
    653     }
    654     else
    655     {
    656         m_indices << base + i1;
    657         m_indices << base + i2;
    658         m_indices << base + i3;
    659 
    660         m_indices << base + i4;
    661         m_indices << base + i1;
    662         m_indices << base + i3;
    663     }
    664 }
    665 
    666 //-----------------------------------------------------------------------------
    667 void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
    668 {
    669     int vbase = m_vert.Count();
    670     AddDuplicateVertex(base + i1);
    671     AddDuplicateVertex(base + i2);
    672     AddDuplicateVertex(base + i3);
    673     AddDuplicateVertex(base + i4);
    674 
    675     AppendQuad(0, 1, 2, 3, vbase);
    676 }
    677 
    678 //-----------------------------------------------------------------------------
    679 void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
    680 {
    681     m_indices << base + i1;
    682     m_indices << base + i2;
    683     m_indices << base + i3;
    684 }
    685 
    686 //-----------------------------------------------------------------------------
    687 void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
    688 {
    689     m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
    690     m_indices << m_vert.Count(); AddDuplicateVertex(base + i2);
    691     m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
    692 }
    693 
    694 //-----------------------------------------------------------------------------
    695 void EasyMesh::ComputeNormals(int start, int vcount)
    696 {
    697 
    698     if (BD()->IsEnabled(MeshBuildOperation::CommandExecution) &&
    699         BD()->IsEnabled(MeshBuildOperation::PostBuildComputeNormals))
    700         return;
    701 
    702     array< array<vec3> > normals;
    703     normals.Resize(m_vert.Count());
    704     for (int i = 0; i < vcount; i += 3)
    705     {
    706         vec3 v0 = m_vert[m_indices[start + i + 2]].m_coord
    707                 - m_vert[m_indices[start + i + 0]].m_coord;
    708         vec3 v1 = m_vert[m_indices[start + i + 1]].m_coord
    709                 - m_vert[m_indices[start + i + 0]].m_coord;
    710         vec3 n = normalize(cross(v1, v0));
    711 
    712         for (int j = 0; j < 3; j++)
    713             normals[m_indices[start + i + j]] << n;
    714     }
    715 
    716     for (int i = 0; i < normals.Count(); i++)
    717     {
    718         if (normals[i].Count() > 0)
    719         {
    720             //remove doubles
    721             for (int j = 0; j < normals[i].Count(); ++j)
    722                 for (int k = j + 1; k < normals[i].Count(); ++k)
    723                     if (1.f - dot(normals[i][k], normals[i][j]) < .00001f)
    724                         normals[i].Remove(k--);
    725 
    726             vec3 newv = vec3::zero;
    727             for (int j = 0; j < normals[i].Count(); ++j)
    728                 newv += normals[i][j];
    729             m_vert[i].m_normal = normalize(newv / (float)normals[i].Count());
    730         }
    731     }
    732 }
    733 
    734 //-----------------------------------------------------------------------------
    735 void EasyMesh::VerticesCleanup()
    736 {
    737     array<int> vert_ids;
    738     vert_ids.Resize(m_vert.Count(), 0);
    739 
    740     //1: Remove triangles with two vertices on each other
    741     for (int i = 0; i < m_indices.Count(); i += 3)
    742     {
    743         bool remove = false;
    744         for (int j = 0; !remove && j < 3; ++j)
    745             if (length(m_vert[m_indices[i + j]].m_coord - m_vert[m_indices[i + (j + 1) % 3]].m_coord) < .00001f)
    746                 remove = true;
    747         if (remove)
    748         {
    749             m_indices.RemoveSwap(i, 3);
    750             i -= 3;
    751         }
    752         else
    753         {
    754             //1.5: Mark all used vertices
    755             for (int j = 0; j < 3; ++j)
    756                 vert_ids[m_indices[i + j]] = 1;
    757         }
    758     }
    759 
    760     //2: Remove all unused vertices
    761     array<VertexData> old_vert = m_vert;
    762     int shift = 0;
    763     m_vert.Empty();
    764     for (int i = 0; i < vert_ids.Count(); ++i)
    765     {
    766         //Unused vertex, update the shift quantity instead of keeping it.
    767         if (vert_ids[i] == 0)
    768             shift++;
    769         else
    770             m_vert << old_vert[i];
    771         //Always mark it with the shift quantity
    772         vert_ids[i] = shift;
    773     }
    774 
    775     //3: Update the indices
    776     for (int i = 0; i < m_indices.Count(); ++i)
    777         m_indices[i] -= vert_ids[m_indices[i]];
    778 }
    779 
    780 //-----------------------------------------------------------------------------
    781 void EasyMesh::VerticesMerge()
    782 {
    783     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    784     {
    785         BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesMerge);
    786         return;
    787     }
    788 
    789     //1: Crunch all vertices in the dictionnary
    790     VertexDictionnary vert_dict;
    791     for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
    792         vert_dict.AddVertex(i, m_vert[i].m_coord);
    793 
    794     //2: Update the indices
    795     for (int i = 0; i < m_indices.Count(); ++i)
    796     {
    797         int master = vert_dict.FindVertexMaster(m_indices[i]);
    798         if (master >= 0)
    799             m_indices[i] = master;
    800     }
    801 
    802     //2: Cleanup
    803     VerticesCleanup();
    804 }
    805 
    806 //-----------------------------------------------------------------------------
    807 void EasyMesh::VerticesSeparate()
    808 {
    809     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    810     {
    811         BD()->CmdStack().AddCmd(EasyMeshCmdType::VerticesSeparate);
    812         return;
    813     }
    814 
    815     array< array<int> > new_ids;
    816     array<int> vert_ids;
    817     vert_ids.Resize(m_vert.Count(), 0);
    818 
    819     //1: Mark all used vertices
    820     for (int i = 0; i < m_indices.Count(); ++i)
    821         vert_ids[m_indices[i]]++;
    822 
    823     //2: Update the vertices
    824     int vbase = m_cursors.Last().m1;
    825     int vcount = m_vert.Count();
    826     new_ids.Resize(vcount);
    827     for (int i = vbase; i < vcount; i++)
    828     {
    829         while (vert_ids[i] > 1)
    830         {
    831             //Add duplicate
    832             new_ids[i] << m_vert.Count();
    833             AddDuplicateVertex(i);
    834             vert_ids[i]--;
    835         }
    836     }
    837 
    838     //3: Update the indices
    839     for (int i = 0; i < m_indices.Count(); ++i)
    840     {
    841         if (new_ids[m_indices[i]].Count())
    842         {
    843             int j = new_ids[m_indices[i]].Pop();
    844             m_indices[i] = j;
    845         }
    846     }
    847 
    848     //4: Cleanup
    849     VerticesCleanup();
    850 }
    851 
    852 //-----------------------------------------------------------------------------
    853 void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset)
    854 {
    855     UNUSED(uv_scale, uv_offset);
    856 #if 0
    857     VertexDictionnary vert_dict;
    858     array<int> tri_list;
    859 
    860     tri_list.Reserve(m_indices.Count() - m_cursors.Last().m2);
    861     for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++)
    862     {
    863         vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m_coord);
    864         tri_list << m_indices[i];
    865     }
    866 
    867     //full triangle count
    868     array<int> tri_done;
    869     array<int> tri_check;
    870     int tri_count = (m_indices.Count() - m_cursors.Last().m2) / 3;
    871 
    872     tri_check << tri_list[0];
    873 
    874     while (tri_check.Count())
    875     {
    876         int cur_tri = tri_check[0];
    877         int v[3]   = { tri_list[cur_tri + uv_offset % 3], tri_list[cur_tri + (1 + uv_offset) % 3], tri_list[cur_tri + (2 + uv_offset) % 3] };
    878         vec2 uv[3] = { m_vert[tri_list[cur_tri]].m_texcoord.xy, m_vert[tri_list[cur_tri + 1]].m_texcoord.xy, m_vert[tri_list[cur_tri + 2]].m_texcoord.xy };
    879         for (int j = 0; j < 3; j++)
    880         {
    881             if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3])
    882             {
    883                 uv[0] = vec2(-1.0f);
    884                 uv[1] = vec2(-1.0f);
    885                 uv[2] = vec2(-1.0f);
    886                 break;
    887             }
    888         }
    889         int uv_set = 0;
    890         for (int j = 0; j < 3; j++)
    891             uv_set += (uv[j].x < 0.f)?(0):(1);
    892 
    893         //this case shouldn't happen.
    894         if (uv_set == 1)
    895         {
    896             /*
    897             for (int j = 0; j < 3; j++)
    898             {
    899                 if (uv[j] != vec2(-1.0f))
    900                 {
    901                     uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(m_vert[v[j]].m1 - m_vert[v[(j + 1) % 3]].m1));
    902                     uv_set = 2;
    903                     break;
    904                 }
    905             }
    906             */
    907         }
    908         //No UV is set, let's do the arbitrary set and use the basic method.
    909         if (uv_set == 0)
    910         {
    911             float new_dot = FLT_MAX;
    912             int base_i = 0;
    913             for (int j = 0; j < 3; j++)
    914             {
    915                 float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m_coord - m_vert[v[j]].m_coord),
    916                                         normalize(m_vert[v[(j + 2) % 3]].m_coord - m_vert[v[j]].m_coord)));
    917                 if (tmp_dot < new_dot)
    918                 {
    919                     base_i = j;
    920                     new_dot = tmp_dot;
    921                 }
    922             }
    923             uv[base_i] = vec2(.0f);
    924             uv[(base_i + 1) % 3] = vec2(.0f, uv_scale * length(m_vert[v[base_i]].m_coord - m_vert[v[(base_i + 1) % 3]].m_coord));
    925             uv_set = 2;
    926         }
    927         //2 points have been set, let's figure the third
    928         if (uv_set == 2)
    929         {
    930             {
    931                 //invert values so the two set uv are in [0, 1] slots.
    932                 int new_v[3];
    933                 vec2 new_uv[3];
    934                 bool ignore_set = false;
    935                 if (uv[0].x >= 0.f && uv[1].x < 0.f)
    936                 {
    937                     new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1];
    938                     new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1];
    939                 }
    940                 else if (uv[0].x < 0.f && uv[1].x >= 0.f)
    941                 {
    942                     new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0];
    943                     new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0];
    944                 }
    945                 else
    946                     ignore_set = true;
    947                 if (!ignore_set)
    948                 {
    949                     v[0]  = new_v[0];  v[1]  = new_v[1];  v[2]  = new_v[2];
    950                     uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2];
    951                 }
    952             }
    953 
    954             //Do this to be sure the normal is OK.
    955             ComputeNormals(cur_tri, 3);
    956             vec3 v01 = normalize(m_vert[v[1]].m_coord - m_vert[v[0]].m_coord);
    957             vec3 v02 = m_vert[v[2]].m_coord - m_vert[v[0]].m_coord;
    958             vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m_normal, v01));
    959             vec2 texu_dir = uv[1] - uv[0];
    960             vec2 texv_dir = vec2(texu_dir.y, texu_dir.x);
    961             //Final calculations
    962             uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02);
    963 
    964             //Set UV on ALL matching vertices!
    965             array<int> matching_vert;
    966             for (int i = 0; i < 3; i++)
    967             {
    968 #if 1
    969                 //This marks all same position UV to the same values
    970                 //Deactivation is a test.
    971                 matching_vert << v[i];
    972                 vert_dict.FindMatchingVertices(v[i], matching_vert);
    973                 for (int j = 0; j < matching_vert.Count(); j++)
    974                     if (m_vert[matching_vert[j]].m_texcoord.xy == vec2(-1.0f))
    975                         m_vert[matching_vert[j]].m_texcoord = vec4(abs(uv[i]), m_vert[matching_vert[j]].m_texcoord.zw);
    976 #else
    977                 m_vert[v[i]].m_texcoord = abs(uv[i]);
    978 #endif
    979             }
    980 
    981             tri_done << cur_tri;
    982             tri_check.Remove(0);
    983 
    984             //Get connected triangles and go from there.
    985             for (int j = 0; j < 3; j++)
    986             {
    987 #if 1
    988                 //This finds triangle that are connected to this triangle
    989                 vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done);
    990 #else
    991                 //This finds triangle that are connected to the vertices of this triangle
    992                 vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done);
    993 #endif
    994             }
    995         }
    996         else if (uv_set == 3)
    997         {
    998             for (int j = 0; j < 3; j++)
    999             {
    1000                 m_vert[tri_list[cur_tri]].m_texcoord     = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri]].m_texcoord.zw);
    1001                 m_vert[tri_list[cur_tri + 1]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 1]].m_texcoord.zw);
    1002                 m_vert[tri_list[cur_tri + 2]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 2]].m_texcoord.zw);
    1003             }
    1004 
    1005             //uv[0] = vec2(-1.0f);
    1006             //uv[1] = vec2(-1.0f);
    1007             //uv[2] = vec2(-1.0f);
    1008             /*
    1009             bool tri_present = false;
    1010             for (int j = 0; j < tri_done.Count(); j++)
    1011                 if (cur_tri == tri_done[j])
    1012                     tri_present = true;
    1013             if (!tri_present)
    1014                 tri_done << cur_tri;
    1015             tri_check.Remove(0);
    1016             */
    1017         }
    1018 
    1019         if (tri_check.Count() == 0 && tri_done.Count() != tri_count)
    1020         {
    1021             //look for unset triangle
    1022             for (int i = 0; !tri_check.Count() && i < tri_list.Count(); i += 3)
    1023             {
    1024                 bool tri_present = false;
    1025                 for (int j = 0; j < tri_done.Count(); j++)
    1026                     if (i == tri_done[j])
    1027                         tri_present = true;
    1028                 if (!tri_present)
    1029                     tri_check << i;
    1030             }
    1031         }
    1032     }
    1033 #endif
    1034 }
    1035 
    1036 //-----------------------------------------------------------------------------
    1037 void EasyMesh::SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale)
    1038 {
    1039     BD()->TexCoordOffset() = new_offset;
    1040     BD()->TexCoordScale() = new_scale;
    1041 }
    1042 
    1043 //-----------------------------------------------------------------------------
    1044 void EasyMesh::SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale)
    1045 {
    1046     BD()->TexCoordOffset2() = new_offset;
    1047     BD()->TexCoordScale2() = new_scale;
    1048 }
    1049 
    1050 //-----------------------------------------------------------------------------
    1051 void EasyMesh::SetCurVertNormal(vec3 const &normal)
    1052 {
    1053     m_vert[m_vert.Count() - 1].m_normal = normal;
    1054 }
    1055 
    1056 //-----------------------------------------------------------------------------
    1057 void EasyMesh::SetCurVertColor(vec4 const &color)
    1058 {
    1059     m_vert[m_vert.Count() - 1].m_color = color;
    1060 }
    1061 
    1062 //-----------------------------------------------------------------------------
    1063 void EasyMesh::SetCurVertTexCoord(vec2 const &texcoord)
    1064 {
    1065     m_vert[m_vert.Count() - 1].m_texcoord = vec4(texcoord, m_vert[m_vert.Count() - 1].m_texcoord.zw);
    1066 }
    1067 
    1068 //-----------------------------------------------------------------------------
    1069 void EasyMesh::SetCurVertTexCoord2(vec2 const &texcoord)
    1070 {
    1071     m_vert[m_vert.Count() - 1].m_texcoord = vec4(m_vert[m_vert.Count() - 1].m_texcoord.xy, texcoord);
    1072 }
    107322
    107423//-----------------------------------------------------------------------------
     
    1158107    }
    1159108
    1160     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
     109    ComputeNormals(m_cursors.Last().m2, (int)m_indices.Count() - m_cursors.Last().m2);
    1161110}
    1162111
     
    1240189        }
    1241190    }
    1242     ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
    1243 }
    1244 
    1245 //-----------------------------------------------------------------------------
     191    ComputeNormals(m_cursors.Last().m2, (int)m_indices.Count() - m_cursors.Last().m2);
     192}
     193
     194//-----------------------------------------------------------------------------
     195void EasyMesh::Scale(float s) { Scale(vec3(s)); }
    1246196void EasyMesh::Scale(vec3 const &s)
    1247197{
     
    1288238    }
    1289239
    1290     int vlen = m_vert.Count() - m_cursors.Last().m1;
    1291     int tlen = m_indices.Count() - m_cursors.Last().m2;
     240    int vlen = (int)m_vert.Count() - m_cursors.Last().m1;
     241    int tlen = (int)m_indices.Count() - m_cursors.Last().m2;
    1292242
    1293243    for (int i = 0; i < vlen; i++)
     
    1312262
    1313263//-----------------------------------------------------------------------------
    1314 void EasyMesh::AppendCylinder(int nsides, float h, float d1, float d2,
    1315                               bool dualside, bool smooth, bool close)
    1316 {
    1317     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1318     {
    1319         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCylinder);
    1320         BD()->CmdStack() << nsides << h << d1 << d2 << dualside << smooth << close;
    1321         return;
    1322     }
    1323 
    1324     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1325     float r1 = d1 * .5f;
    1326     float r2 = d2 * .5f;
    1327 
    1328     //SAVE
    1329     vec4 Saved_ColorA = BD()->ColorA();
    1330     vec4 Saved_ColorB = BD()->ColorB();
    1331     vec2 Save_texcoord_offset = BD()->TexCoordOffset();
    1332     vec2 Save_texcoord_scale = BD()->TexCoordScale();
    1333 
    1334     int vbase = m_vert.Count();
    1335 
    1336     mat3 rotmat = mat3::rotate(360.0f / (float)nsides, 0.f, 1.f, 0.f);
    1337     vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n;
    1338     vec2 uv1(.0f, .0f), uv2(.0f, 1.0f), uvadd(1.0f / (float)nsides, .0f);
    1339     if (close)
    1340         SetTexCoordData(vec2(.0f), vec2(1.0f, .5f));
    1341 
    1342     /* Construct normal */
    1343     if (r2 != .0f)
    1344         n = vec3(r2, h * .5f, 0.f);
    1345     else
    1346         n = vec3(r1, h * .5f, 0.f);
    1347     n.y = r1 * (r1 - r2) / h;
    1348     if (!smooth)
    1349         n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n;
    1350     n = normalize(n);
    1351 
    1352     //Two passes necessary to ensure "weighted quad" compatibility
    1353     //First pass : Add vertices
    1354     for (int i = 0; i < nsides; i++)
    1355     {
    1356         /* FIXME: normals should be flipped in two-sided mode, but that
    1357          * means duplicating the vertices again... */
    1358         AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1359         AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    1360 
    1361         p1 = rotmat * p1; uv1 += uvadd;
    1362         p2 = rotmat * p2; uv2 += uvadd;
    1363 
    1364         if (!smooth)
    1365         {
    1366             AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1);
    1367             AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); SetCurVertColor(BD()->ColorB());
    1368         }
    1369 
    1370         n = rotmat * n;
    1371     }
    1372     //Second pass : Build quad
    1373     for (int i = 0; i < nsides; i++)
    1374     {
    1375         if (smooth)
    1376         {
    1377             int j = (i + 1) % nsides;
    1378             AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase);
    1379             if (dualside)
    1380                 AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase);
    1381         }
    1382         else
    1383         {
    1384             AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase);
    1385             if (dualside)
    1386                 AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase);
    1387         }
    1388 
    1389     }
    1390 
    1391     if (close)
    1392     {
    1393         //START
    1394         OpenBrace();
    1395         //LOWER DISC
    1396         SetTexCoordData(vec2(.0f, .5f), vec2(.5f, .5f));
    1397         SetCurColorA(BD()->ColorA());
    1398         AppendDisc(nsides, d1);
    1399         Translate(vec3(.0f, h, .0f));
    1400         RotateX(180.0f);
    1401         //UPPER DISC
    1402         SetTexCoordData(vec2(.5f, .5f), vec2(.5f, .5f));
    1403         SetCurColorA(BD()->ColorB());
    1404         AppendDisc(nsides, d2);
    1405         Translate(vec3(.0f, h * .5f, .0f));
    1406         CloseBrace();
    1407     }
    1408     //RESTORE
    1409     SetCurColorA(Saved_ColorA);
    1410     SetCurColorB(Saved_ColorB);
    1411     SetTexCoordData(Save_texcoord_offset, Save_texcoord_scale);
    1412 }
    1413 
    1414 //-----------------------------------------------------------------------------
    1415 void EasyMesh::AppendSphere(int ndivisions, float d)
    1416 {
    1417     AppendCapsule(ndivisions, 0.f, d);
    1418 }
    1419 
    1420 //-----------------------------------------------------------------------------
    1421 void EasyMesh::AppendCapsule(int ndivisions, float h, float d)
    1422 {
    1423     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1424     {
    1425         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCapsule);
    1426         BD()->CmdStack() << ndivisions << h << d;
    1427         return;
    1428     }
    1429 
    1430     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1431     float r = d * .5f;
    1432 
    1433     int ibase = m_indices.Count();
    1434 
    1435     array<vec3> vertices;
    1436     float uv_h = 0;
    1437     float uv_r = 0;
    1438 
    1439     /* FIXME: we don't know how to handle even-divided capsules, so we
    1440      * force the count to be odd. */
    1441     if (h)
    1442     {
    1443         ndivisions |= 1;
    1444         //calculate uv h&r percents
    1445         uv_h = (float)h / (float)(h + r * 2);
    1446         uv_r = (float)r / (float)(h + r * 2);
    1447     }
    1448 
    1449     /* Fill in the icosahedron vertices, rotating them so that there
    1450      * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */
    1451     float phi = 0.5f + 0.5f * sqrt(5.f);
    1452     mat3 m = mat3::rotate(degrees(asin(1.f / sqrt(2.f + phi))),
    1453                           vec3(0.f, 0.f, 1.f));
    1454     for (int i = 0; i < 4; i++)
    1455     {
    1456         float x = (i & 1) ? 0.5f : -0.5f;
    1457         float y = (i & 2) ? phi * 0.5f : phi * -0.5f;
    1458         vertices << m * vec3(x, y, 0.f);
    1459         vertices << m * vec3(0.f, x, y);
    1460         vertices << m * vec3(y, 0.f, x);
    1461     }
    1462 
    1463     static int const trilist[] =
    1464     {
    1465         0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8,
    1466         7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11,
    1467 
    1468         0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1,
    1469         2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6,
    1470         7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8
    1471     };
    1472 
    1473     for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3)
    1474     {
    1475         vec3 const &a = vertices[trilist[i]];
    1476         vec3 const &b = vertices[trilist[i + 1]];
    1477         vec3 const &c = vertices[trilist[i + 2]];
    1478 
    1479         vec3 const vb = 1.f / ndivisions * (b - a);
    1480         vec3 const vc = 1.f / ndivisions * (c - a);
    1481 
    1482         int line = ndivisions + 1;
    1483 
    1484         for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++)
    1485         {
    1486             vec3 p[] = { a + (float)x * vb + (float)y * vc,
    1487                          p[0] + vb,
    1488                          p[0] + vc,
    1489                          p[0] + vb + vc };
    1490             vec2 uv[4];
    1491 
    1492             /* FIXME: when we normalise here, we get a volume that is slightly
    1493              * smaller than the sphere of radius 1, since we are not using
    1494              * the midradius. */
    1495             for (int k = 0; k < 4; k++)
    1496             {
    1497                 //keep normalized until the end of the UV calculations
    1498                 p[k] = normalize(p[k]);
    1499 
    1500                 uv[k].x = (lol::atan2(p[k].z, p[k].x) + F_PI) / (F_PI * 2.f);
    1501                 if (abs(p[k].y) >= 1.0f)
    1502                     uv[k].x = -1.f;
    1503                 uv[k].y = lol::atan2(p[k].y, dot(p[k], normalize(p[k] * vec3(1.f,0.f,1.f)))) / F_PI + 0.5f;
    1504                 if (h)
    1505                 {
    1506                     if (uv[k].y > .5f)
    1507                         uv[k].y = uv_r + uv_h + (uv[k].y - .5f) * uv_r * 2.f;
    1508                     else
    1509                         uv[k].y *= uv_r * 2.f;
    1510                 }
    1511                 p[k] *= r;
    1512             }
    1513 
    1514             /* If this is a capsule, grow in the Y direction */
    1515             if (h > 0.f)
    1516             {
    1517                 for (int k = 0; k < 4; k++)
    1518                     p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h;
    1519             }
    1520 
    1521             /* Add zero, one or two triangles */
    1522             int id[] = { 0, 1, 2,
    1523                          1, 3 ,2 };
    1524             int l = 6;
    1525             while ((l -= 3) >= 0)
    1526             {
    1527                 if ((l == 0 && y < line - 1) || (l == 3 && y < line - 2))
    1528                 {
    1529                     int k = -1;
    1530                     while (++k < 3)
    1531                     {
    1532                         int rid[] = { id[k + l], id[(k + 1) % 3 + l] };
    1533                         if (uv[rid[0]].x >= .0f &&
    1534                             uv[rid[1]].x >= .0f &&
    1535                             abs(uv[rid[0]].x - uv[rid[1]].x) > .5f)
    1536                         {
    1537                             if (uv[rid[0]].x < uv[rid[1]].x)
    1538                                 uv[rid[0]].x += 1.0f;
    1539                             else
    1540                                 uv[rid[1]].x += 1.0f;
    1541                         }
    1542                     }
    1543                     k = -1;
    1544                     while (++k < 3)
    1545                     {
    1546                         int rid[] = { id[k + l], id[(k + 1) % 3 + l], id[(k + 2) % 3 + l] };
    1547                         AddVertex(p[rid[0]]);
    1548                         vec2 new_uv;
    1549                         if (uv[rid[0]].x < .0f)
    1550                             new_uv = vec2((uv[rid[1]].x + uv[rid[2]].x) * .5f, uv[rid[0]].y);
    1551                         else
    1552                             new_uv = uv[rid[0]];
    1553                         SetCurVertTexCoord(vec2(0.f, 1.f) - new_uv);
    1554                         SetCurVertTexCoord2(vec2(0.f, 1.f) - new_uv);
    1555                     }
    1556                     AppendTriangle(0, 2, 1, m_vert.Count() - 3);
    1557                 }
    1558             }
    1559 
    1560             y++;
    1561             if (y == line)
    1562             {
    1563                 x++;
    1564                 y = 0;
    1565                 line--;
    1566             }
    1567         }
    1568     }
    1569 
    1570     ComputeNormals(ibase, m_indices.Count() - ibase);
    1571 }
    1572 
    1573 //-----------------------------------------------------------------------------
    1574 void EasyMesh::AppendTorus(int ndivisions, float d1, float d2)
    1575 {
    1576     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1577     {
    1578         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendTorus);
    1579         BD()->CmdStack() << ndivisions << d1 << d2;
    1580         return;
    1581     }
    1582 
    1583     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1584     float r1 = d1 * .5f;
    1585     float r2 = d2 * .5f;
    1586 
    1587     int ibase = m_indices.Count();
    1588     int nidiv = ndivisions; /* Cross-section */
    1589     int njdiv = ndivisions; /* Full circumference */
    1590 
    1591     for (int j = 0; j < njdiv; j++)
    1592     for (int i = 0; i < 2 * nidiv; i++)
    1593     {
    1594         for (int di = 0; di < 2; di++)
    1595         for (int dj = 0; dj < 2; dj++)
    1596         {
    1597             int i2 = (i + di) % nidiv;
    1598             int j2 = (j + dj) % njdiv;
    1599 
    1600             //Location on the donut
    1601             float x = 0.5f * (r2 - r1) * (float)lol::cos(2.f * F_PI * i2 / nidiv) + 0.5f * (r1 + r2);
    1602             float y = 0.5f * (r2 - r1) * (float)lol::sin(2.f * F_PI * i2 / nidiv);
    1603             float z = 0.0f;
    1604 
    1605             //Center circle
    1606             float ca = (float)lol::cos(2.f * F_PI * j2 / njdiv);
    1607             float sa = (float)lol::sin(2.f * F_PI * j2 / njdiv);
    1608 
    1609             //Actual location
    1610             float x2 = x * ca - z * sa;
    1611             float z2 = z * ca + x * sa;
    1612 
    1613             AddVertex(vec3(x2, y, z2));
    1614             SetCurVertTexCoord(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1615             SetCurVertTexCoord2(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv));
    1616         }
    1617 
    1618         AppendTriangle(0, 2, 3, m_vert.Count() - 4);
    1619         AppendTriangle(0, 3, 1, m_vert.Count() - 4);
    1620     }
    1621 
    1622     ComputeNormals(ibase, m_indices.Count() - ibase);
    1623 }
    1624 
    1625 //-----------------------------------------------------------------------------
    1626 void EasyMesh::AppendBox(vec3 const &size, float chamf)
    1627 {
    1628     AppendBox(size, chamf, false);
    1629 }
    1630 
    1631 //-----------------------------------------------------------------------------
    1632 void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
    1633 {
    1634     AppendBox(size, chamf, true);
    1635 }
    1636 
    1637 //-----------------------------------------------------------------------------
    1638 void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
    1639 {
    1640     AppendBox(size, chamf, false);
    1641 }
    1642 
    1643 //-----------------------------------------------------------------------------
    1644 void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
    1645 {
    1646     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1647     {
    1648         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendBox);
    1649         BD()->CmdStack() << size << chamf << smooth;
    1650         return;
    1651     }
    1652 
    1653     if (chamf < 0.0f)
    1654     {
    1655         AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth);
    1656         return;
    1657     }
    1658 
    1659     int vbase = m_vert.Count();
    1660     int ibase = m_indices.Count();
    1661 
    1662     vec3 d = size * 0.5f;
    1663 
    1664     MeshType mt = MeshType::Box;
    1665     TexCoordPos bl = TexCoordPos::BL;
    1666     TexCoordPos br = TexCoordPos::BR;
    1667     TexCoordPos tl = TexCoordPos::TL;
    1668     TexCoordPos tr = TexCoordPos::TR;
    1669 
    1670     //--
    1671     //Side vertices
    1672     //--
    1673     MeshFaceType mft = MeshFaceType::BoxFront;
    1674     AddVertex(vec3(-d.x, -d.y, -d.z - chamf));
    1675     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1676     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1677     //--
    1678     AddVertex(vec3(-d.x, +d.y, -d.z - chamf));
    1679     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1680     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1681     //--
    1682     AddVertex(vec3(+d.x, +d.y, -d.z - chamf));
    1683     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1684     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1685     //--
    1686     AddVertex(vec3(+d.x, -d.y, -d.z - chamf));
    1687     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1688     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1689 
    1690     //--
    1691     mft = MeshFaceType::BoxLeft;
    1692     AddVertex(vec3(-d.x - chamf, -d.y, +d.z));
    1693     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1694     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1695     //--
    1696     AddVertex(vec3(-d.x - chamf, +d.y, +d.z));
    1697     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1698     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1699     //--
    1700     AddVertex(vec3(-d.x - chamf, +d.y, -d.z));
    1701     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1702     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1703     //--
    1704     AddVertex(vec3(-d.x - chamf, -d.y, -d.z));
    1705     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1706     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1707 
    1708     //--
    1709     mft = MeshFaceType::BoxBack;
    1710     AddVertex(vec3(+d.x, -d.y, +d.z + chamf));
    1711     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1712     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1713     //--
    1714     AddVertex(vec3(+d.x, +d.y, +d.z + chamf));
    1715     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1716     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1717     //--
    1718     AddVertex(vec3(-d.x, +d.y, +d.z + chamf));
    1719     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1720     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1721     //--
    1722     AddVertex(vec3(-d.x, -d.y, +d.z + chamf));
    1723     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1724     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1725 
    1726     //--
    1727     mft = MeshFaceType::BoxRight;
    1728     AddVertex(vec3(+d.x + chamf, -d.y, -d.z));
    1729     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1730     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1731     //--
    1732     AddVertex(vec3(+d.x + chamf, +d.y, -d.z));
    1733     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1734     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1735     //--
    1736     AddVertex(vec3(+d.x + chamf, +d.y, +d.z));
    1737     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1738     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1739     //--
    1740     AddVertex(vec3(+d.x + chamf, -d.y, +d.z));
    1741     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1742     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1743 
    1744     //--
    1745     //Bottom vertices
    1746     //--
    1747     mft = MeshFaceType::BoxBottom;
    1748     AddVertex(vec3(-d.x, -d.y - chamf, +d.z));
    1749     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1750     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1751     //--
    1752     AddVertex(vec3(-d.x, -d.y - chamf, -d.z));
    1753     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1754     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1755     //--
    1756     AddVertex(vec3(+d.x, -d.y - chamf, -d.z));
    1757     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1758     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1759     //--
    1760     AddVertex(vec3(+d.x, -d.y - chamf, +d.z));
    1761     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1762     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1763 
    1764     //--
    1765     //Top vertices
    1766     //--
    1767     mft = MeshFaceType::BoxTop;
    1768     AddVertex(vec3(-d.x, +d.y + chamf, -d.z));
    1769     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    1770     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1771     //--
    1772     AddVertex(vec3(-d.x, +d.y + chamf, +d.z));
    1773     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    1774     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1775     //--
    1776     AddVertex(vec3(+d.x, +d.y + chamf, +d.z));
    1777     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    1778     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1779     //--
    1780     AddVertex(vec3(+d.x, +d.y + chamf, -d.z));
    1781     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    1782     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    1783 
    1784     ComputeNormals(ibase, m_indices.Count() - ibase);
    1785     ibase = m_indices.Count();
    1786 
    1787     //Build the box at the end : The 6 quads on each side of the box.
    1788     for (int i = 0; i < 24; i += 4)
    1789         AppendQuad(i, i + 1, i + 2, i + 3, vbase);
    1790 
    1791     /* The 8 quads at each edge of the box */
    1792     if (chamf)
    1793     {
    1794         static int const quadlist[48] =
    1795         {
    1796             0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18,
    1797             2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22,
    1798             1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2,
    1799         };
    1800 
    1801         for (int i = 0; i < 48; i += 4)
    1802         {
    1803             if (smooth)
    1804                 AppendQuad(quadlist[i],     quadlist[i + 1],
    1805                            quadlist[i + 2], quadlist[i + 3], vbase);
    1806             else
    1807                 AppendQuadDuplicateVerts(quadlist[i],     quadlist[i + 1],
    1808                                          quadlist[i + 2], quadlist[i + 3], vbase);
    1809         }
    1810     }
    1811 
    1812     /* The 8 triangles at each corner of the box */
    1813     if (chamf)
    1814     {
    1815         static int const trilist[24] =
    1816         {
    1817             3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17,
    1818             2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1,
    1819         };
    1820 
    1821         for (int i = 0; i < 24; i += 3)
    1822         {
    1823             if (smooth)
    1824                 AppendTriangle(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1825             else
    1826                 AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1], trilist[i + 2], vbase);
    1827         }
    1828     }
    1829 
    1830     if (!smooth)
    1831         ComputeNormals(ibase, m_indices.Count() - ibase);
    1832 }
    1833 
    1834 //-----------------------------------------------------------------------------
    1835 void EasyMesh::AppendStar(int nbranches, float d1, float d2,
    1836                           bool fade, bool fade2)
    1837 {
    1838     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1839     {
    1840         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendStar);
    1841         BD()->CmdStack() << nbranches << d1 << d2 << fade << fade2;
    1842         return;
    1843     }
    1844 
    1845     //Should ignore quad weight, as it does not destroy star symmetry
    1846     BD()->Enable(MeshBuildOperation::IgnoreQuadWeighting);
    1847 
    1848     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1849     float r1 = d1 * .5f;
    1850     float r2 = d2 * .5f;
    1851 
    1852     //TODO: It would probably be good to think of another way of UV painting this, like "branch repeating"
    1853     int vbase = m_vert.Count();
    1854     float maxr = max(r1, r2);
    1855 
    1856     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1857 
    1858     mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
    1859     vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f);
    1860     vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
    1861          uv2(0.f, 0.f, -.5f * ((float)r2 / maxr));
    1862 
    1863     p2 = rotmat * p2; uv2 = rotmat * uv2;
    1864     rotmat = rotmat * rotmat;
    1865 
    1866     for (int i = 0; i < nbranches; i++)
    1867     {
    1868         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1869         if (fade2)
    1870             SetCurVertColor(BD()->ColorB());
    1871 
    1872         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1873         if (fade)
    1874             SetCurVertColor(BD()->ColorB());
    1875 
    1876         //Append quad at the end
    1877         AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches), vbase);
    1878 
    1879         p1 = rotmat * p1; uv1 = rotmat * uv1;
    1880         p2 = rotmat * p2; uv2 = rotmat * uv2;
    1881     }
    1882 
    1883     //Restore
    1884     BD()->Disable(MeshBuildOperation::IgnoreQuadWeighting);
    1885 }
    1886 
    1887 //-----------------------------------------------------------------------------
    1888 void EasyMesh::AppendExpandedStar(int nbranches, float d1, float d2, float extrad)
    1889 {
    1890     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1891     {
    1892         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendExpandedStar);
    1893         BD()->CmdStack() << nbranches << d1 << d2 << extrad;
    1894         return;
    1895     }
    1896 
    1897     //Should ignore quad weight, as it does not destroy star symmetry
    1898     BD()->Enable(MeshBuildOperation::IgnoreQuadWeighting);
    1899 
    1900     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1901     float r1 = d1 * .5f;
    1902     float r2 = d2 * .5f;
    1903     float extrar = extrad * .5f;
    1904 
    1905     int vbase = m_vert.Count();
    1906     float maxr = (float)max(max(r1, r2), max(r1 + extrar, r2 + extrar));
    1907 
    1908     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1909 
    1910     mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f);
    1911     vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f),
    1912          p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);;
    1913     vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)),
    1914          uv2(0.f, 0.f, -.5f * ((float)r2 / maxr)),
    1915          uv3(0.f, 0.f, -.5f * ((float)(r1 + extrar) / maxr)),
    1916          uv4(0.f, 0.f, -.5f * ((float)(r2 + extrar) / maxr));
    1917 
    1918     p2 = rotmat * p2; uv2 = rotmat * uv2;
    1919     p4 = rotmat * p4; uv4 = rotmat * uv4;
    1920     rotmat = rotmat * rotmat;
    1921 
    1922     for (int i = 0; i < nbranches; i++)
    1923     {
    1924         AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f));
    1925         AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f));
    1926         AddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1927         AddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->ColorB());
    1928 
    1929         int j = (i + 1) % nbranches;
    1930         //
    1931         AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase);
    1932         AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase);
    1933         AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase);
    1934 
    1935         p1 = rotmat * p1; uv1 = rotmat * uv1;
    1936         p2 = rotmat * p2; uv2 = rotmat * uv2;
    1937         p3 = rotmat * p3; uv3 = rotmat * uv3;
    1938         p4 = rotmat * p4; uv4 = rotmat * uv4;
    1939     }
    1940 
    1941     //Restore
    1942     BD()->Disable(MeshBuildOperation::IgnoreQuadWeighting);
    1943 }
    1944 
    1945 //-----------------------------------------------------------------------------
    1946 void EasyMesh::AppendDisc(int nsides, float d, bool fade)
    1947 {
    1948     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1949     {
    1950         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendDisc);
    1951         BD()->CmdStack() << nsides << d << fade;
    1952         return;
    1953     }
    1954 
    1955     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1956     float r = d * .5f;
    1957 
    1958     int vbase = m_vert.Count();
    1959 
    1960     AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f));
    1961 
    1962     mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f);
    1963     vec3 p1(r, 0.f, 0.f);
    1964     vec3 uv(.5f, .0f, .0f);
    1965 
    1966     for (int i = 0; i < nsides; i++)
    1967     {
    1968         AddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f));
    1969         if (fade)
    1970             SetCurVertColor(BD()->ColorB());
    1971         AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase);
    1972         p1 = rotmat * p1;
    1973         uv = rotmat * uv;
    1974     }
    1975 }
    1976 
    1977 //-----------------------------------------------------------------------------
    1978 void EasyMesh::AppendSimpleTriangle(float d, bool fade)
    1979 {
    1980     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    1981     {
    1982         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendSimpleTriangle);
    1983         BD()->CmdStack() << d << fade;
    1984         return;
    1985     }
    1986 
    1987     //XXX : This operation is done to convert radius to diameter without changing all the code.
    1988     float size = d * .5f;
    1989 
    1990     mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
    1991     vec3 p(0.f, 0.f, size);
    1992 
    1993     AddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f));
    1994     p = m * p;
    1995     AddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f));
    1996     if (fade)
    1997         SetCurVertColor(BD()->ColorB());
    1998     p = m * p;
    1999     AddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f));
    2000     if (fade)
    2001         SetCurVertColor(BD()->ColorB());
    2002 
    2003     AppendTriangle(0, 1, 2, m_vert.Count() - 3);
    2004 }
    2005 
    2006 //-----------------------------------------------------------------------------
    2007 void EasyMesh::AppendSimpleQuad(float size, bool fade)
    2008 {
    2009     AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
    2010 }
    2011 
    2012 //-----------------------------------------------------------------------------
    2013 void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, bool fade)
    2014 {
    2015     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2016     {
    2017         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendSimpleQuad);
    2018         BD()->CmdStack() << p1 << p2 << z << fade;
    2019         return;
    2020     }
    2021 
    2022     MeshType mt = MeshType::Quad;
    2023     MeshFaceType mft = MeshFaceType::QuadDefault;
    2024 
    2025     //--
    2026     AddVertex(vec3(p2.x, z, -p1.y));
    2027     TexCoordPos br = TexCoordPos::BR;
    2028     SetCurVertTexCoord(BD()->TexCoord(mt, br, mft));
    2029     SetCurVertTexCoord2(BD()->TexCoord2(mt, br, mft));
    2030     //--
    2031     AddVertex(vec3(p2.x, z, -p2.y));
    2032     TexCoordPos bl = TexCoordPos::BL;
    2033     SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft));
    2034     SetCurVertTexCoord2(BD()->TexCoord2(mt, bl, mft));
    2035     //--
    2036     AddVertex(vec3(p1.x, z, -p2.y));
    2037     TexCoordPos tl = TexCoordPos::TL;
    2038     SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft));
    2039     SetCurVertTexCoord2(BD()->TexCoord2(mt, tl, mft));
    2040     if (fade) SetCurVertColor(BD()->ColorB());
    2041     //--
    2042     AddVertex(vec3(p1.x, z, -p1.y));
    2043     TexCoordPos tr = TexCoordPos::TR;
    2044     SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft));
    2045     SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft));
    2046     if (fade) SetCurVertColor(BD()->ColorB());
    2047 
    2048     AppendQuad(0, 1, 2, 3, m_vert.Count() - 4);
    2049     ComputeNormals(m_indices.Count() - 6, 6);
    2050 }
    2051 
    2052 //-----------------------------------------------------------------------------
    2053 void EasyMesh::AppendCog(int nbsides, float h, float d10, float d20,
    2054                          float d11, float d21, float d12, float d22,
    2055                          float sidemul, bool offset)
    2056 {
    2057     if (BD()->IsEnabled(MeshBuildOperation::CommandRecording))
    2058     {
    2059         BD()->CmdStack().AddCmd(EasyMeshCmdType::AppendCog);
    2060         BD()->CmdStack() << nbsides << h
    2061                          << d10 << d20
    2062                          << d11 << d21
    2063                          << d12 << d22
    2064                          << sidemul << offset;
    2065         return;
    2066     }
    2067 
    2068     //XXX : This operation is done to convert radius to diameter without changing all the code.
    2069     float r10 = d10 * .5f;
    2070     float r20 = d20 * .5f;
    2071     float r11 = d11 * .5f;
    2072     float r21 = d21 * .5f;
    2073     float r12 = d12 * .5f;
    2074     float r22 = d22 * .5f;
    2075 
    2076     int ibase = m_indices.Count();
    2077     int vbase = m_vert.Count();
    2078 
    2079     /* FIXME: enforce this some other way */
    2080     if (r12 < 0)
    2081         h = -h;
    2082 
    2083     mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f);
    2084     mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f);
    2085     mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f);
    2086 
    2087     vec3 p[12];
    2088 
    2089     //Upper points
    2090     p[0] = vec3(r10, h * .5f, 0.f);
    2091     p[1] = rotmat * p[0];
    2092     p[2] = vec3(r11, h * .5f, 0.f);
    2093     p[3] = rotmat * p[2];
    2094     p[4] = smat1 * (rotmat * vec3(r11 + r12, h * .5f, 0.f));
    2095     p[5] = smat2 * (rotmat * p[4]);
    2096 
    2097     //Lower points
    2098     p[6] = vec3(r20, h * -.5f, 0.f);
    2099     p[7] = rotmat * p[6];
    2100     p[8] = vec3(r21, h * -.5f, 0.f);
    2101     p[9] = rotmat * p[8];
    2102     p[10] = smat1 * (rotmat * vec3(r21 + r22, h * -.5f, 0.f));
    2103     p[11] = smat2 * (rotmat * p[10]);
    2104 
    2105     if (offset)
    2106         for (int n = 0; n < 12; n++)