KiCad PCB EDA Suite
Loading...
Searching...
No Matches
3d_model.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Oleg Endo <[email protected]>
5 * Copyright (C) 2015-2020 Mario Luzeiro <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
29#include <algorithm>
30#include <stdexcept>
31#include <gal/opengl/kiglew.h> // Must be included first
32
33#include "3d_model.h"
34#include "../common_ogl/ogl_utils.h"
35#include "../3d_math.h"
36#include <utility>
37#include <wx/debug.h>
38#include <wx/log.h>
39#include <chrono>
40#include <memory>
41
42
43/*
44 * Flag to enable connectivity profiling.
45 *
46 * @ingroup trace_env_vars
47 */
48const wxChar* MODEL_3D::m_logTrace = wxT( "KI_TRACE_EDA_OGL_3DMODEL" );
49
50
51void MODEL_3D::MakeBbox( const BBOX_3D& aBox, unsigned int aIdxOffset, VERTEX* aVtxOut,
52 GLuint* aIdxOut, const glm::vec4& aColor )
53{
54 aVtxOut[0].m_pos = { aBox.Min().x, aBox.Min().y, aBox.Min().z };
55 aVtxOut[1].m_pos = { aBox.Max().x, aBox.Min().y, aBox.Min().z };
56 aVtxOut[2].m_pos = { aBox.Max().x, aBox.Max().y, aBox.Min().z };
57 aVtxOut[3].m_pos = { aBox.Min().x, aBox.Max().y, aBox.Min().z };
58
59 aVtxOut[4].m_pos = { aBox.Min().x, aBox.Min().y, aBox.Max().z };
60 aVtxOut[5].m_pos = { aBox.Max().x, aBox.Min().y, aBox.Max().z };
61 aVtxOut[6].m_pos = { aBox.Max().x, aBox.Max().y, aBox.Max().z };
62 aVtxOut[7].m_pos = { aBox.Min().x, aBox.Max().y, aBox.Max().z };
63
64 for( unsigned int i = 0; i < 8; ++i )
65 aVtxOut[i].m_color = aVtxOut[i].m_cad_color = glm::clamp( aColor * 255.0f, 0.0f, 255.0f );
66
67 #define bbox_line( vtx_a, vtx_b )\
68 do { *aIdxOut++ = vtx_a + aIdxOffset; \
69 *aIdxOut++ = vtx_b + aIdxOffset; } while( 0 )
70
71 bbox_line( 0, 1 );
72 bbox_line( 1, 2 );
73 bbox_line( 2, 3 );
74 bbox_line( 3, 0 );
75
76 bbox_line( 4, 5 );
77 bbox_line( 5, 6 );
78 bbox_line( 6, 7 );
79 bbox_line( 7, 4 );
80
81 bbox_line( 0, 4 );
82 bbox_line( 1, 5 );
83 bbox_line( 2, 6 );
84 bbox_line( 3, 7 );
85
86 #undef bbox_line
87}
88
89
90MODEL_3D::MODEL_3D( const S3DMODEL& a3DModel, MATERIAL_MODE aMaterialMode )
91{
92 wxLogTrace( m_logTrace, wxT( "MODEL_3D::MODEL_3D %u meshes %u materials" ),
93 static_cast<unsigned int>( a3DModel.m_MeshesSize ),
94 static_cast<unsigned int>( a3DModel.m_MaterialsSize ) );
95
96 auto start_time = std::chrono::high_resolution_clock::now();
97 GLuint buffers[8];
98
106 glGenBuffers( 6, buffers );
107 m_bbox_vertex_buffer = buffers[2];
108 m_bbox_index_buffer = buffers[3];
109 m_vertex_buffer = buffers[4];
110 m_index_buffer = buffers[5];
111
112 // Validate a3DModel pointers
113 wxASSERT( a3DModel.m_Materials != nullptr );
114 wxASSERT( a3DModel.m_Meshes != nullptr );
115 wxASSERT( a3DModel.m_MaterialsSize > 0 );
116 wxASSERT( a3DModel.m_MeshesSize > 0 );
117
118 m_materialMode = aMaterialMode;
119
120 if( a3DModel.m_Materials == nullptr || a3DModel.m_Meshes == nullptr
121 || a3DModel.m_MaterialsSize == 0 || a3DModel.m_MeshesSize == 0 )
122 return;
123
124 // create empty bbox for each mesh. it will be updated when the vertices are copied.
125 m_meshes_bbox.resize( a3DModel.m_MeshesSize );
126
127 // copy materials for later use during rendering.
128 m_materials.reserve( a3DModel.m_MaterialsSize );
129
130 for( unsigned int i = 0; i < a3DModel.m_MaterialsSize; ++i )
131 m_materials.emplace_back( a3DModel.m_Materials[i] );
132
133 // build temporary vertex and index buffers for bounding boxes.
134 // the first box is the outer box.
135 std::vector<VERTEX> bbox_tmp_vertices( ( m_meshes_bbox.size() + 1 ) * bbox_vtx_count );
136 std::vector<GLuint> bbox_tmp_indices( ( m_meshes_bbox.size() + 1 ) * bbox_idx_count );
137
138 // group all meshes by material.
139 // for each material create a combined vertex and index buffer.
140 // some models might have many sub-meshes. so iterate over the
141 // input meshes only once.
142 struct MESH_GROUP
143 {
144 std::vector<VERTEX> m_vertices;
145 std::vector<GLuint> m_indices;
146 };
147
148 std::vector<MESH_GROUP> mesh_groups( m_materials.size() );
149
150 for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
151 {
152 const SMESH& mesh = a3DModel.m_Meshes[mesh_i];
153
154 // silently ignore meshes that have invalid material references or invalid geometry.
155 if( mesh.m_MaterialIdx >= m_materials.size()
156 || mesh.m_Positions == nullptr
157 || mesh.m_FaceIdx == nullptr
158 || mesh.m_Normals == nullptr
159 || mesh.m_FaceIdxSize == 0
160 || mesh.m_VertexSize == 0 )
161 {
162 continue;
163 }
164
165 MESH_GROUP& mesh_group = mesh_groups[mesh.m_MaterialIdx];
166 MATERIAL& material = m_materials[mesh.m_MaterialIdx];
167
168 if( material.IsTransparent() && m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
170 else
172
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 );
175
176 // copy vertex data and update the bounding box.
177 // use material color for mesh bounding box or some sort of average vertex color.
178 glm::vec3 avg_color = material.m_Diffuse;
179
180 BBOX_3D &mesh_bbox = m_meshes_bbox[mesh_i];
181
182 for( unsigned int vtx_i = 0; vtx_i < mesh.m_VertexSize; ++vtx_i )
183 {
184 mesh_bbox.Union( mesh.m_Positions[vtx_i] );
185
186 VERTEX& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
187
188 vtx_out.m_pos = mesh.m_Positions[vtx_i];
189 vtx_out.m_nrm = glm::clamp( glm::vec4( mesh.m_Normals[vtx_i], 1.0f ) * 127.0f,
190 -127.0f, 127.0f );
191
192 vtx_out.m_tex_uv = mesh.m_Texcoords != nullptr ? mesh.m_Texcoords[vtx_i]
193 : glm::vec2 (0);
194
195 if( mesh.m_Color != nullptr )
196 {
197 avg_color = ( avg_color + mesh.m_Color[vtx_i] ) * 0.5f;
198
199 vtx_out.m_color =
200 glm::clamp( glm::vec4( mesh.m_Color[vtx_i],
201 1 - material.m_Transparency ) * 255.0f,
202 0.0f, 255.0f );
203
204 vtx_out.m_cad_color =
205 glm::clamp( glm::vec4( MaterialDiffuseToColorCAD( mesh.m_Color[vtx_i] ),
206 1 ) * 255.0f, 0.0f, 255.0f );
207 }
208 else
209 {
210 // the mesh will be rendered with other meshes that might have
211 // vertex colors. thus, we can't enable/disable vertex colors
212 // for individual meshes during rendering.
213
214 // if there are no vertex colors, use material color instead.
215 vtx_out.m_color =
216 glm::clamp( glm::vec4( material.m_Diffuse,
217 1 - material.m_Transparency ) * 255.0f,
218 0.0f, 255.0f );
219
220 vtx_out.m_cad_color =
221 glm::clamp( glm::vec4 ( MaterialDiffuseToColorCAD( material.m_Diffuse ),
222 1 ) * 255.0f,
223 0.0f, 255.0f );
224 }
225 }
226
227 if( mesh_bbox.IsInitialized() )
228 {
229 // generate geometry for the bounding box
230 MakeBbox( mesh_bbox, ( mesh_i + 1 ) * bbox_vtx_count,
231 &bbox_tmp_vertices[( mesh_i + 1 ) * bbox_vtx_count],
232 &bbox_tmp_indices[( mesh_i + 1 ) * bbox_idx_count],
233 { avg_color, 1.0f } );
234
235 // bump the outer bounding box
236 m_model_bbox.Union( mesh_bbox );
237
238 // add to the material group
239 material.m_bbox.Union( mesh_bbox );
240 }
241
242
243 // append indices of this mesh to the mesh group.
244 const unsigned int idx_offset = mesh_group.m_indices.size();
245 unsigned int use_idx_count = mesh.m_FaceIdxSize;
246
247 if( use_idx_count % 3 != 0 )
248 {
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;
252 }
253
254 mesh_group.m_indices.resize( mesh_group.m_indices.size() + use_idx_count );
255
256 for( unsigned int idx_i = 0; idx_i < use_idx_count; ++idx_i )
257 {
258 if( mesh.m_FaceIdx[idx_i] >= mesh.m_VertexSize )
259 {
260 wxLogTrace( m_logTrace, wxT( " index %u out of range (%u)" ),
261 static_cast<unsigned int>( mesh.m_FaceIdx[idx_i] ),
262 static_cast<unsigned int>( mesh.m_VertexSize ) );
263
264 // FIXME: should skip this triangle
265 }
266
267 mesh_group.m_indices[idx_offset + idx_i] = mesh.m_FaceIdx[idx_i] + vtx_offset;
268 }
269 }
270
271 // generate geometry for the outer bounding box
273 MakeBbox( m_model_bbox, 0, &bbox_tmp_vertices[0], &bbox_tmp_indices[0],
274 { 0.0f, 1.0f, 0.0f, 1.0f } );
275
276 // create bounding box buffers
277 glGenBuffers( 1, &m_bbox_vertex_buffer );
278 glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
279 glBufferData( GL_ARRAY_BUFFER, sizeof( VERTEX ) * bbox_tmp_vertices.size(),
280 bbox_tmp_vertices.data(), GL_STATIC_DRAW );
281
282 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
283
284 if( bbox_tmp_vertices.size() <= std::numeric_limits<GLushort>::max() )
285 {
286 m_bbox_index_buffer_type = GL_UNSIGNED_SHORT;
287
288 auto u16buf = std::make_unique<GLushort[]>( bbox_tmp_indices.size() );
289
290 for( unsigned int i = 0; i < bbox_tmp_indices.size(); ++i )
291 u16buf[i] = static_cast<GLushort>( bbox_tmp_indices[i] );
292
293 glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( GLushort ) * bbox_tmp_indices.size(),
294 u16buf.get(), GL_STATIC_DRAW );
295 }
296 else
297 {
298 m_bbox_index_buffer_type = GL_UNSIGNED_INT;
299 glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( GLuint ) * bbox_tmp_indices.size(),
300 bbox_tmp_indices.data(), GL_STATIC_DRAW );
301 }
302
303 // merge the mesh group geometry data.
304 unsigned int total_vertex_count = 0;
305 unsigned int total_index_count = 0;
306
307 for( const MESH_GROUP& mg : mesh_groups )
308 {
309 total_vertex_count += mg.m_vertices.size();
310 total_index_count += mg.m_indices.size();
311 }
312
313 wxLogTrace( m_logTrace, wxT( " total %u vertices, %u indices" ),
314 total_vertex_count, total_index_count );
315
316 glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer );
317 glBufferData( GL_ARRAY_BUFFER, sizeof( VERTEX ) * total_vertex_count,
318 nullptr, GL_STATIC_DRAW );
319
320 unsigned int idx_size = 0;
321
322 if( total_vertex_count <= std::numeric_limits<GLushort>::max() )
323 {
324 m_index_buffer_type = GL_UNSIGNED_SHORT;
325 idx_size = sizeof( GLushort );
326 }
327 else
328 {
329 m_index_buffer_type = GL_UNSIGNED_INT;
330 idx_size = sizeof( GLuint );
331 }
332
333 // temporary index buffer which will contain either GLushort or GLuint
334 // type indices. allocate with a bit of meadow at the end.
335 auto tmp_idx =
336 std::make_unique<GLuint[]>( ( idx_size * total_index_count + 8 ) / sizeof( GLuint ) );
337
338 unsigned int prev_vtx_count = 0;
339 unsigned int idx_offset = 0;
340 unsigned int vtx_offset = 0;
341
342 for( unsigned int mg_i = 0; mg_i < mesh_groups.size (); ++mg_i )
343 {
344 MESH_GROUP& mg = mesh_groups[mg_i];
345 MATERIAL& mat = m_materials[mg_i];
346 uintptr_t tmp_idx_ptr = reinterpret_cast<uintptr_t>( tmp_idx.get() );
347
348 if( m_index_buffer_type == GL_UNSIGNED_SHORT )
349 {
350 GLushort* idx_out = reinterpret_cast<GLushort*>( tmp_idx_ptr + idx_offset );
351
352 for( GLuint idx : mg.m_indices )
353 *idx_out++ = static_cast<GLushort>( idx + prev_vtx_count );
354 }
355 else if( m_index_buffer_type == GL_UNSIGNED_INT )
356 {
357 GLuint* idx_out = reinterpret_cast<GLuint*>( tmp_idx_ptr + idx_offset );
358
359 for( GLuint idx : mg.m_indices )
360 *idx_out++ = static_cast<GLuint>( idx + prev_vtx_count );
361 }
362
363 glBufferSubData( GL_ARRAY_BUFFER, vtx_offset, mg.m_vertices.size() * sizeof( VERTEX ),
364 mg.m_vertices.data() );
365
366 mat.m_render_idx_buffer_offset = idx_offset;
367 mat.m_render_idx_count = mg.m_indices.size();
368
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 );
372 }
373
374 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer );
375 glBufferData( GL_ELEMENT_ARRAY_BUFFER, idx_size * total_index_count, tmp_idx.get(),
376 GL_STATIC_DRAW );
377
378 glBindBuffer( GL_ARRAY_BUFFER, 0 );
379 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
380
381 auto end_time = std::chrono::high_resolution_clock::now();
382
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() );
386}
387
388
389void MODEL_3D::BeginDrawMulti( bool aUseColorInformation )
390{
391 glEnableClientState( GL_VERTEX_ARRAY );
392 glEnableClientState( GL_NORMAL_ARRAY );
393
394 if( aUseColorInformation )
395 {
396 glEnableClientState( GL_COLOR_ARRAY );
397 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
398 glEnable( GL_COLOR_MATERIAL );
399 }
400
401 glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
402}
403
404
406{
407 glDisable( GL_COLOR_MATERIAL );
408 glDisableClientState( GL_VERTEX_ARRAY );
409 glDisableClientState( GL_NORMAL_ARRAY );
410 glDisableClientState( GL_COLOR_ARRAY );
411 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
412
413 glBindBuffer( GL_ARRAY_BUFFER, 0 );
414 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
415}
416
417
418void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
419 const SFVEC3F& aSelectionColor,
420 const glm::mat4 *aModelWorldMatrix,
421 const SFVEC3F *aCameraWorldPos ) const
422{
423 if( aOpacity <= FLT_EPSILON )
424 return;
425
426 if( !glBindBuffer )
427 throw std::runtime_error( "The OpenGL context no longer exists: unable to draw" );
428
429 glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer );
430 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer );
431
432 glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
433 reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
434
435 glNormalPointer( GL_BYTE, sizeof( VERTEX ),
436 reinterpret_cast<const void*>( offsetof( VERTEX, m_nrm ) ) );
437
438 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
439 reinterpret_cast<const void*>( m_materialMode == MATERIAL_MODE::CAD_MODE
440 ? offsetof( VERTEX, m_cad_color )
441 : offsetof( VERTEX, m_color ) ) );
442
443 glTexCoordPointer( 2, GL_FLOAT, sizeof( VERTEX ),
444 reinterpret_cast<const void*>( offsetof( VERTEX, m_tex_uv ) ) );
445
446 const SFVEC4F param = SFVEC4F( 1.0f, 1.0f, 1.0f, aOpacity );
447
448 glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&param.x );
449
450 std::vector<const MODEL_3D::MATERIAL *> materialsToRender;
451
452 materialsToRender.reserve( m_materials.size() );
453
454 if( aModelWorldMatrix && aCameraWorldPos )
455 {
456 // Sort Material groups
457
458 std::vector<std::pair<const MODEL_3D::MATERIAL*, float>> materialsSorted;
459
460 // Calculate the distance to the camera for each material group
461 for( const MODEL_3D::MATERIAL& mat : m_materials )
462 {
463 if( mat.m_render_idx_count == 0 )
464 {
465 continue;
466 }
467
468 if( ( mat.IsTransparent() != aTransparent )
469 && ( aOpacity >= 1.0f )
470 && m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
471 {
472 continue;
473 }
474
475 const BBOX_3D& bBox = mat.m_bbox;
476 const SFVEC3F& bBoxCenter = bBox.GetCenter();
477 const SFVEC3F bBoxWorld = *aModelWorldMatrix * glm::vec4( bBoxCenter, 1.0f );
478
479 const float distanceToCamera = glm::length( *aCameraWorldPos - bBoxWorld );
480
481 materialsSorted.emplace_back( &mat, distanceToCamera );
482 }
483
484 // Sort from back to front
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 )
488 {
489 bool aInsideB = a.first->m_bbox.Inside( b.first->m_bbox );
490 bool bInsideA = b.first->m_bbox.Inside( a.first->m_bbox );
491
492 // If A is inside B, then A is rendered first
493 if( aInsideB != bInsideA )
494 return bInsideA;
495
496 if( a.second != b.second )
497 return a.second > b.second;
498
499 return a.first > b.first; // compare pointers as a last resort
500 } );
501
502 for( const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
503 {
504 materialsToRender.push_back( mat.first );
505 }
506 }
507 else
508 {
509 for( const MODEL_3D::MATERIAL& mat : m_materials )
510 {
511 // There is at least one default material created in case a mesh has no declared
512 // materials. Most meshes have a material, so usually the first material will have
513 // nothing to render and is skip. See S3D::GetModel for more details.
514 if( mat.m_render_idx_count == 0 )
515 {
516 continue;
517 }
518
519 if( ( mat.IsTransparent() != aTransparent )
520 && ( aOpacity >= 1.0f )
521 && m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
522 {
523 continue;
524 }
525
526 materialsToRender.push_back( &mat );
527 }
528 }
529
530 for( const MODEL_3D::MATERIAL* mat : materialsToRender )
531 {
532 switch( m_materialMode )
533 {
534 case MATERIAL_MODE::NORMAL:
535 OglSetMaterial( *mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
536 break;
537
538 case MATERIAL_MODE::DIFFUSE_ONLY:
539 OglSetDiffuseMaterial( mat->m_Diffuse, aOpacity, aUseSelectedMaterial,
540 aSelectionColor );
541 break;
542
543 case MATERIAL_MODE::CAD_MODE:
544 OglSetDiffuseMaterial( MaterialDiffuseToColorCAD( mat->m_Diffuse ), aOpacity,
545 aUseSelectedMaterial, aSelectionColor );
546 break;
547
548 default:
549 break;
550 }
551
552 glDrawElements( GL_TRIANGLES, mat->m_render_idx_count, m_index_buffer_type,
553 reinterpret_cast<const void*>(
554 static_cast<uintptr_t>( mat->m_render_idx_buffer_offset ) ) );
555 }
556}
557
558
560{
561 if( glDeleteBuffers )
562 {
563 glDeleteBuffers( 1, &m_vertex_buffer );
564 glDeleteBuffers( 1, &m_index_buffer );
565 glDeleteBuffers( 1, &m_bbox_vertex_buffer );
566 glDeleteBuffers( 1, &m_bbox_index_buffer );
567 }
568}
569
570
572{
573 if( !glBindBuffer )
574 throw std::runtime_error( "The OpenGL context no longer exists: unable to draw bbox" );
575
576 glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
577 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
578
579 glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
580 reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
581
582 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
583 reinterpret_cast<const void*>( offsetof( VERTEX, m_color ) ) );
584
585 glDrawElements( GL_LINES, bbox_idx_count, m_bbox_index_buffer_type,
586 reinterpret_cast<const void*>( 0 ) );
587}
588
589
591{
592 if( !glBindBuffer )
593 throw std::runtime_error( "The OpenGL context no longer exists: unable to draw bboxes" );
594
595 glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
596 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
597
598 glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
599 reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
600
601 glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
602 reinterpret_cast<const void*>( offsetof( VERTEX, m_color ) ) );
603
604 unsigned int idx_size = m_bbox_index_buffer_type == GL_UNSIGNED_SHORT ? sizeof( GLushort )
605 : sizeof( GLuint );
606
607 glDrawElements( GL_LINES, bbox_idx_count * m_meshes_bbox.size(), m_bbox_index_buffer_type,
608 reinterpret_cast<const void*>(
609 static_cast<uintptr_t>( bbox_idx_count * idx_size ) ) );
610}
611
MATERIAL_MODE
Render 3d model shape materials mode.
Definition: 3d_enums.h:71
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:147
#define bbox_line(vtx_a, vtx_b)
GLuint m_vertex_buffer
Definition: 3d_model.h:138
void DrawBbox() const
Draw main bounding box of the model.
Definition: 3d_model.cpp:571
bool m_have_opaque_meshes
Definition: 3d_model.h:161
static void EndDrawMulti()
Cleanup render states after drawing multiple models.
Definition: 3d_model.cpp:405
GLenum m_index_buffer_type
Definition: 3d_model.h:140
MODEL_3D(const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode)
Load a 3D model.
Definition: 3d_model.cpp:90
std::vector< MATERIAL > m_materials
Definition: 3d_model.h:156
static void MakeBbox(const BBOX_3D &aBox, unsigned int aIdxOffset, VERTEX *aVtxOut, GLuint *aIdxOut, const glm::vec4 &aColor)
Definition: 3d_model.cpp:51
GLuint m_index_buffer
Definition: 3d_model.h:139
void Draw(bool aTransparent, float aOpacity, bool aUseSelectedMaterial, const SFVEC3F &aSelectionColor, const glm::mat4 *aModelWorldMatrix, const SFVEC3F *aCameraWorldPos) const
Render the model into the current context.
Definition: 3d_model.cpp:418
static void BeginDrawMulti(bool aUseColorInformation)
Set some basic render states before drawing multiple models.
Definition: 3d_model.cpp:389
GLuint m_bbox_index_buffer
Definition: 3d_model.h:170
static constexpr unsigned int bbox_idx_count
Definition: 3d_model.h:167
MATERIAL_MODE m_materialMode
Definition: 3d_model.h:121
void DrawBboxes() const
Draw individual bounding boxes of each mesh.
Definition: 3d_model.cpp:590
static const wxChar * m_logTrace
Definition: 3d_model.h:116
bool m_have_transparent_meshes
Definition: 3d_model.h:162
std::vector< BBOX_3D > m_meshes_bbox
individual bbox for each mesh
Definition: 3d_model.h:124
GLenum m_bbox_index_buffer_type
Definition: 3d_model.h:171
static constexpr unsigned int bbox_vtx_count
Definition: 3d_model.h:166
BBOX_3D m_model_bbox
global bounding box for this model
Definition: 3d_model.h:123
GLuint m_bbox_vertex_buffer
Definition: 3d_model.h:169
void OglSetDiffuseMaterial(const SFVEC3F &aMaterialDiffuse, float aOpacity, bool aUseSelectedMaterial, SFVEC3F aSelectionColor)
Sets only the diffuse color and keep other parameters with default values.
Definition: ogl_utils.cpp:168
void OglSetMaterial(const SMATERIAL &aMaterial, float aOpacity, bool aUseSelectedMaterial, SFVEC3F aSelectionColor)
Set OpenGL materials.
Definition: ogl_utils.cpp:144
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:43
void Union(const SFVEC3F &aPoint)
Recalculate the bounding box adding a point.
Definition: bbox_3d.cpp:102
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition: bbox_3d.cpp:132
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:192
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:199
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition: bbox_3d.cpp:88
bool IsTransparent() const
Definition: 3d_model.h:153
unsigned int m_render_idx_count
Definition: 3d_model.h:147
BBOX_3D m_bbox
bounding box for this material group, used for transparent material ordering.
Definition: 3d_model.h:149
unsigned int m_render_idx_buffer_offset
Definition: 3d_model.h:146
glm::vec3 m_pos
Definition: 3d_model.h:129
glm::vec2 m_tex_uv
Definition: 3d_model.h:133
glm::u8vec4 m_cad_color
Definition: 3d_model.h:132
glm::u8vec4 m_color
Definition: 3d_model.h:131
glm::u8vec4 m_nrm
Definition: 3d_model.h:130
Store the a model based on meshes and materials.
Definition: c3dmodel.h:95
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:100
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:96
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:97
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:99
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:81
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:88
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:84
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:89
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:82
SFVEC2F * m_Texcoords
Vertex texture coordinates array, can be NULL.
Definition: c3dmodel.h:85
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:87
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:86
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:83
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
glm::vec4 SFVEC4F
Definition: xv3d_types.h:46