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