88 wxLogTrace(
m_logTrace, wxT(
"MODEL_3D::MODEL_3D %u meshes %u materials" ),
92 auto start_time = std::chrono::high_resolution_clock::now();
102 glGenBuffers( 6, buffers );
110 wxASSERT( a3DModel.
m_Meshes !=
nullptr );
140 std::vector<VERTEX> m_vertices;
141 std::vector<GLuint> m_indices;
144 std::vector<MESH_GROUP> mesh_groups(
m_materials.size() );
146 for(
unsigned int mesh_i = 0; mesh_i < a3DModel.
m_MeshesSize; ++mesh_i )
169 const unsigned int vtx_offset = mesh_group.m_vertices.size();
170 mesh_group.m_vertices.resize( mesh_group.m_vertices.size() + mesh.
m_VertexSize );
174 glm::vec3 avg_color = material.
m_Diffuse;
178 for(
unsigned int vtx_i = 0; vtx_i < mesh.
m_VertexSize; ++vtx_i )
182 VERTEX& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
185 vtx_out.
m_nrm = glm::clamp( glm::vec4( mesh.
m_Normals[vtx_i], 1.0f ) * 127.0f,
193 avg_color = ( avg_color + mesh.
m_Color[vtx_i] ) * 0.5f;
196 glm::clamp( glm::vec4( mesh.
m_Color[vtx_i],
202 1 ) * 255.0f, 0.0f, 255.0f );
212 glm::clamp( glm::vec4( material.
m_Diffuse,
229 { avg_color, 1.0f } );
242 if( use_idx_count % 3 != 0 )
244 wxLogTrace(
m_logTrace, wxT(
" index count %u not multiple of 3, truncating" ),
245 static_cast<unsigned int>( use_idx_count ) );
246 use_idx_count = ( use_idx_count / 3 ) * 3;
249 mesh_group.m_indices.reserve( mesh_group.m_indices.size() + use_idx_count );
251 for(
unsigned int idx_i = 0; idx_i < use_idx_count; idx_i += 3 )
255 wxLogTrace(
m_logTrace, wxT(
" triangle at index %u out of range (%u), skipping" ),
256 static_cast<unsigned int>( idx_i ),
262 mesh_group.m_indices.push_back( mesh.
m_FaceIdx[idx_i + 0] + vtx_offset );
263 mesh_group.m_indices.push_back( mesh.
m_FaceIdx[idx_i + 1] + vtx_offset );
264 mesh_group.m_indices.push_back( mesh.
m_FaceIdx[idx_i + 2] + vtx_offset );
271 { 0.0f, 1.0f, 0.0f, 1.0f } );
276 glBufferData( GL_ARRAY_BUFFER,
sizeof(
VERTEX ) * bbox_tmp_vertices.size(),
277 bbox_tmp_vertices.data(), GL_STATIC_DRAW );
281 if( bbox_tmp_vertices.size() <= std::numeric_limits<GLushort>::max() )
285 auto u16buf = std::make_unique<GLushort[]>( bbox_tmp_indices.size() );
287 for(
unsigned int i = 0; i < bbox_tmp_indices.size(); ++i )
288 u16buf[i] =
static_cast<GLushort
>( bbox_tmp_indices[i] );
290 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
sizeof( GLushort ) * bbox_tmp_indices.size(),
291 u16buf.get(), GL_STATIC_DRAW );
296 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
sizeof( GLuint ) * bbox_tmp_indices.size(),
297 bbox_tmp_indices.data(), GL_STATIC_DRAW );
301 unsigned int total_vertex_count = 0;
302 unsigned int total_index_count = 0;
304 for(
const MESH_GROUP& mg : mesh_groups )
306 total_vertex_count += mg.m_vertices.size();
307 total_index_count += mg.m_indices.size();
310 wxLogTrace(
m_logTrace, wxT(
" total %u vertices, %u indices" ),
311 total_vertex_count, total_index_count );
314 glBufferData( GL_ARRAY_BUFFER,
sizeof(
VERTEX ) * total_vertex_count,
315 nullptr, GL_STATIC_DRAW );
317 unsigned int idx_size = 0;
319 if( total_vertex_count <= std::numeric_limits<GLushort>::max() )
322 idx_size =
sizeof( GLushort );
327 idx_size =
sizeof( GLuint );
333 std::make_unique<GLuint[]>( ( idx_size * total_index_count + 8 ) /
sizeof( GLuint ) );
335 unsigned int prev_vtx_count = 0;
336 unsigned int idx_offset = 0;
337 unsigned int vtx_offset = 0;
339 for(
unsigned int mg_i = 0; mg_i < mesh_groups.size (); ++mg_i )
341 MESH_GROUP& mg = mesh_groups[mg_i];
343 uintptr_t tmp_idx_ptr =
reinterpret_cast<uintptr_t
>( tmp_idx.get() );
347 GLushort* idx_out =
reinterpret_cast<GLushort*
>( tmp_idx_ptr + idx_offset );
349 for( GLuint idx : mg.m_indices )
350 *idx_out++ =
static_cast<GLushort
>( idx + prev_vtx_count );
354 GLuint* idx_out =
reinterpret_cast<GLuint*
>( tmp_idx_ptr + idx_offset );
356 for( GLuint idx : mg.m_indices )
357 *idx_out++ =
static_cast<GLuint
>( idx + prev_vtx_count );
360 glBufferSubData( GL_ARRAY_BUFFER, vtx_offset, mg.m_vertices.size() *
sizeof(
VERTEX ),
361 mg.m_vertices.data() );
366 prev_vtx_count += mg.m_vertices.size();
367 idx_offset += mg.m_indices.size() * idx_size;
368 vtx_offset += mg.m_vertices.size() *
sizeof(
VERTEX );
372 glBufferData( GL_ELEMENT_ARRAY_BUFFER, idx_size * total_index_count, tmp_idx.get(),
375 glBindBuffer( GL_ARRAY_BUFFER, 0 );
376 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
378 auto end_time = std::chrono::high_resolution_clock::now();
380 wxLogTrace(
m_logTrace, wxT(
" loaded in %u ms\n" ),
381 (
unsigned int)std::chrono::duration_cast<std::chrono::milliseconds> (
382 end_time - start_time).count() );
415void MODEL_3D::Draw(
bool aTransparent,
float aOpacity,
bool aUseSelectedMaterial,
416 const SFVEC3F& aSelectionColor,
417 const glm::mat4 *aModelWorldMatrix,
418 const SFVEC3F *aCameraWorldPos )
const
420 if( aOpacity <= FLT_EPSILON )
424 throw std::runtime_error(
"The OpenGL context no longer exists: unable to draw" );
429 glVertexPointer( 3, GL_FLOAT,
sizeof(
VERTEX ),
430 reinterpret_cast<const void*
>( offsetof(
VERTEX, m_pos ) ) );
432 glNormalPointer( GL_BYTE,
sizeof(
VERTEX ),
433 reinterpret_cast<const void*
>( offsetof(
VERTEX, m_nrm ) ) );
435 glColorPointer( 4, GL_UNSIGNED_BYTE,
sizeof(
VERTEX ),
437 ? offsetof(
VERTEX, m_cad_color )
438 : offsetof(
VERTEX, m_color ) ) );
440 glTexCoordPointer( 2, GL_FLOAT,
sizeof(
VERTEX ),
441 reinterpret_cast<const void*
>( offsetof(
VERTEX, m_tex_uv ) ) );
445 glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (
const float*)¶m.x );
447 std::vector<const MODEL_3D::MATERIAL *> materialsToRender;
451 if( aModelWorldMatrix && aCameraWorldPos )
455 std::vector<std::pair<const MODEL_3D::MATERIAL*, float>> materialsSorted;
460 if( mat.m_render_idx_count == 0 )
465 if( ( mat.IsTransparent() != aTransparent )
466 && ( aOpacity >= 1.0f )
472 const BBOX_3D& bBox = mat.m_bbox;
474 const SFVEC3F bBoxWorld = *aModelWorldMatrix * glm::vec4( bBoxCenter, 1.0f );
476 const float distanceToCamera = glm::length( *aCameraWorldPos - bBoxWorld );
478 materialsSorted.emplace_back( &mat, distanceToCamera );
482 std::sort( materialsSorted.begin(), materialsSorted.end(),
483 [&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
484 std::pair<const MODEL_3D::MATERIAL*, float>& b )
486 bool aInsideB = a.first->m_bbox.Inside( b.first->m_bbox );
487 bool bInsideA = b.first->m_bbox.Inside( a.first->m_bbox );
490 if( aInsideB != bInsideA )
493 if( a.second != b.second )
494 return a.second > b.second;
496 return a.first > b.first;
499 for(
const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
501 materialsToRender.push_back( mat.first );
511 if( mat.m_render_idx_count == 0 )
516 if( ( mat.IsTransparent() != aTransparent )
517 && ( aOpacity >= 1.0f )
523 materialsToRender.push_back( &mat );
532 OglSetMaterial( *mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
542 aUseSelectedMaterial, aSelectionColor );
550 reinterpret_cast<const void*
>(
551 static_cast<uintptr_t
>( mat->m_render_idx_buffer_offset ) ) );