KiCad PCB EDA Suite
c_ogl_3dmodel.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 <olegendo@gcc.gnu.org>
5  * Copyright (C) 2015-2020 Mario Luzeiro <mrluzeiro@ua.pt>
6  * Copyright (C) 1992-2020 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 
31 #include <GL/glew.h>
32 #include "c_ogl_3dmodel.h"
33 #include "ogl_legacy_utils.h"
34 #include "../common_ogl/ogl_utils.h"
35 #include "../3d_math.h"
36 #include <wx/debug.h>
37 #include <chrono>
38 
39 const wxChar * C_OGL_3DMODEL::m_logTrace = wxT( "KI_TRACE_EDA_OGL_3DMODEL" );
40 
41 void C_OGL_3DMODEL::MakeBbox( const CBBOX &aBox, unsigned int aIdxOffset,
42  VERTEX *aVtxOut, GLuint *aIdxOut,
43  const glm::vec4 &aColor )
44 {
45  aVtxOut[0].m_pos = { aBox.Min().x, aBox.Min().y, aBox.Min().z };
46  aVtxOut[1].m_pos = { aBox.Max().x, aBox.Min().y, aBox.Min().z };
47  aVtxOut[2].m_pos = { aBox.Max().x, aBox.Max().y, aBox.Min().z };
48  aVtxOut[3].m_pos = { aBox.Min().x, aBox.Max().y, aBox.Min().z };
49 
50  aVtxOut[4].m_pos = { aBox.Min().x, aBox.Min().y, aBox.Max().z };
51  aVtxOut[5].m_pos = { aBox.Max().x, aBox.Min().y, aBox.Max().z };
52  aVtxOut[6].m_pos = { aBox.Max().x, aBox.Max().y, aBox.Max().z };
53  aVtxOut[7].m_pos = { aBox.Min().x, aBox.Max().y, aBox.Max().z };
54 
55  for( unsigned int i = 0; i < 8; ++i )
56  aVtxOut[i].m_color = aVtxOut[i].m_cad_color = glm::clamp( aColor * 255.0f, 0.0f, 255.0f );
57 
58  #define bbox_line( vtx_a, vtx_b )\
59  do { *aIdxOut++ = vtx_a + aIdxOffset; \
60  *aIdxOut++ = vtx_b + aIdxOffset; } while( 0 )
61 
62  bbox_line( 0, 1 );
63  bbox_line( 1, 2 );
64  bbox_line( 2, 3 );
65  bbox_line( 3, 0 );
66 
67  bbox_line( 4, 5 );
68  bbox_line( 5, 6 );
69  bbox_line( 6, 7 );
70  bbox_line( 7, 4 );
71 
72  bbox_line( 0, 4 );
73  bbox_line( 1, 5 );
74  bbox_line( 2, 6 );
75  bbox_line( 3, 7 );
76 
77  #undef bbox_line
78 }
79 
81  MATERIAL_MODE aMaterialMode )
82 {
83  wxLogTrace( m_logTrace, wxT( "C_OGL_3DMODEL::C_OGL_3DMODEL %u meshes %u materials" ),
84  static_cast<unsigned int>( a3DModel.m_MeshesSize ),
85  static_cast<unsigned int>( a3DModel.m_MaterialsSize ) );
86 
87  auto start_time = std::chrono::high_resolution_clock::now();
88 
89  // Validate a3DModel pointers
90  wxASSERT( a3DModel.m_Materials != nullptr );
91  wxASSERT( a3DModel.m_Meshes != nullptr );
92  wxASSERT( a3DModel.m_MaterialsSize > 0 );
93  wxASSERT( a3DModel.m_MeshesSize > 0 );
94 
95  m_material_mode = aMaterialMode;
96 
97  if( a3DModel.m_Materials == nullptr || a3DModel.m_Meshes == nullptr
98  || a3DModel.m_MaterialsSize == 0 || a3DModel.m_MeshesSize == 0 )
99  return;
100 
101  // create empty bbox for each mesh. it will be updated when the vertices
102  // are copied.
103  m_meshes_bbox.resize( a3DModel.m_MeshesSize );
104 
105  // copy materials for later use during rendering.
106  m_materials.reserve( a3DModel.m_MaterialsSize );
107 
108  for( unsigned int i = 0; i < a3DModel.m_MaterialsSize; ++i )
109  m_materials.emplace_back( a3DModel.m_Materials[i] );
110 
111  // build temporary vertex and index buffers for bounding boxes.
112  // the first box is the outer box.
113  std::vector<VERTEX> bbox_tmp_vertices( ( m_meshes_bbox.size() + 1 ) * bbox_vtx_count );
114  std::vector<GLuint> bbox_tmp_indices( ( m_meshes_bbox.size() + 1 ) * bbox_idx_count );
115 
116  // group all meshes by material.
117  // for each material create a combined vertex and index buffer.
118  // some models might have many sub-meshes. so iterate over the
119  // input meshes only once.
120  struct MESH_GROUP
121  {
122  std::vector<VERTEX> m_vertices;
123  std::vector<GLuint> m_indices;
124  };
125 
126  std::vector<MESH_GROUP> mesh_groups( m_materials.size() );
127 
128  for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
129  {
130  const auto& mesh = a3DModel.m_Meshes[mesh_i];
131 
132  // silently ignore meshes that have invalid material references
133  // or invalid geometry.
134  if( mesh.m_MaterialIdx >= m_materials.size()
135  || mesh.m_Positions == nullptr
136  || mesh.m_FaceIdx == nullptr
137  || mesh.m_Normals == nullptr
138  || mesh.m_FaceIdxSize == 0
139  || mesh.m_VertexSize == 0 )
140  continue;
141 
142  auto& mesh_group = mesh_groups[mesh.m_MaterialIdx];
143  auto& material = m_materials[mesh.m_MaterialIdx];
144 
145  if( material.IsTransparent() )
147  else
148  m_have_opaque_meshes = true;
149 
150  const unsigned int vtx_offset = mesh_group.m_vertices.size();
151  mesh_group.m_vertices.resize( mesh_group.m_vertices.size() + mesh.m_VertexSize );
152 
153  // copy vertex data and update the bounding box.
154  // use material color for mesh bounding box or some sort of average
155  // vertex color.
156  glm::vec3 avg_color = material.m_Diffuse;
157 
158  for( unsigned int vtx_i = 0; vtx_i < mesh.m_VertexSize; ++vtx_i )
159  {
160  m_meshes_bbox[mesh_i].Union( mesh.m_Positions[vtx_i] );
161 
162  auto& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
163 
164  vtx_out.m_pos = mesh.m_Positions[vtx_i];
165  vtx_out.m_nrm = glm::clamp( glm::vec4( mesh.m_Normals[vtx_i], 1.0f ) * 127.0f,
166  -127.0f, 127.0f );
167 
168  vtx_out.m_tex_uv = mesh.m_Texcoords != nullptr
169  ? mesh.m_Texcoords[vtx_i]
170  : glm::vec2 (0);
171 
172  if( mesh.m_Color != nullptr )
173  {
174  avg_color = ( avg_color + mesh.m_Color[vtx_i] ) * 0.5f;
175 
176  vtx_out.m_color =
177  glm::clamp( glm::vec4( mesh.m_Color[vtx_i],
178  1 - material.m_Transparency ) * 255.0f,
179  0.0f, 255.0f );
180 
181  vtx_out.m_cad_color =
182  glm::clamp( glm::vec4( MaterialDiffuseToColorCAD( mesh.m_Color[vtx_i] ),
183  1 ) * 255.0f,
184  0.0f, 255.0f );
185  }
186  else
187  {
188  // the mesh will be rendered with other meshes that might have
189  // vertex colors. thus, we can't enable/disable vertex colors
190  // for individual meshes during rendering.
191 
192  // if there are no vertex colors, use material color instead.
193  vtx_out.m_color =
194  glm::clamp( glm::vec4( material.m_Diffuse,
195  1 - material.m_Transparency ) * 255.0f,
196  0.0f, 255.0f );
197 
198  vtx_out.m_cad_color =
199  glm::clamp( glm::vec4 ( MaterialDiffuseToColorCAD( material.m_Diffuse ),
200  1 ) * 255.0f,
201  0.0f, 255.0f );
202  }
203  }
204 
205  if( m_meshes_bbox[mesh_i].IsInitialized() )
206  {
207  // generate geometry for the bounding box
208  MakeBbox( m_meshes_bbox[mesh_i], ( mesh_i + 1 ) * bbox_vtx_count,
209  &bbox_tmp_vertices[( mesh_i + 1 ) * bbox_vtx_count],
210  &bbox_tmp_indices[( mesh_i + 1 ) * bbox_idx_count],
211  { avg_color, 1.0f } );
212 
213  // bump the outer bounding box
214  m_model_bbox.Union( m_meshes_bbox[mesh_i] );
215  }
216 
217 
218  // append indices of this mesh to the mesh group.
219  const unsigned int idx_offset = mesh_group.m_indices.size();
220  unsigned int use_idx_count = mesh.m_FaceIdxSize;
221 
222  if( use_idx_count % 3 != 0 )
223  {
224  wxLogTrace( m_logTrace, wxT( " index count %u not multiple of 3, truncating" ),
225  static_cast<unsigned int>( use_idx_count ) );
226  use_idx_count = ( use_idx_count / 3 ) * 3;
227  }
228 
229  mesh_group.m_indices.resize( mesh_group.m_indices.size() + use_idx_count );
230 
231  for( unsigned int idx_i = 0; idx_i < use_idx_count; ++idx_i )
232  {
233  if( mesh.m_FaceIdx[idx_i] >= mesh.m_VertexSize )
234  {
235  wxLogTrace( m_logTrace, wxT( " index %u out of range (%u)" ),
236  static_cast<unsigned int>( mesh.m_FaceIdx[idx_i] ),
237  static_cast<unsigned int>( mesh.m_VertexSize ) );
238 
239  // FIXME: should skip this triangle
240  }
241 
242  mesh_group.m_indices[idx_offset + idx_i] = mesh.m_FaceIdx[idx_i] + vtx_offset;
243  }
244  }
245 
246  // generate geometry for the outer bounding box
248  MakeBbox( m_model_bbox, 0, &bbox_tmp_vertices[0], &bbox_tmp_indices[0],
249  { 0.0f, 1.0f, 0.0f, 1.0f } );
250 
251  // create bounding box buffers
252  glGenBuffers( 1, &m_bbox_vertex_buffer );
253  glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
254  glBufferData( GL_ARRAY_BUFFER, sizeof( VERTEX ) * bbox_tmp_vertices.size(),
255  bbox_tmp_vertices.data(), GL_STATIC_DRAW );
256 
257  glGenBuffers( 1, &m_bbox_index_buffer );
258  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
259 
260  if( bbox_tmp_vertices.size() <= std::numeric_limits<GLushort>::max() )
261  {
262  m_bbox_index_buffer_type = GL_UNSIGNED_SHORT;
263 
264  auto u16buf = std::make_unique<GLushort[]>( bbox_tmp_indices.size() );
265 
266  for( unsigned int i = 0; i < bbox_tmp_indices.size(); ++i )
267  u16buf[i] = static_cast<GLushort>( bbox_tmp_indices[i] );
268 
269  glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( GLushort ) * bbox_tmp_indices.size(),
270  u16buf.get(), GL_STATIC_DRAW );
271  }
272  else
273  {
274  m_bbox_index_buffer_type = GL_UNSIGNED_INT;
275  glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( GLuint ) * bbox_tmp_indices.size(),
276  bbox_tmp_indices.data(), GL_STATIC_DRAW );
277  }
278 
279 
280  // merge the mesh group geometry data.
281  unsigned int total_vertex_count = 0;
282  unsigned int total_index_count = 0;
283 
284  for( auto& mg : mesh_groups )
285  {
286  total_vertex_count += mg.m_vertices.size();
287  total_index_count += mg.m_indices.size();
288  }
289 
290  wxLogTrace( m_logTrace, wxT( " total %u vertices, %u indices" ),
291  total_vertex_count, total_index_count );
292 
293  glGenBuffers( 1, &m_vertex_buffer );
294  glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer );
295  glBufferData( GL_ARRAY_BUFFER, sizeof( VERTEX ) * total_vertex_count,
296  nullptr, GL_STATIC_DRAW );
297 
298  unsigned int idx_size = 0;
299 
300  if( total_vertex_count <= std::numeric_limits<GLushort>::max() )
301  {
302  m_index_buffer_type = GL_UNSIGNED_SHORT;
303  idx_size = sizeof( GLushort );
304  }
305  else
306  {
307  m_index_buffer_type = GL_UNSIGNED_INT;
308  idx_size = sizeof( GLuint );
309  }
310 
311  // temporary index buffer which will contain either GLushort or GLuint
312  // type indices. allocate with a bit of meadow at the end.
313  auto tmp_idx = std::make_unique<GLuint[]>(
314  ( idx_size * total_index_count + 8 ) / sizeof( GLuint ) );
315 
316  unsigned int prev_vtx_count = 0;
317  unsigned int idx_offset = 0;
318  unsigned int vtx_offset = 0;
319 
320  for( unsigned int mg_i = 0; mg_i < mesh_groups.size (); ++mg_i )
321  {
322  auto& mg = mesh_groups[mg_i];
323  auto& mat = m_materials[mg_i];
324 
325  if( m_index_buffer_type == GL_UNSIGNED_SHORT )
326  {
327  auto idx_out = reinterpret_cast<GLushort*>(
328  reinterpret_cast<uintptr_t>( tmp_idx.get() ) + idx_offset );
329 
330  for( auto idx : mg.m_indices )
331  *idx_out++ = static_cast<GLushort>( idx + prev_vtx_count );
332  }
333  else if( m_index_buffer_type == GL_UNSIGNED_INT )
334  {
335  auto idx_out = reinterpret_cast<GLuint*>(
336  reinterpret_cast<uintptr_t>( tmp_idx.get() ) + idx_offset );
337 
338  for( auto idx : mg.m_indices )
339  *idx_out++ = static_cast<GLuint>( idx + prev_vtx_count );
340  }
341 
342  glBufferSubData( GL_ARRAY_BUFFER,
343  vtx_offset,
344  mg.m_vertices.size() * sizeof( VERTEX ),
345  mg.m_vertices.data() );
346 
347  mat.m_render_idx_buffer_offset = idx_offset;
348  mat.m_render_idx_count = mg.m_indices.size();
349 
350  prev_vtx_count += mg.m_vertices.size();
351  idx_offset += mg.m_indices.size() * idx_size;
352  vtx_offset += mg.m_vertices.size() * sizeof( VERTEX );
353  }
354 
355  glGenBuffers( 1, &m_index_buffer );
356  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer );
357  glBufferData( GL_ELEMENT_ARRAY_BUFFER, idx_size * total_index_count,
358  tmp_idx.get(), GL_STATIC_DRAW );
359 
360  glBindBuffer( GL_ARRAY_BUFFER, 0 );
361  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
362 
363  auto end_time = std::chrono::high_resolution_clock::now();
364 
365  wxLogTrace( m_logTrace, wxT( " loaded in %u ms\n" ),
366  (unsigned int)std::chrono::duration_cast<std::chrono::milliseconds> (
367  end_time - start_time).count() );
368 }
369 
371 {
372  glEnableClientState( GL_VERTEX_ARRAY );
373  glEnableClientState( GL_NORMAL_ARRAY );
374  glEnableClientState( GL_COLOR_ARRAY );
375  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
376 
377  glEnable( GL_COLOR_MATERIAL );
378  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
379 }
380 
382 {
383  glDisable( GL_COLOR_MATERIAL );
384  glDisableClientState( GL_VERTEX_ARRAY );
385  glDisableClientState( GL_NORMAL_ARRAY );
386  glDisableClientState( GL_COLOR_ARRAY );
387  glDisableClientState( GL_TEXTURE_COORD_ARRAY );
388 
389  glBindBuffer( GL_ARRAY_BUFFER, 0 );
390  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
391 }
392 
393 
394 void C_OGL_3DMODEL::Draw( bool aTransparent, float aOpacity ) const
395 {
396  if( aOpacity <= FLT_EPSILON )
397  return;
398 
399  glBindBuffer( GL_ARRAY_BUFFER, m_vertex_buffer );
400  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_index_buffer );
401 
402  glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
403  reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
404 
405  glNormalPointer( GL_BYTE, sizeof( VERTEX ),
406  reinterpret_cast<const void*>( offsetof( VERTEX, m_nrm ) ) );
407 
408  glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
409  reinterpret_cast<const void*>(
411  ? offsetof( VERTEX, m_cad_color )
412  : offsetof( VERTEX, m_color ) ) );
413 
414  glTexCoordPointer( 2, GL_FLOAT, sizeof( VERTEX ),
415  reinterpret_cast<const void*>( offsetof( VERTEX, m_tex_uv ) ) );
416 
417  const SFVEC4F param = SFVEC4F( 1.0f, 1.0f, 1.0f, aOpacity );
418 
419  glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&param.x );
420 
421  // BeginDrawMulti();
422 
423  for( auto& mat : m_materials )
424  {
425  if( ( mat.IsTransparent() != aTransparent ) &&
426  ( aOpacity >= 1.0f ) )
427  continue;
428 
429  switch( m_material_mode )
430  {
432  OGL_SetMaterial( mat, aOpacity );
433  break;
434 
436  OGL_SetDiffuseOnlyMaterial( mat.m_Diffuse, aOpacity );
437  break;
438 
440  OGL_SetDiffuseOnlyMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ), aOpacity );
441  break;
442 
443  default:
444  break;
445  }
446 
447  glDrawElements( GL_TRIANGLES, mat.m_render_idx_count, m_index_buffer_type,
448  reinterpret_cast<const void*>( mat.m_render_idx_buffer_offset ) );
449  }
450 
451  // EndDrawMulti();
452 }
453 
455 {
456  glDeleteBuffers( 1, &m_vertex_buffer );
457  glDeleteBuffers( 1, &m_index_buffer );
458  glDeleteBuffers( 1, &m_bbox_vertex_buffer );
459  glDeleteBuffers( 1, &m_bbox_index_buffer );
460 }
461 
462 
464 {
465  glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
466  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
467 
468  glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
469  reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
470 
471  glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
472  reinterpret_cast<const void*>( offsetof( VERTEX, m_color ) ) );
473 
474  glDrawElements( GL_LINES, bbox_idx_count, m_bbox_index_buffer_type,
475  reinterpret_cast<const void*>( 0 ) );
476 }
477 
478 
480 {
481  glBindBuffer( GL_ARRAY_BUFFER, m_bbox_vertex_buffer );
482  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_bbox_index_buffer );
483 
484  glVertexPointer( 3, GL_FLOAT, sizeof( VERTEX ),
485  reinterpret_cast<const void*>( offsetof( VERTEX, m_pos ) ) );
486 
487  glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( VERTEX ),
488  reinterpret_cast<const void*>( offsetof( VERTEX, m_color ) ) );
489 
490  unsigned int idx_size = m_bbox_index_buffer_type == GL_UNSIGNED_SHORT
491  ? sizeof( GLushort ) : sizeof( GLuint );
492 
493  glDrawElements( GL_LINES, bbox_idx_count * m_meshes_bbox.size(), m_bbox_index_buffer_type,
494  reinterpret_cast<const void*>( bbox_idx_count * idx_size ) );
495 }
496 
Use a gray shading based on diffuse material.
static void EndDrawMulti()
EndDrawMulti - cleanup render states after drawing multiple models.
static constexpr unsigned int bbox_vtx_count
const SFVEC3F & Max() const
Function Max return the maximum vertex pointer.
Definition: cbbox.h:212
implement a legacy 3dmodel render
static const wxChar * m_logTrace
glm::vec4 SFVEC4F
Definition: xv3d_types.h:49
C_OGL_3DMODEL(const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode)
C_OGL_3DMODEL - Load a 3d model.
MATERIAL_MODE m_material_mode
static constexpr unsigned int bbox_idx_count
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
bool m_have_transparent_meshes
CBBOX m_model_bbox
global bounding box for this model
void Union(const SFVEC3F &aPoint)
Function Union recalculate the bounding box adding a point.
Definition: cbbox.cpp:105
Use only diffuse material properties.
Use all material properties from model file.
void Draw(bool aTransparent, float aOpacity) const
#define bbox_line(vtx_a, vtx_b)
GLenum m_bbox_index_buffer_type
static void BeginDrawMulti()
BeginDrawMulti - set some basic render states before drawing multiple models.
GLuint m_bbox_vertex_buffer
MATERIAL_MODE
Render 3d model shape materials mode.
Definition: 3d_enums.h:102
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
GLenum m_index_buffer_type
void OGL_SetMaterial(const SMATERIAL &aMaterial, float aOpacity)
OGL_SetMaterial - Set OpenGL materials.
Definition: ogl_utils.cpp:145
const SFVEC3F & Min() const
Function Min return the minimun vertex pointer.
Definition: cbbox.h:205
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:154
void Draw_bboxes() const
Draw_bboxes - draw individual bounding boxes of each mesh.
GLuint m_vertex_buffer
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
GLuint m_bbox_index_buffer
std::vector< MATERIAL > m_materials
static void MakeBbox(const CBBOX &aBox, unsigned int aIdxOffset, VERTEX *aVtxOut, GLuint *aIdxOut, const glm::vec4 &aColor)
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
GLuint m_index_buffer
void Draw_bbox() const
Draw_bbox - draw main bounding box of the model.
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
std::vector< CBBOX > m_meshes_bbox
individual bbox for each mesh
bool m_have_opaque_meshes
CBBOX manages a bounding box defined by two SFVEC3F min max points.
Definition: cbbox.h:40
void OGL_SetDiffuseOnlyMaterial(const SFVEC3F &aMaterialDiffuse, float aOpacity)
OGL_SetDiffuseOnlyMaterial - sets only the diffuse color and keep other parameters with default value...
Definition: ogl_utils.cpp:169
bool IsInitialized() const
Function IsInitialized check if this bounding box is already initialized.
Definition: cbbox.cpp:87