92    wxLogTrace( 
m_logTrace, wxT( 
"MODEL_3D::MODEL_3D %u meshes %u materials" ),
 
   96    auto start_time = std::chrono::high_resolution_clock::now();
 
  106    glGenBuffers( 6, buffers );
 
  114    wxASSERT( a3DModel.
m_Meshes != 
nullptr );
 
  144        std::vector<VERTEX> m_vertices;
 
  145        std::vector<GLuint> m_indices;
 
  148    std::vector<MESH_GROUP> mesh_groups( 
m_materials.size() );
 
  150    for( 
unsigned int mesh_i = 0; mesh_i < a3DModel.
m_MeshesSize; ++mesh_i )
 
  173        const unsigned int vtx_offset = mesh_group.m_vertices.size();
 
  174        mesh_group.m_vertices.resize( mesh_group.m_vertices.size() + mesh.
m_VertexSize );
 
  178        glm::vec3 avg_color = material.
m_Diffuse;
 
  182        for( 
unsigned int vtx_i = 0; vtx_i < mesh.
m_VertexSize; ++vtx_i )
 
  186            VERTEX& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
 
  189            vtx_out.
m_nrm = glm::clamp( glm::vec4( mesh.
m_Normals[vtx_i], 1.0f ) * 127.0f,
 
  197              avg_color = ( avg_color + mesh.
m_Color[vtx_i] ) * 0.5f;
 
  200                  glm::clamp( glm::vec4( mesh.
m_Color[vtx_i],
 
  206                                         1 ) * 255.0f, 0.0f, 255.0f );
 
  216                    glm::clamp( glm::vec4( material.
m_Diffuse,
 
  233                      { avg_color, 1.0f } );
 
  244        const unsigned int idx_offset = mesh_group.m_indices.size();
 
  247        if( use_idx_count % 3 != 0 )
 
  249            wxLogTrace( 
m_logTrace, wxT( 
"  index count %u not multiple of 3, truncating" ),
 
  250                        static_cast<unsigned int>( use_idx_count ) );
 
  251            use_idx_count = ( use_idx_count / 3 ) * 3;
 
  254        mesh_group.m_indices.resize( mesh_group.m_indices.size() + use_idx_count );
 
  256        for( 
unsigned int idx_i = 0; idx_i < use_idx_count; ++idx_i )
 
  260                wxLogTrace( 
m_logTrace, wxT( 
" index %u out of range (%u)" ),
 
  261                            static_cast<unsigned int>( mesh.
m_FaceIdx[idx_i] ),
 
  267            mesh_group.m_indices[idx_offset + idx_i] = mesh.
m_FaceIdx[idx_i] + vtx_offset;
 
  274                  { 0.0f, 1.0f, 0.0f, 1.0f } );
 
  279    glBufferData( GL_ARRAY_BUFFER, 
sizeof( 
VERTEX ) * bbox_tmp_vertices.size(),
 
  280                  bbox_tmp_vertices.data(), GL_STATIC_DRAW );
 
  284    if( bbox_tmp_vertices.size() <= std::numeric_limits<GLushort>::max() )
 
  288        auto u16buf = std::make_unique<GLushort[]>( bbox_tmp_indices.size() );
 
  290        for( 
unsigned int i = 0; i < bbox_tmp_indices.size(); ++i )
 
  291          u16buf[i] = 
static_cast<GLushort
>( bbox_tmp_indices[i] );
 
  293        glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
sizeof( GLushort ) * bbox_tmp_indices.size(),
 
  294                      u16buf.get(), GL_STATIC_DRAW );
 
  299        glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
sizeof( GLuint ) * bbox_tmp_indices.size(),
 
  300                      bbox_tmp_indices.data(), GL_STATIC_DRAW );
 
  304    unsigned int total_vertex_count = 0;
 
  305    unsigned int total_index_count = 0;
 
  307    for( 
const MESH_GROUP& mg : mesh_groups )
 
  309        total_vertex_count += mg.m_vertices.size();
 
  310        total_index_count += mg.m_indices.size();
 
  313    wxLogTrace( 
m_logTrace, wxT( 
"  total %u vertices, %u indices" ),
 
  314                total_vertex_count, total_index_count );
 
  317    glBufferData( GL_ARRAY_BUFFER, 
sizeof( 
VERTEX ) * total_vertex_count,
 
  318                  nullptr, GL_STATIC_DRAW );
 
  320    unsigned int idx_size = 0;
 
  322    if( total_vertex_count <= std::numeric_limits<GLushort>::max() )
 
  325        idx_size = 
sizeof( GLushort );
 
  330        idx_size = 
sizeof( GLuint );
 
  336            std::make_unique<GLuint[]>( ( idx_size * total_index_count + 8 ) / 
sizeof( GLuint ) );
 
  338    unsigned int prev_vtx_count = 0;
 
  339    unsigned int idx_offset = 0;
 
  340    unsigned int vtx_offset = 0;
 
  342    for( 
unsigned int mg_i = 0; mg_i < mesh_groups.size (); ++mg_i )
 
  344        MESH_GROUP& mg = mesh_groups[mg_i];
 
  346        uintptr_t   tmp_idx_ptr = 
reinterpret_cast<uintptr_t
>( tmp_idx.get() );
 
  350            GLushort* idx_out = 
reinterpret_cast<GLushort*
>( tmp_idx_ptr + idx_offset );
 
  352            for( GLuint idx : mg.m_indices )
 
  353                *idx_out++ = 
static_cast<GLushort
>( idx + prev_vtx_count );
 
  357            GLuint* idx_out = 
reinterpret_cast<GLuint*
>( tmp_idx_ptr + idx_offset );
 
  359            for( GLuint idx : mg.m_indices )
 
  360                *idx_out++ = 
static_cast<GLuint
>( idx + prev_vtx_count );
 
  363        glBufferSubData( GL_ARRAY_BUFFER, vtx_offset, mg.m_vertices.size() * 
sizeof( 
VERTEX ),
 
  364                         mg.m_vertices.data() );
 
  369        prev_vtx_count += mg.m_vertices.size();
 
  370        idx_offset += mg.m_indices.size() * idx_size;
 
  371        vtx_offset += mg.m_vertices.size() * 
sizeof( 
VERTEX );
 
  375    glBufferData( GL_ELEMENT_ARRAY_BUFFER, idx_size * total_index_count, tmp_idx.get(),
 
  378    glBindBuffer( GL_ARRAY_BUFFER, 0 );
 
  379    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
 
  381    auto end_time = std::chrono::high_resolution_clock::now();
 
  383    wxLogTrace( 
m_logTrace, wxT( 
"  loaded in %u ms\n" ),
 
  384               (
unsigned int)std::chrono::duration_cast<std::chrono::milliseconds> (
 
  385                   end_time - start_time).count() );
 
 
  418void MODEL_3D::Draw( 
bool aTransparent, 
float aOpacity, 
bool aUseSelectedMaterial,
 
  419                     const SFVEC3F& aSelectionColor,
 
  420                     const glm::mat4 *aModelWorldMatrix,
 
  421                     const SFVEC3F *aCameraWorldPos )
 const 
  423    if( aOpacity <= FLT_EPSILON )
 
  427        throw std::runtime_error( 
"The OpenGL context no longer exists: unable to draw" );
 
  432    glVertexPointer( 3, GL_FLOAT, 
sizeof( 
VERTEX ),
 
  433                     reinterpret_cast<const void*
>( offsetof( 
VERTEX, m_pos ) ) );
 
  435    glNormalPointer( GL_BYTE, 
sizeof( 
VERTEX ),
 
  436                     reinterpret_cast<const void*
>( offsetof( 
VERTEX, m_nrm ) ) );
 
  438    glColorPointer( 4, GL_UNSIGNED_BYTE, 
sizeof( 
VERTEX ),
 
  440                                                         ? offsetof( 
VERTEX, m_cad_color )
 
  441                                                         : offsetof( 
VERTEX, m_color ) ) );
 
  443    glTexCoordPointer( 2, GL_FLOAT, 
sizeof( 
VERTEX ),
 
  444                       reinterpret_cast<const void*
>( offsetof( 
VERTEX, m_tex_uv ) ) );
 
  448    glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (
const float*)¶m.x );
 
  450    std::vector<const MODEL_3D::MATERIAL *> materialsToRender;
 
  454    if( aModelWorldMatrix && aCameraWorldPos )
 
  458        std::vector<std::pair<const MODEL_3D::MATERIAL*, float>> materialsSorted;
 
  463            if( mat.m_render_idx_count == 0 )
 
  468            if( ( mat.IsTransparent() != aTransparent )
 
  469                && ( aOpacity >= 1.0f )
 
  475            const BBOX_3D& bBox = mat.m_bbox;
 
  477            const SFVEC3F bBoxWorld = *aModelWorldMatrix * glm::vec4( bBoxCenter, 1.0f );
 
  479            const float distanceToCamera = glm::length( *aCameraWorldPos - bBoxWorld );
 
  481            materialsSorted.emplace_back( &mat, distanceToCamera  );
 
  485        std::sort( materialsSorted.begin(), materialsSorted.end(),
 
  486                [&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
 
  487                     std::pair<const MODEL_3D::MATERIAL*, float>& b )
 
  489                    bool aInsideB = a.first->m_bbox.Inside( b.first->m_bbox );
 
  490                    bool bInsideA = b.first->m_bbox.Inside( a.first->m_bbox );
 
  493                    if( aInsideB != bInsideA )
 
  496                    if( a.second != b.second )
 
  497                        return a.second > b.second;
 
  499                    return a.first > b.first;       
 
  502        for( 
const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
 
  504            materialsToRender.push_back( mat.first );
 
  514            if( mat.m_render_idx_count == 0 )
 
  519            if( ( mat.IsTransparent() != aTransparent )
 
  520                && ( aOpacity >= 1.0f )
 
  526            materialsToRender.push_back( &mat );
 
  535            OglSetMaterial( *mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
 
  545                                   aUseSelectedMaterial, aSelectionColor );
 
  553                        reinterpret_cast<const void*
>(
 
  554                                static_cast<uintptr_t
>( mat->m_render_idx_buffer_offset ) ) );