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) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include "c_ogl_3dmodel.h"
31 #include "ogl_legacy_utils.h"
32 #include "../common_ogl/ogl_utils.h"
33 #include "../3d_math.h"
34 #include <wx/debug.h>
35 
36 
38  MATERIAL_MODE aMaterialMode )
39 {
43  m_nr_meshes = 0;
44  m_meshs_bbox = NULL;
45 
46  // Validate a3DModel pointers
47  wxASSERT( a3DModel.m_Materials != NULL );
48  wxASSERT( a3DModel.m_Meshes != NULL );
49  wxASSERT( a3DModel.m_MaterialsSize > 0 );
50  wxASSERT( a3DModel.m_MeshesSize > 0 );
51 
52  if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
53  (a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
54  {
55  m_nr_meshes = a3DModel.m_MeshesSize;
56 
57  m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize];
58 
59  // Generate m_MeshesSize auxiliar lists to render the meshes
60  m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
61 
62  // Render each mesh of the model
63  // /////////////////////////////////////////////////////////////////////
64  for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
65  {
66  if( glIsList( m_ogl_idx_list_meshes + mesh_i ) )
67  {
68  const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
69 
70  // Validate the mesh pointers
71  wxASSERT( mesh.m_Positions != NULL );
72  wxASSERT( mesh.m_FaceIdx != NULL );
73  wxASSERT( mesh.m_Normals != NULL );
74 
75  if( (mesh.m_Positions != NULL) &&
76  (mesh.m_Normals != NULL) &&
77  (mesh.m_FaceIdx != NULL) &&
78  (mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) )
79  {
80  SFVEC4F *pColorRGBA = NULL;
81 
82  // Create the bbox for this mesh
83  // /////////////////////////////////////////////////////////
84  m_meshs_bbox[mesh_i].Reset();
85 
86  for( unsigned int vertex_i = 0;
87  vertex_i < mesh.m_VertexSize;
88  ++vertex_i )
89  {
90  m_meshs_bbox[mesh_i].Union( mesh.m_Positions[vertex_i] );
91  }
92 
93  // Make sure we start with client state disabled
94  // /////////////////////////////////////////////////////////
95  glDisableClientState( GL_TEXTURE_COORD_ARRAY );
96  glDisableClientState( GL_COLOR_ARRAY );
97 
98 
99  // Enable arrays client states
100  // /////////////////////////////////////////////////////////
101  glEnableClientState( GL_VERTEX_ARRAY );
102  glEnableClientState( GL_NORMAL_ARRAY );
103 
104  glVertexPointer( 3, GL_FLOAT, 0, mesh.m_Positions );
105  glNormalPointer( GL_FLOAT, 0, mesh.m_Normals );
106 
107  if( mesh.m_Color != NULL )
108  {
109  glEnableClientState( GL_COLOR_ARRAY );
110 
111  float transparency = 0.0f;
112 
113  if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
114  transparency = a3DModel.m_Materials[mesh.m_MaterialIdx].m_Transparency;
115 
116  if( (transparency > FLT_EPSILON) &&
117  (aMaterialMode == MATERIAL_MODE_NORMAL) )
118  {
119  // Create a new array of RGBA colors
120  pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
121 
122  // Copy RGB array and add the Alpha value
123  for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
124  pColorRGBA[i] = SFVEC4F( mesh.m_Color[i],
125  1.0f - transparency );
126 
127  // Load an RGBA array
128  glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
129  }
130  else
131  {
132  switch( aMaterialMode )
133  {
136  // load the original RGB color array
137  glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color );
138  break;
140  // Create a new array of RGBA colors
141  pColorRGBA = new SFVEC4F[mesh.m_VertexSize];
142 
143  // Copy RGB array and add the Alpha value
144  for( unsigned int i = 0; i < mesh.m_VertexSize; ++i )
145  {
146  pColorRGBA[i] =
148  1.0f );
149  }
150 
151  // Load an RGBA array
152  glColorPointer( 4, GL_FLOAT, 0, pColorRGBA );
153  break;
154  default:
155  break;
156  }
157  }
158  }
159 
160  if( mesh.m_Texcoords != NULL )
161  {
162  glEnableClientState( GL_TEXTURE_COORD_ARRAY );
163  glTexCoordPointer( 2, GL_FLOAT, 0, mesh.m_Texcoords );
164  }
165 
166  // Compile the display list to store triangles
167  // /////////////////////////////////////////////////////////
168  glNewList( m_ogl_idx_list_meshes + mesh_i, GL_COMPILE );
169 
170  // Set material properties
171  // /////////////////////////////////////////////////////////
172 
173  if( mesh.m_Color != NULL )
174  {
175  // This enables the use of the Color Pointer information
176  glEnable( GL_COLOR_MATERIAL );
177  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
178  }
179  else
180  {
181  glDisable( GL_COLOR_MATERIAL );
182  }
183 
184  if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
185  {
186  switch( aMaterialMode )
187  {
189  OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] );
190  break;
193  a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse );
194  break;
198  a3DModel.m_Materials[mesh.m_MaterialIdx].m_Diffuse ) );
199  break;
200  default:
201  break;
202  }
203  }
204 
205  // Draw mesh
206  // /////////////////////////////////////////////////////////
207  glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize,
208  GL_UNSIGNED_INT, mesh.m_FaceIdx );
209 
210  glDisable( GL_COLOR_MATERIAL );
211 
212  glEndList();
213 
214  // Disable arrays client states
215  // /////////////////////////////////////////////////////////
216  glDisableClientState( GL_TEXTURE_COORD_ARRAY );
217  glDisableClientState( GL_COLOR_ARRAY );
218  glDisableClientState( GL_NORMAL_ARRAY );
219  glDisableClientState( GL_VERTEX_ARRAY );
220 
221  glFinish();
222 
223  delete [] pColorRGBA;
224  }
225  }
226  }// for each mesh
227 
228 
229  m_ogl_idx_list_opaque = glGenLists( 1 );
230 
231  // Check if the generated list is valid
232  if( glIsList( m_ogl_idx_list_opaque ) )
233  {
234  bool have_opaque_meshes = false;
235  bool have_transparent_meshes = false;
236 
237  // Compile the model display list
238  glNewList( m_ogl_idx_list_opaque, GL_COMPILE );
239 
240  // Render each mesh display list (opaque first)
241  // /////////////////////////////////////////////////////////////////
242  for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
243  {
244  const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
245 
246  if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
247  {
248  const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
249 
250  if( material.m_Transparency == 0.0f )
251  {
252  have_opaque_meshes = true; // Flag that we have at least one opaque mesh
253  glCallList( m_ogl_idx_list_meshes + mesh_i );
254  }
255  else
256  {
257  have_transparent_meshes = true; // Flag that we found a transparent mesh
258  }
259  }
260  }
261 
262  glEndList();
263 
264  if( !have_opaque_meshes )
265  {
266  // If we dont have opaque meshes, we can free the list
267  glDeleteLists( m_ogl_idx_list_opaque, 1 );
269  }
270 
271  if( have_transparent_meshes )
272  {
273  m_ogl_idx_list_transparent = glGenLists( 1 );
274 
275  // Check if the generated list is valid
276  if( glIsList( m_ogl_idx_list_transparent ) )
277  {
278  // Compile the model display list
279  glNewList( m_ogl_idx_list_transparent, GL_COMPILE );
280 
281  glEnable( GL_BLEND );
282  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
283 
284  // Render each mesh display list
285  // /////////////////////////////////////////////////////////
286  for( unsigned mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
287  {
288  const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
289 
290  if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
291  {
292  const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
293 
294  // Render the transparent mesh if it have a transparency value
295  if( material.m_Transparency != 0.0f )
296  glCallList( m_ogl_idx_list_meshes + mesh_i );
297  }
298  }
299 
300  glDisable( GL_BLEND );
301 
302  glEndList();
303  }
304  else
305  {
307  }
308  }
309  }
310  else
311  {
313  }
314 
315  // Create the main bbox
316  // /////////////////////////////////////////////////////////////////////
318 
319  for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
320  m_model_bbox.Union( m_meshs_bbox[mesh_i] );
321 
322  glFinish();
323  }
324 }
325 
326 
328 {
329  if( glIsList( m_ogl_idx_list_opaque ) )
330  glCallList( m_ogl_idx_list_opaque );
331 }
332 
333 
335 {
336  if( glIsList( m_ogl_idx_list_transparent ) )
337  glCallList( m_ogl_idx_list_transparent );
338 }
339 
340 
342 {
343  if( glIsList( m_ogl_idx_list_opaque ) )
344  glDeleteLists( m_ogl_idx_list_opaque, 1 );
345 
346  if( glIsList( m_ogl_idx_list_transparent ) )
347  glDeleteLists( m_ogl_idx_list_transparent, 1 );
348 
349  if( glIsList( m_ogl_idx_list_meshes ) )
350  glDeleteLists( m_ogl_idx_list_meshes, m_nr_meshes );
351 
355 
356  delete[] m_meshs_bbox;
357  m_meshs_bbox = NULL;
358 }
359 
360 
362 {
364 }
365 
366 
368 {
369  for( unsigned int mesh_i = 0; mesh_i < m_nr_meshes; ++mesh_i )
370  OGL_draw_bbox( m_meshs_bbox[mesh_i] );
371 }
372 
373 
375 {
376  return glIsList( m_ogl_idx_list_opaque );
377 }
378 
379 
381 {
382  return glIsList( m_ogl_idx_list_transparent );
383 }
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
Use only diffuse material properties.
Definition: 3d_enums.h:93
implement a legacy 3dmodel render
unsigned int m_nr_meshes
number of meshes of this model
Definition: c_ogl_3dmodel.h:91
bool Have_transparent() const
Have_transparent - return true if have transparent meshs to render.
glm::vec4 SFVEC4F
Definition: xv3d_types.h:49
C_OGL_3DMODEL(const S3DMODEL &a3DModel, MATERIAL_MODE aMaterialMode)
C_OGL_3DMODEL - Load a 3d model.
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
void Draw_transparent() const
Draw_transparent - render the model into the current context.
void Draw_opaque() const
Draw_opaque - render the model into the current context.
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
GLuint m_ogl_idx_list_transparent
display list for rendering transparent meshes
Definition: c_ogl_3dmodel.h:89
void Draw_bbox() const
Draw_bbox - draw main bounding box of the model.
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
CBBOX m_model_bbox
global bounding box for this model
Definition: c_ogl_3dmodel.h:93
void Union(const SFVEC3F &aPoint)
Function Union recalculate the bounding box adding a point.
Definition: cbbox.cpp:105
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
void OGL_SetMaterial(const SMATERIAL &aMaterial)
OGL_SetMaterial - Set OpenGL materials.
Definition: ogl_utils.cpp:141
bool Have_opaque() const
Have_opaque - return true if have opaque meshs to render.
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
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
Use a gray shading based on diffuse material.
Definition: 3d_enums.h:94
void Draw_bboxes() const
Draw_bboxes - draw individual bounding boxes of each mesh.
MATERIAL_MODE
Render 3d model shape materials mode.
Definition: 3d_enums.h:90
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
GLuint m_ogl_idx_list_opaque
display list for rendering opaque meshes
Definition: c_ogl_3dmodel.h:88
Use all material properties from model file.
Definition: 3d_enums.h:92
GLuint m_ogl_idx_list_meshes
display lists for all meshes.
Definition: c_ogl_3dmodel.h:90
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:154
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
void OGL_draw_bbox(const CBBOX &aBBox)
OGL_draw_bbox - draw the bounding box lines.
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
CBBOX * m_meshs_bbox
individual bbox for each mesh
Definition: c_ogl_3dmodel.h:94
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
void OGL_SetDiffuseOnlyMaterial(const SFVEC3F &aMaterialDiffuse)
OGL_SetDiffuseOnlyMaterial - sets only the diffuse color and keep other parameters with default value...
Definition: ogl_utils.cpp:161
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
Class CBBOX manages a bounding box defined by two SFVEC3F min max points.
Definition: cbbox.h:40
void Reset()
Function Reset reset the bounding box to zero and de-initialized it.
Definition: cbbox.cpp:98