KiCad PCB EDA Suite
c3d_render_ogl_legacy.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-2020 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2020 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 // Apple, in their infinite wisdom, has decided to mark OpenGL as deprecated.
31 // Luckily we can silence warnings about its deprecation. This is needed on the GLEW
32 // includes since they seem to transitively include the OpenGL headers.
33 #define GL_SILENCE_DEPRECATION 1
34 #include <GL/glew.h>
35 
36 #include "c3d_render_ogl_legacy.h"
37 #include "ogl_legacy_utils.h"
38 #include "common_ogl/ogl_utils.h"
39 #include "../cimage.h"
40 #include <class_board.h>
41 #include <class_module.h>
42 #include <3d_math.h>
43 #include <math/util.h> // for KiROUND
44 
45 #include <base_units.h>
46 
50 #define UNITS3D_TO_UNITSPCB (IU_PER_MM)
51 
53  C3D_RENDER_BASE( aAdapter, aCamera )
54 {
55  wxLogTrace( m_logTrace, wxT( "C3D_RENDER_OGL_LEGACY::C3D_RENDER_OGL_LEGACY" ) );
56 
60  m_triangles.clear();
62 
65 
70  //m_ogl_disp_list_through_holes_vias_inner = NULL;
74 
78 
79  m_3dmodel_map.clear();
80 }
81 
82 
84 {
85  wxLogTrace( m_logTrace, wxT( "C3D_RENDER_OGL_LEGACY::~C3D_RENDER_OGL_LEGACY" ) );
86 
88 
89  glDeleteTextures( 1, &m_ogl_circle_texture );
90 }
91 
92 
94 {
95  return 50; // ms
96 }
97 
98 
99 void C3D_RENDER_OGL_LEGACY::SetCurWindowSize( const wxSize &aSize )
100 {
101  if( m_windowSize != aSize )
102  {
103  m_windowSize = aSize;
104  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
105 
106  // Initialize here any screen dependent data here
107  }
108 }
109 
110 
112 {
113  if( enabled )
114  glEnable( GL_LIGHT0 );
115  else
116  glDisable( GL_LIGHT0 );
117 }
118 
119 
121 {
122  if( enabled )
123  glEnable( GL_LIGHT1 );
124  else
125  glDisable( GL_LIGHT1 );
126 }
127 
128 
130 {
131  if( enabled )
132  glEnable( GL_LIGHT2 );
133  else
134  glDisable( GL_LIGHT2 );
135 }
136 
137 
139 {
140  const float arrow_size = RANGE_SCALE_3D * 0.30f;
141 
142  glDisable( GL_CULL_FACE );
143 
144  // YxY squared view port, this is on propose
145  glViewport( 4, 4, m_windowSize.y / 8 , m_windowSize.y / 8 );
146  glClear( GL_DEPTH_BUFFER_BIT );
147 
148  glMatrixMode( GL_PROJECTION );
149  glLoadIdentity();
150  gluPerspective( 45.0f, 1.0f, 0.001f, RANGE_SCALE_3D );
151 
152  glMatrixMode( GL_MODELVIEW );
153  glLoadIdentity();
154 
155  const glm::mat4 TranslationMatrix = glm::translate(
156  glm::mat4(1.0f),
157  SFVEC3F( 0.0f, 0.0f, -(arrow_size * 2.75f) ) );
158 
159  const glm::mat4 ViewMatrix = TranslationMatrix * m_camera.GetRotationMatrix();
160 
161  glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
162 
164 
165  glColor3f( 0.9f, 0.0f, 0.0f );
166  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
167  SFVEC3F( arrow_size, 0.0f, 0.0f ),
168  0.275f );
169 
170  glColor3f( 0.0f, 0.9f, 0.0f );
171  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
172  SFVEC3F( 0.0f, arrow_size, 0.0f ),
173  0.275f );
174 
175  glColor3f( 0.0f, 0.0f, 0.9f );
176  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
177  SFVEC3F( 0.0f, 0.0f, arrow_size ),
178  0.275f );
179 
180  glEnable( GL_CULL_FACE );
181 }
182 
183 
185 {
186  m_materials = {};
187 
189  {
190  // http://devernay.free.fr/cours/opengl/materials.html
191 
192  // Plated copper
193  // Copper material mixed with the copper color
194  m_materials.m_Copper.m_Ambient = SFVEC3F( m_boardAdapter.m_CopperColor.r * 0.1f,
195  m_boardAdapter.m_CopperColor.g * 0.1f,
196  m_boardAdapter.m_CopperColor.b * 0.1f);
197 
198  m_materials.m_Copper.m_Specular = SFVEC3F( m_boardAdapter.m_CopperColor.r * 0.75f + 0.25f,
199  m_boardAdapter.m_CopperColor.g * 0.75f + 0.25f,
200  m_boardAdapter.m_CopperColor.b * 0.75f + 0.25f );
201 
202  // This guess the material type(ex: copper vs gold) to determine the
203  // shininess factor between 0.1 and 0.4
204  float shininessfactor = 0.40f - mapf( fabs( m_boardAdapter.m_CopperColor.r -
206  0.15f, 1.00f,
207  0.00f, 0.30f );
208 
209  m_materials.m_Copper.m_Shininess = shininessfactor * 128.0f;
210  m_materials.m_Copper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
211 
212 
213  // Non plated copper (raw copper)
214  m_materials.m_NonPlatedCopper.m_Ambient = SFVEC3F( 0.191f, 0.073f, 0.022f );
215  m_materials.m_NonPlatedCopper.m_Diffuse = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
216  m_materials.m_NonPlatedCopper.m_Specular = SFVEC3F( 0.256f, 0.137f, 0.086f );
217  m_materials.m_NonPlatedCopper.m_Shininess = 0.1f * 128.0f;
218  m_materials.m_NonPlatedCopper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
219 
220  // Paste material mixed with paste color
221  m_materials.m_Paste.m_Ambient = SFVEC3F( m_boardAdapter.m_SolderPasteColor.r,
224 
225  m_materials.m_Paste.m_Specular = SFVEC3F( m_boardAdapter.m_SolderPasteColor.r *
231 
232  m_materials.m_Paste.m_Shininess = 0.1f * 128.0f;
233  m_materials.m_Paste.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
234 
235 
236  // Silk screen material mixed with silk screen color
237  m_materials.m_SilkSTop.m_Ambient = SFVEC3F( m_boardAdapter.m_SilkScreenColorTop.r,
240 
241  m_materials.m_SilkSTop.m_Specular = SFVEC3F(
245 
246  m_materials.m_SilkSTop.m_Shininess = 0.078125f * 128.0f;
247  m_materials.m_SilkSTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
248 
249  // Silk screen material mixed with silk screen color
250  m_materials.m_SilkSBot.m_Ambient = SFVEC3F( m_boardAdapter.m_SilkScreenColorBot.r,
253 
254  m_materials.m_SilkSBot.m_Specular = SFVEC3F(
258 
259  m_materials.m_SilkSBot.m_Shininess = 0.078125f * 128.0f;
260  m_materials.m_SilkSBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
261 
262  m_materials.m_SolderMask.m_Shininess = 0.8f * 128.0f;
263  m_materials.m_SolderMask.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
264 
265  // Epoxy material
266  m_materials.m_EpoxyBoard.m_Ambient = SFVEC3F( 117.0f / 255.0f,
267  97.0f / 255.0f,
268  47.0f / 255.0f );
269 
270  m_materials.m_EpoxyBoard.m_Specular = SFVEC3F( 18.0f / 255.0f,
271  3.0f / 255.0f,
272  20.0f / 255.0f );
273 
274  m_materials.m_EpoxyBoard.m_Shininess = 0.1f * 128.0f;
275  m_materials.m_EpoxyBoard.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
276  }
277  else // Technical Mode
278  {
279  const SFVEC3F matAmbientColor = SFVEC3F( 0.10f );
280  const SFVEC3F matSpecularColor = SFVEC3F( 0.10f );
281  const float matShininess = 0.1f * 128.0f;
282 
283  // Copper material
284  m_materials.m_Copper.m_Ambient = matAmbientColor;
285  m_materials.m_Copper.m_Specular = matSpecularColor;
286  m_materials.m_Copper.m_Shininess = matShininess;
287  m_materials.m_Copper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
288 
289  // Paste material
290  m_materials.m_Paste.m_Ambient = matAmbientColor;
291  m_materials.m_Paste.m_Specular = matSpecularColor;
292  m_materials.m_Paste.m_Shininess = matShininess;
293  m_materials.m_Paste.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
294 
295  // Silk screen material
296  m_materials.m_SilkSTop.m_Ambient = matAmbientColor;
297  m_materials.m_SilkSTop.m_Specular = matSpecularColor;
298  m_materials.m_SilkSTop.m_Shininess = matShininess;
299  m_materials.m_SilkSTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
300 
301  // Silk screen material
302  m_materials.m_SilkSBot.m_Ambient = matAmbientColor;
303  m_materials.m_SilkSBot.m_Specular = matSpecularColor;
304  m_materials.m_SilkSBot.m_Shininess = matShininess;
305  m_materials.m_SilkSBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
306 
307  // Solder mask material
308  m_materials.m_SolderMask.m_Ambient = matAmbientColor;
309  m_materials.m_SolderMask.m_Specular = matSpecularColor;
310  m_materials.m_SolderMask.m_Shininess = matShininess;
311  m_materials.m_SolderMask.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
312 
313  // Epoxy material
314  m_materials.m_EpoxyBoard.m_Ambient = matAmbientColor;
315  m_materials.m_EpoxyBoard.m_Specular = matSpecularColor;
316  m_materials.m_EpoxyBoard.m_Shininess = matShininess;
317  m_materials.m_EpoxyBoard.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
318 
319  // Gray material (used for example in technical vias and pad holes)
320  m_materials.m_GrayMaterial.m_Ambient = SFVEC3F( 0.8f, 0.8f, 0.8f );
321  m_materials.m_GrayMaterial.m_Diffuse = SFVEC3F( 0.3f, 0.3f, 0.3f );
322  m_materials.m_GrayMaterial.m_Specular = SFVEC3F( 0.4f, 0.4f, 0.4f );
323  m_materials.m_GrayMaterial.m_Shininess = 0.01f * 128.0f;
324  m_materials.m_GrayMaterial.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
325  }
326 }
327 
328 
330 {
331  switch( aLayerID )
332  {
333  case F_Mask:
334  case B_Mask:
335  {
336  const SFVEC4F layerColor = get_layer_color( aLayerID );
337 
338  m_materials.m_SolderMask.m_Diffuse = layerColor;
339  m_materials.m_SolderMask.m_Transparency = 1.0f - layerColor.a; // Convert Opacity to Transparency
340 
342  {
343  m_materials.m_SolderMask.m_Ambient = m_materials.m_SolderMask.m_Diffuse * 0.3f;
344 
345  m_materials.m_SolderMask.m_Specular = m_materials.m_SolderMask.m_Diffuse *
346  m_materials.m_SolderMask.m_Diffuse;
347  }
348 
349  OGL_SetMaterial( m_materials.m_SolderMask, 1.0f );
350  break;
351  }
352 
353  case B_Paste:
354  case F_Paste:
355  m_materials.m_Paste.m_Diffuse = get_layer_color( aLayerID );
356  OGL_SetMaterial( m_materials.m_Paste, 1.0f );
357  break;
358 
359  case B_SilkS:
360  m_materials.m_SilkSBot.m_Diffuse = get_layer_color( aLayerID );
361  OGL_SetMaterial( m_materials.m_SilkSBot, 1.0f );
362  break;
363 
364  case F_SilkS:
365  m_materials.m_SilkSTop.m_Diffuse = get_layer_color( aLayerID );
366  OGL_SetMaterial( m_materials.m_SilkSTop, 1.0f );
367  break;
368 
369  case B_Adhes:
370  case F_Adhes:
371  case Dwgs_User:
372  case Cmts_User:
373  case Eco1_User:
374  case Eco2_User:
375  case Edge_Cuts:
376  case Margin:
377  case B_CrtYd:
378  case F_CrtYd:
379  case B_Fab:
380  case F_Fab:
381  m_materials.m_Plastic.m_Diffuse = get_layer_color( aLayerID );
382  m_materials.m_Plastic.m_Ambient = SFVEC3F(
383  m_materials.m_Plastic.m_Diffuse.r * 0.05f,
384  m_materials.m_Plastic.m_Diffuse.g * 0.05f,
385  m_materials.m_Plastic.m_Diffuse.b * 0.05f );
386 
387  m_materials.m_Plastic.m_Specular = SFVEC3F(
388  m_materials.m_Plastic.m_Diffuse.r * 0.7f,
389  m_materials.m_Plastic.m_Diffuse.g * 0.7f,
390  m_materials.m_Plastic.m_Diffuse.b * 0.7f );
391 
392  m_materials.m_Plastic.m_Shininess = 0.078125f * 128.0f;
393  m_materials.m_Plastic.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
394  OGL_SetMaterial( m_materials.m_Plastic, 1.0f );
395  break;
396 
397  default:
398  m_materials.m_Copper.m_Diffuse = get_layer_color( aLayerID );
399  OGL_SetMaterial( m_materials.m_Copper, 1.0f );
400 
401  break;
402  }
403 }
404 
405 
407 {
408  SFVEC4F layerColor = m_boardAdapter.GetLayerColor( aLayerID );
409 
411  {
412  switch( aLayerID )
413  {
414  case B_Adhes:
415  case F_Adhes:
416  break;
417 
418  case B_Mask:
420  break;
421  case F_Mask:
423  break;
424 
425  case B_Paste:
426  case F_Paste:
427  layerColor = m_boardAdapter.m_SolderPasteColor;
428  break;
429 
430  case B_SilkS:
432  break;
433  case F_SilkS:
435  break;
436 
437  case Dwgs_User:
438  case Cmts_User:
439  case Eco1_User:
440  case Eco2_User:
441  case Edge_Cuts:
442  case Margin:
443  break;
444 
445  case B_CrtYd:
446  case F_CrtYd:
447  break;
448 
449  case B_Fab:
450  case F_Fab:
451  break;
452 
453  default:
454  layerColor = m_boardAdapter.m_CopperColor;
455  break;
456  }
457  }
458 
459  return layerColor;
460 }
461 
462 void init_lights(void)
463 {
464  // Setup light
465  // https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
466  // /////////////////////////////////////////////////////////////////////////
467  const GLfloat ambient[] = { 0.084f, 0.084f, 0.084f, 1.0f };
468  const GLfloat diffuse0[] = { 0.3f, 0.3f, 0.3f, 1.0f };
469  const GLfloat specular0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
470 
471  glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
472  glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse0 );
473  glLightfv( GL_LIGHT0, GL_SPECULAR, specular0 );
474 
475  const GLfloat diffuse12[] = { 0.7f, 0.7f, 0.7f, 1.0f };
476  const GLfloat specular12[] = { 0.7f, 0.7f, 0.7f, 1.0f };
477 
478  // defines a directional light that points along the negative z-axis
479  GLfloat position[4] = { 0.0f, 0.0f, 1.0f, 0.0f };
480 
481  // This makes a vector slight not perpendicular with XZ plane
482  const SFVEC3F vectorLight = SphericalToCartesian( glm::pi<float>() * 0.03f,
483  glm::pi<float>() * 0.25f );
484 
485  position[0] = vectorLight.x;
486  position[1] = vectorLight.y;
487  position[2] = vectorLight.z;
488 
489  glLightfv( GL_LIGHT1, GL_AMBIENT, ambient );
490  glLightfv( GL_LIGHT1, GL_DIFFUSE, diffuse12 );
491  glLightfv( GL_LIGHT1, GL_SPECULAR, specular12 );
492  glLightfv( GL_LIGHT1, GL_POSITION, position );
493 
494 
495  // defines a directional light that points along the positive z-axis
496  position[2] = -position[2];
497 
498  glLightfv( GL_LIGHT2, GL_AMBIENT, ambient );
499  glLightfv( GL_LIGHT2, GL_DIFFUSE, diffuse12 );
500  glLightfv( GL_LIGHT2, GL_SPECULAR, specular12 );
501  glLightfv( GL_LIGHT2, GL_POSITION, position );
502 
503  const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
504 
505  glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
506 
507  glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
508 }
509 
511 {
512  OGL_SetMaterial( m_materials.m_NonPlatedCopper, 1.0f );
513 }
514 
516 {
517  glEnable( GL_POLYGON_OFFSET_FILL );
518  glPolygonOffset( 0.0f, -2.0f );
519  set_layer_material( aLayer_id );
520 }
521 
523 {
524  glDisable( GL_POLYGON_OFFSET_FILL );
525 }
526 
527 void C3D_RENDER_OGL_LEGACY::render_board_body( bool aSkipRenderHoles )
528 {
530  {
533 
534 
535  m_materials.m_EpoxyBoard.m_Diffuse = m_boardAdapter.m_BoardBodyColor;
536  m_materials.m_EpoxyBoard.m_Transparency = 1.0f - m_boardAdapter.m_BoardBodyColor.a; // opacity to transparency
537 
538  OGL_SetMaterial( m_materials.m_EpoxyBoard, 1.0f );
539 
541 
542  if( (m_ogl_disp_list_through_holes_outer_with_npth) && (!aSkipRenderHoles) )
543  {
547 
550  NULL );
551  }
552  else
553  {
555  }
556  }
557 }
558 
560  bool aIsMoving, REPORTER* aStatusReporter, REPORTER* aWarningReporter )
561 {
562  // Initialize openGL
564  {
565  if( !initializeOpenGL() )
566  return false;
567  }
568 
569  if( m_reloadRequested )
570  {
571  std::unique_ptr<BUSY_INDICATOR> busy = CreateBusyIndicator();
572 
573  if( aStatusReporter )
574  aStatusReporter->Report( _( "Loading..." ) );
575 
576  reload( aStatusReporter, aWarningReporter );
577  setupMaterials();
578 
579  // generate a new 3D grid as the size of the board may had changed
582  }
583  else
584  {
585  // Check if grid was changed
587  {
588  // and generate a new one
591  }
592  }
593 
594  // Initial setup
595  // /////////////////////////////////////////////////////////////////////////
596  glDepthFunc( GL_LESS );
597  glEnable( GL_CULL_FACE );
598  glFrontFace( GL_CCW ); // This is the openGL default
599  glEnable( GL_NORMALIZE ); // This allow openGL to normalize the normals after transformations
600 
601  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
602 
604  {
605  if( !aIsMoving )
606  {
607  glEnable( GL_MULTISAMPLE );
608  }
609  else
610  {
611  glDisable( GL_MULTISAMPLE );
612  }
613  }
614 
615  // clear color and depth buffers
616  // /////////////////////////////////////////////////////////////////////////
617  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
618  glClearDepth( 1.0f );
619  glClearStencil( 0x00 );
620  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
621 
623 
624  // Draw the background ( rectangle with color gradient)
625  // /////////////////////////////////////////////////////////////////////////
628 
629  glEnable( GL_DEPTH_TEST );
630 
631 
632  // Set projection and modelview matrixes
633  // /////////////////////////////////////////////////////////////////////////
634  glMatrixMode( GL_PROJECTION );
635  glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
636 
637  glMatrixMode( GL_MODELVIEW );
638  glLoadIdentity();
639  glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
640 
641 
642  // Position the headlight
643  // /////////////////////////////////////////////////////////////////////////
644 
645  setLight_Front( true );
646  setLight_Top( true );
647  setLight_Bottom( true );
648 
649  glEnable( GL_LIGHTING );
650 
651  {
652  const SFVEC3F &cameraPos = m_camera.GetPos();
653 
654  // Place the light at a minimun Z so the diffuse factor will not drop
655  // and the board will still look with good light.
656  float zpos;
657 
658  if( cameraPos.z > 0.0f )
659  {
660  zpos = glm::max( cameraPos.z, 0.5f ) + cameraPos.z * cameraPos.z;
661  }
662  else
663  {
664  zpos = glm::min( cameraPos.z,-0.5f ) - cameraPos.z * cameraPos.z;
665  }
666 
667  const GLfloat headlight_pos[] = { cameraPos.x,
668  cameraPos.y,
669  zpos,
670  1.0f }; // This is a point light
671 
672  glLightfv( GL_LIGHT0, GL_POSITION, headlight_pos );
673  }
674 
675  const bool drawMiddleSegments = !( aIsMoving &&
677 
678  const bool skipRenderHoles = aIsMoving &&
680 
681  const bool skipRenderVias = aIsMoving &&
683 
685  {
686  // Draw vias and pad holes with copper material
688  }
689  else
690  {
691  OGL_SetMaterial( m_materials.m_GrayMaterial, 1.0f );
692  }
693 
694  if( (!( skipRenderVias || skipRenderHoles ) ) && m_ogl_disp_list_via )
695  {
697  }
698 
699  if( ( !skipRenderHoles ) && m_ogl_disp_list_pads_holes )
700  {
702  }
703 
704 
705  // Display copper and tech layers
706  // /////////////////////////////////////////////////////////////////////////
707  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers.begin();
708  ii != m_ogl_disp_lists_layers.end();
709  ++ii )
710  {
711  const PCB_LAYER_ID layer_id = (PCB_LAYER_ID)(ii->first);
712 
713  // Mask layers are not processed here because they are a special case
714  if( (layer_id == B_Mask) || (layer_id == F_Mask) )
715  continue;
716 
717  // Do not show inner layers when it is displaying the board
718  // and board body is full opaque
720  ( m_boardAdapter.m_BoardBodyColor.a > 0.99f ) )
721  {
722  if( (layer_id > F_Cu) && (layer_id < B_Cu) )
723  continue;
724  }
725 
726  glPushMatrix();
727 
728  // !TODO: if we want to increase the separation between layers
729  //glScalef( 1.0f, 1.0f, 3.0f );
730 
731 
732  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
733 
734  if( (layer_id >= F_Cu) && (layer_id <= B_Cu) )
735  {
737 
738  if( skipRenderHoles )
739  {
740  pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
741 
742  // Draw copper plated pads
743 
744  if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
746  setPlatedCopperAndDepthOffset( layer_id );
747 
748  if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu )
750  else
751  if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu )
753 
755  }
756  else
757  {
760  pLayerDispList->GetZBot(),
761  pLayerDispList->GetZTop() - pLayerDispList->GetZBot() );
762 
763  if( m_ogl_disp_lists_layers_holes_outer.find( layer_id ) !=
765  {
766  const CLAYERS_OGL_DISP_LISTS* viasHolesLayer =
768 
769  wxASSERT( viasHolesLayer != NULL );
770 
771  if( viasHolesLayer != NULL )
772  {
773  pLayerDispList->DrawAllCameraCulledSubtractLayer(
775  viasHolesLayer,
776  drawMiddleSegments );
777 
778  // Draw copper plated pads
779 
780  if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
782  setPlatedCopperAndDepthOffset( layer_id );
783 
784  if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu )
787  viasHolesLayer,
788  drawMiddleSegments );
789  else
790  if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu )
793  viasHolesLayer,
794  drawMiddleSegments );
795 
797  }
798  }
799  else
800  {
801  pLayerDispList->DrawAllCameraCulledSubtractLayer(
803  NULL,
804  drawMiddleSegments );
805 
806  // Draw copper plated pads
807 
808  if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
810  setPlatedCopperAndDepthOffset( layer_id );
811 
812  if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu )
815  NULL,
816  drawMiddleSegments );
817  else
818  if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu )
821  NULL,
822  drawMiddleSegments );
823 
825  }
826  }
827  }
828  else
829  {
830  set_layer_material( layer_id );
831 
832  CLAYERS_OGL_DISP_LISTS* dispListThoughHolesOuter =
834  && ( ( layer_id == B_SilkS ) || ( layer_id == F_SilkS ) ) ) ?
837 
838  if( dispListThoughHolesOuter )
839  dispListThoughHolesOuter->ApplyScalePosition( pLayerDispList->GetZBot(),
840  pLayerDispList->GetZTop() - pLayerDispList->GetZBot() );
841 
842  if( (!skipRenderHoles) &&
844  ( ( ( layer_id == B_SilkS ) &&
845  ( m_ogl_disp_lists_layers.find( B_Mask ) != m_ogl_disp_lists_layers.end() ) ) ||
846  ( ( layer_id == F_SilkS ) &&
847  ( m_ogl_disp_lists_layers.find( F_Mask ) != m_ogl_disp_lists_layers.end() ) ) ) )
848  {
849  const PCB_LAYER_ID layerMask_id = (layer_id == B_SilkS)?B_Mask:F_Mask;
850 
851  const CLAYERS_OGL_DISP_LISTS *pLayerDispListMask = m_ogl_disp_lists_layers.at( layerMask_id );
852 
853  pLayerDispList->DrawAllCameraCulledSubtractLayer(
854  pLayerDispListMask,
855  dispListThoughHolesOuter,
856  drawMiddleSegments );
857  }
858  else
859  {
860  if( (!skipRenderHoles) &&
861  dispListThoughHolesOuter &&
862  ( ( layer_id == B_SilkS ) || ( layer_id == F_SilkS )
863  // Remove vias on SolderPaste can be added as an option in future
864  // ( layer_id == B_Paste ) || ( layer_id == F_Paste ) )
865  ) )
866  {
867  pLayerDispList->DrawAllCameraCulledSubtractLayer(
868  NULL,
869  dispListThoughHolesOuter,
870  drawMiddleSegments );
871  }
872  else
873  {
874  // Do not render Paste layers when skipRenderHoles is enabled
875  // otherwise it will cause z-fight issues
876  if( !( skipRenderHoles &&
877  ( ( layer_id == B_Paste ) || ( layer_id == F_Paste ) ) ) )
878  {
879  pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
880  }
881  }
882  }
883  }
884 
885  glPopMatrix();
886  }
887 
888  // Render 3D Models (Non-transparent)
889  // /////////////////////////////////////////////////////////////////////////
890  render_3D_models( false, false );
891  render_3D_models( true, false );
892 
893  // Display board body
894  // /////////////////////////////////////////////////////////////////////////
896  {
897  render_board_body( skipRenderHoles );
898  }
899 
900  // Display transparent mask layers
901  // /////////////////////////////////////////////////////////////////////////
903  {
904  //setLight_Top( true );
905  //setLight_Bottom( true );
906 
907  // add a depth buffer offset, it will help to hide some artifacts
908  // on silkscreen where the SolderMask is removed
909  glEnable( GL_POLYGON_OFFSET_FILL );
910  glPolygonOffset( 0.0f, -2.0f );
911 
912  if( m_camera.GetPos().z > 0 )
913  {
915  drawMiddleSegments, skipRenderHoles );
916 
918  drawMiddleSegments, skipRenderHoles );
919  }
920  else
921  {
923  drawMiddleSegments, skipRenderHoles );
924 
926  drawMiddleSegments, skipRenderHoles );
927  }
928 
929  glDisable( GL_POLYGON_OFFSET_FILL );
930  glPolygonOffset( 0.0f, 0.0f );
931  }
932 
933 
934  // Render 3D Models (Transparent)
935  // /////////////////////////////////////////////////////////////////////////
936  // !TODO: this can be optimized. If there are no transparent models (or no opacity),
937  // then there is no need to make this function call.
938 
939  glDepthMask( GL_FALSE );
940 
941  glEnable( GL_BLEND );
942  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
943 
944  // Enables Texture Env so it can combine model transparency with
945  // each module opacity setting
946  glEnable( GL_TEXTURE_2D );
947  glActiveTexture( GL_TEXTURE0 );
948 
949  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
950  glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
951  glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE );
952 
953  glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR );
954  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
955 
956  glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS );
957  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
958 
959  glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR );
960  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
961  glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT );
962  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_CONSTANT );
963 
964  render_3D_models( false, true );
965  render_3D_models( true, true );
966 
967  glDisable( GL_BLEND );
969 
970  glDepthMask( GL_TRUE );
971 
972  // Render Grid
973  // /////////////////////////////////////////////////////////////////////////
974 
976  {
977  glDisable( GL_LIGHTING );
978 
979  if( glIsList( m_ogl_disp_list_grid ) )
980  glCallList( m_ogl_disp_list_grid );
981 
982  glEnable( GL_LIGHTING );
983  }
984 
985 
986  // Render 3D arrows
987  // /////////////////////////////////////////////////////////////////////////
990 
991  // Return back to the original viewport (this is important if we want
992  // to take a screenshot after the render)
993  // /////////////////////////////////////////////////////////////////////////
994  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
995 
996  return false;
997 }
998 
999 
1001 {
1002  glEnable( GL_LINE_SMOOTH );
1003  glShadeModel( GL_SMOOTH );
1004 
1005  // 4-byte pixel alignment
1006  glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
1007 
1008  // Initialize the open GL texture to draw the filled semi-circle of the segments
1010 
1011  if( !circleImage )
1012  return false;
1013 
1014  circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 2) - 0,
1015  (SIZE_OF_CIRCLE_TEXTURE / 2) - 0,
1016  (SIZE_OF_CIRCLE_TEXTURE / 2) - 4,
1017  0xFF );
1018 
1019  //circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1,
1020  // (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1,
1021  // (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 2, 0xFF );
1022 
1023  CIMAGE *circleImage_Copy = new CIMAGE( *circleImage );
1024 
1025  circleImage->EfxFilter( circleImage_Copy, IMAGE_FILTER::BLUR_3X3 );
1026 
1027  m_ogl_circle_texture = OGL_LoadTexture( *circleImage );
1028 
1029  //circleImage_Copy->SaveAsPNG("circleImage.png");
1030  delete circleImage_Copy;
1031  circleImage_Copy = 0;
1032 
1033  //circleImage->SaveAsPNG("circleImage_blured.png");
1034  delete circleImage;
1035  circleImage = 0;
1036 
1037  init_lights();
1038 
1039  // Use this mode if you want see the triangle lines (debug proposes)
1040  //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
1041 
1042  m_is_opengl_initialized = true;
1043 
1044  return true;
1045 }
1046 
1047 
1049 {
1050  glEnable( GL_COLOR_MATERIAL );
1051  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
1052 
1053  const SFVEC4F ambient = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
1054  const SFVEC4F diffuse = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
1055  const SFVEC4F emissive = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
1056  const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
1057 
1058  glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
1059  glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
1060 
1061  glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r );
1062  glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r );
1063  glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r );
1064 }
1065 
1066 
1068 {
1069  if( glIsList( m_ogl_disp_list_grid ) )
1070  glDeleteLists( m_ogl_disp_list_grid, 1 );
1071 
1073 
1074  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers.begin();
1075  ii != m_ogl_disp_lists_layers.end();
1076  ++ii )
1077  {
1078  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1079  delete pLayerDispList;
1080  }
1081 
1082  m_ogl_disp_lists_layers.clear();
1083 
1086 
1087  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers_holes_outer.begin();
1089  ++ii )
1090  {
1091  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1092  delete pLayerDispList;
1093  }
1094 
1096 
1097 
1098  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers_holes_inner.begin();
1100  ++ii )
1101  {
1102  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1103  delete pLayerDispList;
1104  }
1105 
1107 
1108  for( LIST_TRIANGLES::const_iterator ii = m_triangles.begin();
1109  ii != m_triangles.end();
1110  ++ii )
1111  {
1112  delete *ii;
1113  }
1114 
1115  m_triangles.clear();
1116 
1117 
1118  for( MAP_3DMODEL::const_iterator ii = m_3dmodel_map.begin();
1119  ii != m_3dmodel_map.end();
1120  ++ii )
1121  {
1122  C_OGL_3DMODEL *pointer = static_cast<C_OGL_3DMODEL*>(ii->second);
1123  delete pointer;
1124  }
1125 
1126  m_3dmodel_map.clear();
1127 
1128 
1129  delete m_ogl_disp_list_board;
1131 
1134 
1137 
1140 
1143 
1144  delete m_ogl_disp_list_via;
1145  m_ogl_disp_list_via = 0;
1146 
1149 
1152 }
1153 
1154 
1156  float aZPosition,
1157  bool aDrawMiddleSegments,
1158  bool aSkipRenderHoles )
1159 {
1160  wxASSERT( (aLayerID == B_Mask) || (aLayerID == F_Mask) );
1161 
1162  if( m_ogl_disp_list_board )
1163  {
1164  if( m_ogl_disp_lists_layers.find( aLayerID ) !=
1165  m_ogl_disp_lists_layers.end() )
1166  {
1167  CLAYERS_OGL_DISP_LISTS *pLayerDispListMask = m_ogl_disp_lists_layers.at( aLayerID );
1168 
1171  aZPosition,
1173 
1175  aZPosition,
1177 
1178  set_layer_material( aLayerID );
1179 
1181 
1182  if( aSkipRenderHoles )
1183  {
1185  aDrawMiddleSegments );
1186  }
1187  else
1188  {
1190  pLayerDispListMask,
1192  aDrawMiddleSegments );
1193  }
1194  }
1195  else
1196  {
1197  // This case there is no layer with mask, so we will render the full board as mask
1198 
1201  aZPosition,
1203 
1205  aZPosition,
1207 
1208  set_layer_material( aLayerID );
1209 
1211 
1212  if( aSkipRenderHoles )
1213  {
1215  aDrawMiddleSegments );
1216  }
1217  else
1218  {
1220  NULL,
1222  aDrawMiddleSegments );
1223  }
1224  }
1225  }
1226 }
1227 
1228 
1229 void C3D_RENDER_OGL_LEGACY::render_3D_models( bool aRenderTopOrBot,
1230  bool aRenderTransparentOnly )
1231 {
1233 
1234  // Go for all modules
1235  for( auto module : m_boardAdapter.GetBoard()->Modules() )
1236  {
1237  if( !module->Models().empty() )
1238  if( m_boardAdapter.ShouldModuleBeDisplayed((MODULE_ATTR_T) module->GetAttributes() ) )
1239  if( ( aRenderTopOrBot && !module->IsFlipped() )
1240  || ( !aRenderTopOrBot && module->IsFlipped() ) )
1241  render_3D_module( module, aRenderTransparentOnly );
1242  }
1243 
1245 }
1246 
1247 
1249  bool aRenderTransparentOnly )
1250 {
1251  if( !module->Models().empty() )
1252  {
1253  const double zpos = m_boardAdapter.GetModulesZcoord3DIU( module->IsFlipped() );
1254 
1255  glPushMatrix();
1256 
1257  wxPoint pos = module->GetPosition();
1258 
1259  glTranslatef( pos.x * m_boardAdapter.BiuTo3Dunits(),
1260  -pos.y * m_boardAdapter.BiuTo3Dunits(),
1261  zpos );
1262 
1263  if( module->GetOrientation() )
1264  glRotated( (double) module->GetOrientation() / 10.0, 0.0, 0.0, 1.0 );
1265 
1266  if( module->IsFlipped() )
1267  {
1268  glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
1269  glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
1270  }
1271 
1272  double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3Dunits() * UNITS3D_TO_UNITSPCB;
1273 
1274  glScaled( modelunit_to_3d_units_factor,
1275  modelunit_to_3d_units_factor,
1276  modelunit_to_3d_units_factor );
1277 
1278  // Get the list of model files for this model
1279  for( const MODULE_3D_SETTINGS& sM : module->Models() )
1280  {
1281  if( !sM.m_Show || sM.m_Filename.empty() )
1282  continue;
1283 
1284  // Check if the model is present in our cache map
1285  auto cache_i = m_3dmodel_map.find( sM.m_Filename );
1286 
1287  if( cache_i == m_3dmodel_map.end() )
1288  continue;
1289 
1290  if( const C_OGL_3DMODEL *modelPtr = cache_i->second )
1291  {
1292  bool opaque = sM.m_Opacity >= 1.0;
1293 
1294  if( ( !aRenderTransparentOnly && modelPtr->Have_opaque() && opaque ) ||
1295  ( aRenderTransparentOnly && ( modelPtr->Have_transparent() || !opaque ) ) )
1296  {
1297  glPushMatrix();
1298 
1299  // FIXME: don't do this over and over again unless the
1300  // values have changed. cache the matrix somewhere.
1301  glm::mat4 mtx( 1 );
1302  mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
1303  mtx = glm::rotate(
1304  mtx, glm::radians( (float) -sM.m_Rotation.z ), { 0.0f, 0.0f, 1.0f } );
1305  mtx = glm::rotate(
1306  mtx, glm::radians( (float) -sM.m_Rotation.y ), { 0.0f, 1.0f, 0.0f } );
1307  mtx = glm::rotate(
1308  mtx, glm::radians( (float) -sM.m_Rotation.x ), { 1.0f, 0.0f, 0.0f } );
1309  mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } );
1310  glMultMatrixf( glm::value_ptr( mtx ) );
1311 
1312  if( aRenderTransparentOnly )
1313  modelPtr->Draw_transparent( sM.m_Opacity );
1314  else
1315  modelPtr->Draw_opaque();
1316 
1318  {
1319  glEnable( GL_BLEND );
1320  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1321 
1322  glDisable( GL_LIGHTING );
1323 
1324  glLineWidth( 1 );
1325  modelPtr->Draw_bboxes();
1326 
1327  glLineWidth( 4 );
1328  modelPtr->Draw_bbox();
1329 
1330  glEnable( GL_LIGHTING );
1331  glDisable( GL_BLEND );
1332  }
1333 
1334  glPopMatrix();
1335  }
1336  }
1337  }
1338 
1339  glPopMatrix();
1340  }
1341 }
1342 
1343 
1344 // create a 3D grid to an openGL display list: an horizontal grid (XY plane and Z = 0,
1345 // and a vertical grid (XZ plane and Y = 0)
1347 {
1348  if( glIsList( m_ogl_disp_list_grid ) )
1349  glDeleteLists( m_ogl_disp_list_grid, 1 );
1350 
1352 
1353  if( aGridType == GRID3D_TYPE::NONE )
1354  return;
1355 
1356  m_ogl_disp_list_grid = glGenLists( 1 );
1357 
1358  if( !glIsList( m_ogl_disp_list_grid ) )
1359  return;
1360 
1361  glNewList( m_ogl_disp_list_grid, GL_COMPILE );
1362 
1363  glEnable( GL_BLEND );
1364  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1365 
1366  const double zpos = 0.0;
1367 
1368  // Color of grid lines
1369  const SFVEC3F gridColor = m_boardAdapter.GetColor( DARKGRAY );
1370 
1371  // Color of grid lines every 5 lines
1372  const SFVEC3F gridColor_marker = m_boardAdapter.GetColor( LIGHTGRAY );
1373  const double scale = m_boardAdapter.BiuTo3Dunits();
1374  const double transparency = 0.35;
1375 
1376  double griSizeMM = 0.0;
1377 
1378  switch( aGridType )
1379  {
1380  default:
1381  case GRID3D_TYPE::NONE:
1382  return;
1383  case GRID3D_TYPE::GRID_1MM:
1384  griSizeMM = 1.0;
1385  break;
1387  griSizeMM = 2.5;
1388  break;
1389  case GRID3D_TYPE::GRID_5MM:
1390  griSizeMM = 5.0;
1391  break;
1393  griSizeMM = 10.0;
1394  break;
1395  }
1396 
1397  glNormal3f( 0.0, 0.0, 1.0 );
1398 
1399  const wxSize brd_size = m_boardAdapter.GetBoardSizeBIU();
1400  wxPoint brd_center_pos = m_boardAdapter.GetBoardPosBIU();
1401 
1402  brd_center_pos.y = -brd_center_pos.y;
1403 
1404  const int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) ) * 1.2;
1405  const int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) ) * 1.2;
1406 
1407  // Grid limits, in 3D units
1408  double xmin = (brd_center_pos.x - xsize / 2) * scale;
1409  double xmax = (brd_center_pos.x + xsize / 2) * scale;
1410  double ymin = (brd_center_pos.y - ysize / 2) * scale;
1411  double ymax = (brd_center_pos.y + ysize / 2) * scale;
1412  double zmin = Millimeter2iu( -50 ) * scale;
1413  double zmax = Millimeter2iu( 100 ) * scale;
1414 
1415  // Draw horizontal grid centered on 3D origin (center of the board)
1416  for( int ii = 0; ; ii++ )
1417  {
1418  if( (ii % 5) )
1419  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1420  else
1421  glColor4f( gridColor_marker.r,
1422  gridColor_marker.g,
1423  gridColor_marker.b,
1424  transparency );
1425 
1426  const int delta = KiROUND( ii * griSizeMM * IU_PER_MM );
1427 
1428  if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
1429  {
1430  glBegin( GL_LINES );
1431  glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
1432  glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
1433  glEnd();
1434 
1435  if( ii != 0 )
1436  {
1437  glBegin( GL_LINES );
1438  glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
1439  glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
1440  glEnd();
1441  }
1442  }
1443 
1444  if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
1445  {
1446  glBegin( GL_LINES );
1447  glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
1448  glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
1449  glEnd();
1450 
1451  if( ii != 0 )
1452  {
1453  glBegin( GL_LINES );
1454  glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
1455  glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
1456  glEnd();
1457  }
1458  }
1459 
1460  if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
1461  break;
1462  }
1463 
1464  // Draw vertical grid on Z axis
1465  glNormal3f( 0.0, -1.0, 0.0 );
1466 
1467  // Draw vertical grid lines (parallel to Z axis)
1468  double posy = -brd_center_pos.y * scale;
1469 
1470  for( int ii = 0; ; ii++ )
1471  {
1472  if( (ii % 5) )
1473  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1474  else
1475  glColor4f( gridColor_marker.r,
1476  gridColor_marker.g,
1477  gridColor_marker.b,
1478  transparency );
1479 
1480  const double delta = ii * griSizeMM * IU_PER_MM;
1481 
1482  glBegin( GL_LINES );
1483  xmax = (brd_center_pos.x + delta) * scale;
1484 
1485  glVertex3f( xmax, posy, zmin );
1486  glVertex3f( xmax, posy, zmax );
1487  glEnd();
1488 
1489  if( ii != 0 )
1490  {
1491  glBegin( GL_LINES );
1492  xmin = (brd_center_pos.x - delta) * scale;
1493  glVertex3f( xmin, posy, zmin );
1494  glVertex3f( xmin, posy, zmax );
1495  glEnd();
1496  }
1497 
1498  if( delta > xsize / 2.0f )
1499  break;
1500  }
1501 
1502  // Draw horizontal grid lines on Z axis (parallel to X axis)
1503  for( int ii = 0; ; ii++ )
1504  {
1505  if( (ii % 5) )
1506  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1507  else
1508  glColor4f( gridColor_marker.r,
1509  gridColor_marker.g,
1510  gridColor_marker.b,
1511  transparency );
1512 
1513  const double delta = ii * griSizeMM * IU_PER_MM * scale;
1514 
1515  if( delta <= zmax )
1516  {
1517  // Draw grid lines on Z axis (positive Z axis coordinates)
1518  glBegin( GL_LINES );
1519  glVertex3f( xmin, posy, delta );
1520  glVertex3f( xmax, posy, delta );
1521  glEnd();
1522  }
1523 
1524  if( delta <= -zmin && ( ii != 0 ) )
1525  {
1526  // Draw grid lines on Z axis (negative Z axis coordinates)
1527  glBegin( GL_LINES );
1528  glVertex3f( xmin, posy, -delta );
1529  glVertex3f( xmax, posy, -delta );
1530  glEnd();
1531  }
1532 
1533  if( ( delta > zmax ) && ( delta > -zmin ) )
1534  break;
1535  }
1536 
1537  glDisable( GL_BLEND );
1538 
1539  glEndList();
1540 }
static void EndDrawMulti()
EndDrawMulti - cleanup render states after drawing multiple models.
double BiuTo3Dunits() const noexcept
BiuTo3Dunits - Board integer units To 3D units.
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_lists_platedPads_F_Cu
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_vias_outer_ring
SFVEC4F GetColor(COLOR4D aColor) const
GetColor.
double GetOrientation() const
Definition: class_module.h:224
void DrawAllCameraCulledSubtractLayer(const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractA, const CLAYERS_OGL_DISP_LISTS *aLayerToSubtractB, bool aDrawMiddle=true) const
void generate_new_3DGrid(GRID3D_TYPE aGridType)
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:302
Implementation of conversion functions that require both schematic and board internal units.
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_lists_platedPads_B_Cu
static constexpr double IU_PER_MM
Mock up a conversion function.
void render_3D_models(bool aRenderTopOrBot, bool aRenderTransparentOnly)
render_3D_models
glm::vec4 SFVEC4F
Definition: xv3d_types.h:49
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
Class CCAMERA is a virtual class used to derive CCAMERA objects from.
Definition: ccamera.h:79
float GetLayerTopZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerTopZpos3DU - Get the top z position.
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
Definition: 3d_math.h:136
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
void init_lights(void)
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
const SFVEC3F & GetPos() const
Definition: ccamera.h:113
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
wxSize GetBoardSizeBIU() const noexcept
GetBoardSizeBIU - Get the board size.
void CircleFilled(int aCx, int aCy, int aRadius, unsigned char aValue)
CircleFilled.
Definition: cimage.cpp:173
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
void ApplyScalePosition(float aZposition, float aZscale)
void setLight_Top(bool enabled)
GRID3D_TYPE m_last_grid_type
Stores the last grid computed.
GLuint OGL_LoadTexture(const CIMAGE &aImage)
OGL_LoadTexture - generate a new OpenGL texture.
Definition: ogl_utils.cpp:81
void render_solder_mask_layer(PCB_LAYER_ID aLayerID, float aZPosition, bool aDrawMiddleSegments, bool aSkipRenderHoles)
int GetWaitForEditingTimeOut() override
GetWaitForEditingTimeOut - Give the interface the time (in ms) that it should wait for editing or mov...
const glm::mat4 GetRotationMatrix() const
Function GetRotationMatrix Get the rotation matrix to be applied in a transformation camera.
Definition: ccamera.cpp:158
#define UNITS3D_TO_UNITSPCB
Scale convertion from 3d model units to pcb units.
void OGL_DrawBackground(const SFVEC3F &aTopColor, const SFVEC3F &aBotColor)
OGL_DrawBackground.
Definition: ogl_utils.cpp:184
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_outer
void setPlatedCopperAndDepthOffset(PCB_LAYER_ID aLayer_id)
PCB_LAYER_ID
A quick note on layer IDs:
SFVEC4F m_BgColorTop
background top color
void setLight_Front(bool enabled)
float GetLayerBottomZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerBottomZpos3DU - Get the bottom z position.
#define NULL
MODULES & Modules()
Definition: class_board.h:247
void render_3D_module(const MODULE *module, bool aRenderTransparentOnly)
void setLight_Bottom(bool enabled)
bool m_is_opengl_initialized
flag if the opengl specific for this render was already initialized
void OGL_ResetTextureStateDefaults()
OGL_ResetTextureStateDefaults - resets to default state the texture settings.
Definition: ogl_utils.cpp:213
void SetCurWindowSize(const wxSize &aSize) override
SetCurWindowSize - Before each render, the canvas will tell the render what is the size of its window...
const BOARD * GetBoard() const noexcept
GetBoard - Get current board to be rendered.
SFVEC4F m_BgColorBot
background bottom color
wxSize m_windowSize
The window size that this camera is working.
static void BeginDrawMulti()
BeginDrawMulti - set some basic render states before drawing multiple models.
MODULE_ATTR_T
Enum MODULE_ATTR_T is the set of attributes allowed within a MODULE, using MODULE::SetAttributes() an...
Definition: class_module.h:66
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_vias_outer
void DrawAllCameraCulled(float zCameraPos, bool aDrawMiddle=true) const
DrawAllCameraCulled - Draw all layers if they are visible by the camera.
struct C3D_RENDER_OGL_LEGACY::@0 m_materials
std::unique_ptr< BUSY_INDICATOR > CreateBusyIndicator() const
Return a created busy indicator, if a factory has been set, else a null pointer.
void reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
void OGL_SetMaterial(const SMATERIAL &aMaterial, float aOpacity)
OGL_SetMaterial - Set OpenGL materials.
Definition: ogl_utils.cpp:145
GRID3D_TYPE
Grid types.
Definition: 3d_enums.h:95
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_via
BOARD_ADAPTER & m_boardAdapter
settings refrence in use for this render
GLuint m_ogl_disp_list_grid
oGL list that stores current grid
void DrawAll(bool aDrawMiddle=true) const
DrawAll - This function calls all the display lists.
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_inner
The CLAYERS_OGL_DISP_LISTS class stores the openGL display lists to related with a layer.
#define SIZE_OF_CIRCLE_TEXTURE
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_outer_with_npth
std::list< MODULE_3D_SETTINGS > & Models()
Definition: class_module.h:214
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
GetLayerColor - get the technical color of a layer.
const int scale
bool ShouldModuleBeDisplayed(MODULE_ATTR_T aModuleAttributs) const
ShouldModuleBeDisplayed - Test if module should be displayed in relation to attributs and the flags.
const glm::mat4 & GetViewMatrix() const
Definition: ccamera.cpp:419
bool m_reloadRequested
!TODO: this must be reviewed in order to flag change types
#define _(s)
Definition: 3d_actions.cpp:33
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
void SetItIsTransparent(bool aSetTransparent)
SFVEC4F m_CopperColor
in realistic mode: copper color
bool Redraw(bool aIsMoving, REPORTER *aStatusReporter, REPORTER *aWarningReporter) override
Redraw - Ask to redraw the view.
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
SphericalToCartesian.
Definition: 3d_math.h:43
float GetNonCopperLayerThickness3DU() const noexcept
GetNonCopperLayerThickness3DU - Get the current non copper layers thickness.
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_board
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
implements generic openGL functions that are common to any openGL target
float GetModulesZcoord3DIU(bool aIsFlipped) const
GetModulesZcoord3DIU - Get the position of the module in 3d integer units considering if it is flippe...
const glm::mat4 & GetProjectionMatrix() const
Definition: ccamera.cpp:389
SFVEC4F get_layer_color(PCB_LAYER_ID aLayerID)
Defines math related functions.
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
wxPoint GetBoardPosBIU() const noexcept
GetBoardPosBIU - Get the board size.
wxPoint GetPosition() const override
Definition: class_module.h:219
CIMAGE manages a 8-bit channel image.
Definition: cimage.h:89
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_vias_and_pad_holes_outer_contourn_and_caps
float GetEpoxyThickness3DU() const noexcept
GetEpoxyThickness3DU - Get the current epoxy thickness.
void set_layer_material(PCB_LAYER_ID aLayerID)
C3D_RENDER_OGL_LEGACY(BOARD_ADAPTER &aAdapter, CCAMERA &aCamera)
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_pads_holes
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
GRID3D_TYPE GridGet() const noexcept
GridGet - get the current grid.
static constexpr int Millimeter2iu(double mm)
Class BOARD_ADAPTER Helper class to handle information needed to display 3D board.
Definition: board_adapter.h:68
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:61
void render_board_body(bool aSkipRenderHoles)
void EfxFilter(CIMAGE *aInImg, IMAGE_FILTER aFilterType)
Function EfxFilter apply a filter to the input image and stores it in the image class this <- FilterT...
Definition: cimage.cpp:472
void OGL_draw_arrow(SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize)
OGL_draw_arrow - draw a round arrow.
This is a base class to hold data and functions for render targets.