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 
66  //m_ogl_disp_list_through_holes_vias_inner = NULL;
70 
74 
75  m_3dmodel_map.clear();
76 }
77 
78 
80 {
81  wxLogTrace( m_logTrace, wxT( "C3D_RENDER_OGL_LEGACY::~C3D_RENDER_OGL_LEGACY" ) );
82 
84 
85  glDeleteTextures( 1, &m_ogl_circle_texture );
86 }
87 
88 
90 {
91  return 50; // ms
92 }
93 
94 
95 void C3D_RENDER_OGL_LEGACY::SetCurWindowSize( const wxSize &aSize )
96 {
97  if( m_windowSize != aSize )
98  {
99  m_windowSize = aSize;
100  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
101 
102  // Initialize here any screen dependent data here
103  }
104 }
105 
106 
108 {
109  if( enabled )
110  glEnable( GL_LIGHT0 );
111  else
112  glDisable( GL_LIGHT0 );
113 }
114 
115 
117 {
118  if( enabled )
119  glEnable( GL_LIGHT1 );
120  else
121  glDisable( GL_LIGHT1 );
122 }
123 
124 
126 {
127  if( enabled )
128  glEnable( GL_LIGHT2 );
129  else
130  glDisable( GL_LIGHT2 );
131 }
132 
133 
135 {
136  const float arrow_size = RANGE_SCALE_3D * 0.30f;
137 
138  glDisable( GL_CULL_FACE );
139 
140  // YxY squared view port, this is on propose
141  glViewport( 4, 4, m_windowSize.y / 8 , m_windowSize.y / 8 );
142  glClear( GL_DEPTH_BUFFER_BIT );
143 
144  glMatrixMode( GL_PROJECTION );
145  glLoadIdentity();
146  gluPerspective( 45.0f, 1.0f, 0.001f, RANGE_SCALE_3D );
147 
148  glMatrixMode( GL_MODELVIEW );
149  glLoadIdentity();
150 
151  const glm::mat4 TranslationMatrix = glm::translate(
152  glm::mat4(1.0f),
153  SFVEC3F( 0.0f, 0.0f, -(arrow_size * 2.75f) ) );
154 
155  const glm::mat4 ViewMatrix = TranslationMatrix * m_camera.GetRotationMatrix();
156 
157  glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
158 
160 
161  glColor3f( 0.9f, 0.0f, 0.0f );
162  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
163  SFVEC3F( arrow_size, 0.0f, 0.0f ),
164  0.275f );
165 
166  glColor3f( 0.0f, 0.9f, 0.0f );
167  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
168  SFVEC3F( 0.0f, arrow_size, 0.0f ),
169  0.275f );
170 
171  glColor3f( 0.0f, 0.0f, 0.9f );
172  OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
173  SFVEC3F( 0.0f, 0.0f, arrow_size ),
174  0.275f );
175 
176  glEnable( GL_CULL_FACE );
177 }
178 
179 
181 {
182  m_materials = {};
183 
185  {
186  // http://devernay.free.fr/cours/opengl/materials.html
187 
188  // Copper material mixed with the copper color
189  m_materials.m_Copper.m_Ambient = SFVEC3F( m_boardAdapter.m_CopperColor.r * 0.1f,
190  m_boardAdapter.m_CopperColor.g * 0.1f,
191  m_boardAdapter.m_CopperColor.b * 0.1f);
192 
193  m_materials.m_Copper.m_Specular = SFVEC3F( m_boardAdapter.m_CopperColor.r * 0.75f + 0.25f,
194  m_boardAdapter.m_CopperColor.g * 0.75f + 0.25f,
195  m_boardAdapter.m_CopperColor.b * 0.75f + 0.25f );
196 
197  // This guess the material type(ex: copper vs gold) to determine the
198  // shininess factor between 0.1 and 0.4
199  float shininessfactor = 0.40f - mapf( fabs( m_boardAdapter.m_CopperColor.r -
201  0.15f, 1.00f,
202  0.00f, 0.30f );
203 
204  m_materials.m_Copper.m_Shininess = shininessfactor * 128.0f;
205  m_materials.m_Copper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
206 
207 
208  // Paste material mixed with paste color
209  m_materials.m_Paste.m_Ambient = SFVEC3F( m_boardAdapter.m_SolderPasteColor.r,
212 
213  m_materials.m_Paste.m_Specular = SFVEC3F( m_boardAdapter.m_SolderPasteColor.r *
219 
220  m_materials.m_Paste.m_Shininess = 0.1f * 128.0f;
221  m_materials.m_Paste.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
222 
223 
224  // Silk screen material mixed with silk screen color
225  m_materials.m_SilkSTop.m_Ambient = SFVEC3F( m_boardAdapter.m_SilkScreenColorTop.r,
228 
229  m_materials.m_SilkSTop.m_Specular = SFVEC3F(
233 
234  m_materials.m_SilkSTop.m_Shininess = 0.078125f * 128.0f;
235  m_materials.m_SilkSTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
236 
237  // Silk screen material mixed with silk screen color
238  m_materials.m_SilkSBot.m_Ambient = SFVEC3F( m_boardAdapter.m_SilkScreenColorBot.r,
241 
242  m_materials.m_SilkSBot.m_Specular = SFVEC3F(
246 
247  m_materials.m_SilkSBot.m_Shininess = 0.078125f * 128.0f;
248  m_materials.m_SilkSBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
249 
250 
251  // Solder mask material mixed with solder mask color
252  m_materials.m_SolderMaskTop.m_Ambient = SFVEC3F(
256 
257  m_materials.m_SolderMaskTop.m_Specular = SFVEC3F(
261 
262  m_materials.m_SolderMaskTop.m_Shininess = 0.8f * 128.0f;
263  m_materials.m_SolderMaskTop.m_Transparency = 0.17f;
264  m_materials.m_SolderMaskTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
265 
266  // Solder mask material mixed with solder mask color
267  m_materials.m_SolderMaskBot.m_Ambient = SFVEC3F(
271 
272  m_materials.m_SolderMaskBot.m_Specular = SFVEC3F(
276 
277  m_materials.m_SolderMaskBot.m_Shininess = 0.8f * 128.0f;
278  m_materials.m_SolderMaskBot.m_Transparency = 0.17f;
279  m_materials.m_SolderMaskBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
280 
281 
282  // Epoxy material
283  m_materials.m_EpoxyBoard.m_Ambient = SFVEC3F( 117.0f / 255.0f,
284  97.0f / 255.0f,
285  47.0f / 255.0f );
286 
287  m_materials.m_EpoxyBoard.m_Diffuse = m_boardAdapter.m_BoardBodyColor;
288 
289  m_materials.m_EpoxyBoard.m_Specular = SFVEC3F( 18.0f / 255.0f,
290  3.0f / 255.0f,
291  20.0f / 255.0f );
292 
293  m_materials.m_EpoxyBoard.m_Shininess = 0.1f * 128.0f;
294  m_materials.m_EpoxyBoard.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
295  }
296  else // Technical Mode
297  {
298  const SFVEC3F matAmbientColor = SFVEC3F( 0.10f );
299  const SFVEC3F matSpecularColor = SFVEC3F( 0.10f );
300  const float matShininess = 0.1f * 128.0f;
301 
302  // Copper material
303  m_materials.m_Copper.m_Ambient = matAmbientColor;
304  m_materials.m_Copper.m_Specular = matSpecularColor;
305  m_materials.m_Copper.m_Shininess = matShininess;
306  m_materials.m_Copper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
307 
308  // Paste material
309  m_materials.m_Paste.m_Ambient = matAmbientColor;
310  m_materials.m_Paste.m_Specular = matSpecularColor;
311  m_materials.m_Paste.m_Shininess = matShininess;
312  m_materials.m_Paste.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
313 
314  // Silk screen material
315  m_materials.m_SilkSTop.m_Ambient = matAmbientColor;
316  m_materials.m_SilkSTop.m_Specular = matSpecularColor;
317  m_materials.m_SilkSTop.m_Shininess = matShininess;
318  m_materials.m_SilkSTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
319 
320  // Silk screen material
321  m_materials.m_SilkSBot.m_Ambient = matAmbientColor;
322  m_materials.m_SilkSBot.m_Specular = matSpecularColor;
323  m_materials.m_SilkSBot.m_Shininess = matShininess;
324  m_materials.m_SilkSBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
325 
326  // Solder mask material
327  m_materials.m_SolderMaskTop.m_Ambient = matAmbientColor;
328  m_materials.m_SolderMaskTop.m_Specular = matSpecularColor;
329  m_materials.m_SolderMaskTop.m_Shininess = matShininess;
330  m_materials.m_SolderMaskTop.m_Transparency = 0.17f;
331  m_materials.m_SolderMaskTop.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
332 
333  // Solder mask material
334  m_materials.m_SolderMaskBot.m_Ambient = matAmbientColor;
335  m_materials.m_SolderMaskBot.m_Specular = matSpecularColor;
336  m_materials.m_SolderMaskBot.m_Shininess = matShininess;
337  m_materials.m_SolderMaskBot.m_Transparency = 0.17f;
338  m_materials.m_SolderMaskBot.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
339 
340  // Epoxy material
341  m_materials.m_EpoxyBoard.m_Ambient = matAmbientColor;
342  m_materials.m_EpoxyBoard.m_Diffuse = m_boardAdapter.m_BoardBodyColor;
343  m_materials.m_EpoxyBoard.m_Specular = matSpecularColor;
344  m_materials.m_EpoxyBoard.m_Shininess = matShininess;
345  m_materials.m_EpoxyBoard.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
346 
347  // Gray material (used for example in technical vias and pad holes)
348  m_materials.m_GrayMaterial.m_Ambient = SFVEC3F( 0.8f, 0.8f, 0.8f );
349  m_materials.m_GrayMaterial.m_Diffuse = SFVEC3F( 0.3f, 0.3f, 0.3f );
350  m_materials.m_GrayMaterial.m_Specular = SFVEC3F( 0.4f, 0.4f, 0.4f );
351  m_materials.m_GrayMaterial.m_Shininess = 0.01f * 128.0f;
352  m_materials.m_GrayMaterial.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
353  }
354 }
355 
356 
358 {
359  switch( aLayerID )
360  {
361  case B_Mask:
362  m_materials.m_SolderMaskBot.m_Diffuse = get_layer_color( aLayerID );
363  OGL_SetMaterial( m_materials.m_SolderMaskBot, 1.0f );
364  break;
365  case F_Mask:
366  m_materials.m_SolderMaskTop.m_Diffuse = get_layer_color( aLayerID );
367  OGL_SetMaterial( m_materials.m_SolderMaskTop, 1.0f );
368  break;
369 
370  case B_Paste:
371  case F_Paste:
372  m_materials.m_Paste.m_Diffuse = get_layer_color( aLayerID );
373  OGL_SetMaterial( m_materials.m_Paste, 1.0f );
374  break;
375 
376  case B_SilkS:
377  m_materials.m_SilkSBot.m_Diffuse = get_layer_color( aLayerID );
378  OGL_SetMaterial( m_materials.m_SilkSBot, 1.0f );
379  break;
380 
381  case F_SilkS:
382  m_materials.m_SilkSTop.m_Diffuse = get_layer_color( aLayerID );
383  OGL_SetMaterial( m_materials.m_SilkSTop, 1.0f );
384  break;
385 
386  case B_Adhes:
387  case F_Adhes:
388  case Dwgs_User:
389  case Cmts_User:
390  case Eco1_User:
391  case Eco2_User:
392  case Edge_Cuts:
393  case Margin:
394  case B_CrtYd:
395  case F_CrtYd:
396  case B_Fab:
397  case F_Fab:
398  m_materials.m_Plastic.m_Diffuse = get_layer_color( aLayerID );
399  m_materials.m_Plastic.m_Ambient = SFVEC3F(
400  m_materials.m_Plastic.m_Diffuse.r * 0.05f,
401  m_materials.m_Plastic.m_Diffuse.g * 0.05f,
402  m_materials.m_Plastic.m_Diffuse.b * 0.05f );
403 
404  m_materials.m_Plastic.m_Specular = SFVEC3F(
405  m_materials.m_Plastic.m_Diffuse.r * 0.7f,
406  m_materials.m_Plastic.m_Diffuse.g * 0.7f,
407  m_materials.m_Plastic.m_Diffuse.b * 0.7f );
408 
409  m_materials.m_Plastic.m_Shininess = 0.078125f * 128.0f;
410  m_materials.m_Plastic.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f );
411  OGL_SetMaterial( m_materials.m_Plastic, 1.0f );
412  break;
413 
414  default:
415  m_materials.m_Copper.m_Diffuse = get_layer_color( aLayerID );
416  OGL_SetMaterial( m_materials.m_Copper, 1.0f );
417 
418  break;
419  }
420 }
421 
422 
424 {
425  SFVEC3F layerColor = m_boardAdapter.GetLayerColor( aLayerID );
426 
428  {
429  switch( aLayerID )
430  {
431  case B_Adhes:
432  case F_Adhes:
433  break;
434 
435  case B_Mask:
437  break;
438  case F_Mask:
440  break;
441 
442  case B_Paste:
443  case F_Paste:
444  layerColor = m_boardAdapter.m_SolderPasteColor;
445  break;
446 
447  case B_SilkS:
449  break;
450  case F_SilkS:
452  break;
453 
454  case Dwgs_User:
455  case Cmts_User:
456  case Eco1_User:
457  case Eco2_User:
458  case Edge_Cuts:
459  case Margin:
460  break;
461 
462  case B_CrtYd:
463  case F_CrtYd:
464  break;
465 
466  case B_Fab:
467  case F_Fab:
468  break;
469 
470  default:
471  layerColor = m_boardAdapter.m_CopperColor;
472  break;
473  }
474  }
475 
476  return layerColor;
477 }
478 
479 void init_lights(void)
480 {
481  // Setup light
482  // https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
483  // /////////////////////////////////////////////////////////////////////////
484  const GLfloat ambient[] = { 0.084f, 0.084f, 0.084f, 1.0f };
485  const GLfloat diffuse0[] = { 0.3f, 0.3f, 0.3f, 1.0f };
486  const GLfloat specular0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
487 
488  glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
489  glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse0 );
490  glLightfv( GL_LIGHT0, GL_SPECULAR, specular0 );
491 
492  const GLfloat diffuse12[] = { 0.7f, 0.7f, 0.7f, 1.0f };
493  const GLfloat specular12[] = { 0.7f, 0.7f, 0.7f, 1.0f };
494 
495  // defines a directional light that points along the negative z-axis
496  GLfloat position[4] = { 0.0f, 0.0f, 1.0f, 0.0f };
497 
498  // This makes a vector slight not perpendicular with XZ plane
499  const SFVEC3F vectorLight = SphericalToCartesian( glm::pi<float>() * 0.03f,
500  glm::pi<float>() * 0.25f );
501 
502  position[0] = vectorLight.x;
503  position[1] = vectorLight.y;
504  position[2] = vectorLight.z;
505 
506  glLightfv( GL_LIGHT1, GL_AMBIENT, ambient );
507  glLightfv( GL_LIGHT1, GL_DIFFUSE, diffuse12 );
508  glLightfv( GL_LIGHT1, GL_SPECULAR, specular12 );
509  glLightfv( GL_LIGHT1, GL_POSITION, position );
510 
511 
512  // defines a directional light that points along the positive z-axis
513  position[2] = -position[2];
514 
515  glLightfv( GL_LIGHT2, GL_AMBIENT, ambient );
516  glLightfv( GL_LIGHT2, GL_DIFFUSE, diffuse12 );
517  glLightfv( GL_LIGHT2, GL_SPECULAR, specular12 );
518  glLightfv( GL_LIGHT2, GL_POSITION, position );
519 
520  const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
521 
522  glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
523 
524  glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
525 }
526 
527 
529  bool aIsMoving, REPORTER* aStatusReporter, REPORTER* aWarningReporter )
530 {
531  // Initialize openGL
533  {
534  if( !initializeOpenGL() )
535  return false;
536  }
537 
538  if( m_reloadRequested )
539  {
540  std::unique_ptr<BUSY_INDICATOR> busy = CreateBusyIndicator();
541 
542  if( aStatusReporter )
543  aStatusReporter->Report( _( "Loading..." ) );
544 
545  reload( aStatusReporter, aWarningReporter );
546  setupMaterials();
547 
548  // generate a new 3D grid as the size of the board may had changed
551  }
552  else
553  {
554  // Check if grid was changed
556  {
557  // and generate a new one
560  }
561  }
562 
563  // Initial setup
564  // /////////////////////////////////////////////////////////////////////////
565  glDepthFunc( GL_LESS );
566  glEnable( GL_CULL_FACE );
567  glFrontFace( GL_CCW ); // This is the openGL default
568  glEnable( GL_NORMALIZE ); // This allow openGL to normalize the normals after transformations
569 
570  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
571 
573  {
574  if( !aIsMoving )
575  {
576  glEnable( GL_MULTISAMPLE );
577  }
578  else
579  {
580  glDisable( GL_MULTISAMPLE );
581  }
582  }
583 
584  // clear color and depth buffers
585  // /////////////////////////////////////////////////////////////////////////
586  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
587  glClearDepth( 1.0f );
588  glClearStencil( 0x00 );
589  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
590 
592 
593  // Draw the background ( rectangle with color gradient)
594  // /////////////////////////////////////////////////////////////////////////
597 
598  glEnable( GL_DEPTH_TEST );
599 
600 
601  // Set projection and modelview matrixes
602  // /////////////////////////////////////////////////////////////////////////
603  glMatrixMode( GL_PROJECTION );
604  glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
605 
606  glMatrixMode( GL_MODELVIEW );
607  glLoadIdentity();
608  glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
609 
610 
611  // Position the headlight
612  // /////////////////////////////////////////////////////////////////////////
613 
614  setLight_Front( true );
615  setLight_Top( true );
616  setLight_Bottom( true );
617 
618  glEnable( GL_LIGHTING );
619 
620  {
621  const SFVEC3F &cameraPos = m_camera.GetPos();
622 
623  // Place the light at a minimun Z so the diffuse factor will not drop
624  // and the board will still look with good light.
625  float zpos;
626 
627  if( cameraPos.z > 0.0f )
628  {
629  zpos = glm::max( cameraPos.z, 0.5f ) + cameraPos.z * cameraPos.z;
630  }
631  else
632  {
633  zpos = glm::min( cameraPos.z,-0.5f ) - cameraPos.z * cameraPos.z;
634  }
635 
636  const GLfloat headlight_pos[] = { cameraPos.x,
637  cameraPos.y,
638  zpos,
639  1.0f }; // This is a point light
640 
641  glLightfv( GL_LIGHT0, GL_POSITION, headlight_pos );
642  }
643 
644  const bool drawMiddleSegments = !( aIsMoving &&
646 
647  const bool skipRenderHoles = aIsMoving &&
649 
650  const bool skipRenderVias = aIsMoving &&
652 
653  // Display board body
654  // /////////////////////////////////////////////////////////////////////////
656  {
658  {
661 
662  OGL_SetMaterial( m_materials.m_EpoxyBoard, 1.0f );
663 
665 
666  if( (m_ogl_disp_list_through_holes_outer_with_npth) && (!skipRenderHoles) )
667  {
671 
674  NULL );
675  }
676  else
677  {
679  }
680  }
681  }
682 
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 
712  const PCB_LAYER_ID layer_id = (PCB_LAYER_ID)(ii->first);
713 
714  // Mask kayers are not processed here because they are a special case
715  if( (layer_id == B_Mask) || (layer_id == F_Mask) )
716  continue;
717 
718  // Do not show inner layers when it is displaying the board
720  {
721  if( (layer_id > F_Cu) && (layer_id < B_Cu) )
722  continue;
723  }
724 
725  glPushMatrix();
726 
727  // !TODO: if we want to increase the separation between layers
728  //glScalef( 1.0f, 1.0f, 3.0f );
729 
730 
731  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
732  set_layer_material( layer_id );
733 
734  if( (layer_id >= F_Cu) && (layer_id <= B_Cu) )
735  {
736  if( skipRenderHoles )
737  {
738  pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
739  }
740  else
741  {
744  pLayerDispList->GetZBot(),
745  pLayerDispList->GetZTop() - pLayerDispList->GetZBot() );
746 
747  if( m_ogl_disp_lists_layers_holes_outer.find( layer_id ) !=
749  {
750  const CLAYERS_OGL_DISP_LISTS* viasHolesLayer =
752 
753  wxASSERT( viasHolesLayer != NULL );
754 
755  if( viasHolesLayer != NULL )
756  {
757  pLayerDispList->DrawAllCameraCulledSubtractLayer(
759  viasHolesLayer,
760  drawMiddleSegments );
761  }
762  }
763  else
764  {
765  pLayerDispList->DrawAllCameraCulledSubtractLayer(
767  NULL,
768  drawMiddleSegments );
769  }
770  }
771  }
772  else
773  {
776  pLayerDispList->GetZBot(),
777  pLayerDispList->GetZTop() - pLayerDispList->GetZBot() );
778 
779  if( (!skipRenderHoles) &&
781  ( ( ( layer_id == B_SilkS ) &&
782  ( m_ogl_disp_lists_layers.find( B_Mask ) != m_ogl_disp_lists_layers.end() ) ) ||
783  ( ( layer_id == F_SilkS ) &&
784  ( m_ogl_disp_lists_layers.find( F_Mask ) != m_ogl_disp_lists_layers.end() ) ) ) )
785  {
786  const PCB_LAYER_ID layerMask_id = (layer_id == B_SilkS)?B_Mask:F_Mask;
787 
788  const CLAYERS_OGL_DISP_LISTS *pLayerDispListMask = m_ogl_disp_lists_layers.at( layerMask_id );
789 
790  pLayerDispList->DrawAllCameraCulledSubtractLayer(
791  pLayerDispListMask,
793  drawMiddleSegments );
794  }
795  else
796  {
797  if( (!skipRenderHoles) &&
799  ( ( layer_id == B_SilkS ) || ( layer_id == F_SilkS )
800  // Remove vias on SolderPaste can be added as an option in future
801  // ( layer_id == B_Paste ) || ( layer_id == F_Paste ) )
802  ) )
803  {
804  pLayerDispList->DrawAllCameraCulledSubtractLayer(
805  NULL,
807  drawMiddleSegments );
808  }
809  else
810  {
811  // Do not render Paste layers when skipRenderHoles is enabled
812  // otherwise it will cause z-fight issues
813  if( !( skipRenderHoles &&
814  ( ( layer_id == B_Paste ) || ( layer_id == F_Paste ) ) ) )
815  {
816  pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
817  }
818  }
819  }
820  }
821 
822  glPopMatrix();
823  }
824 
825 
826  // Render 3D Models (Non-transparent)
827  // /////////////////////////////////////////////////////////////////////////
828  render_3D_models( false, false );
829  render_3D_models( true, false );
830 
831 
832  // Display transparent mask layers
833  // /////////////////////////////////////////////////////////////////////////
835  {
836  //setLight_Top( true );
837  //setLight_Bottom( true );
838 
839  // add a depth buffer offset, it will help to hide some artifacts
840  // on silkscreen where the SolderMask is removed
841  glEnable( GL_POLYGON_OFFSET_FILL );
842  glPolygonOffset( 0.0f, -1.0f );
843 
844  if( m_camera.GetPos().z > 0 )
845  {
847  drawMiddleSegments, skipRenderHoles );
848 
850  drawMiddleSegments, skipRenderHoles );
851  }
852  else
853  {
855  drawMiddleSegments, skipRenderHoles );
856 
858  drawMiddleSegments, skipRenderHoles );
859  }
860 
861  glDisable( GL_POLYGON_OFFSET_FILL );
862  glPolygonOffset( 0.0f, 0.0f );
863  }
864 
865 
866  // Render 3D Models (Transparent)
867  // /////////////////////////////////////////////////////////////////////////
868  // !TODO: this can be optimized. If there are no transparent models (or no opacity),
869  // then there is no need to make this function call.
870 
871  glDepthMask( GL_FALSE );
872 
873  glEnable( GL_BLEND );
874  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
875 
876  // Enables Texture Env so it can combine model transparency with
877  // each module opacity setting
878  glEnable( GL_TEXTURE_2D );
879  glActiveTexture( GL_TEXTURE0 );
880 
881  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
882  glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE );
883  glTexEnvf( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE );
884 
885  glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR );
886  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
887 
888  glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS );
889  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
890 
891  glTexEnvi( GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR );
892  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
893  glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT );
894  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_CONSTANT );
895 
896  render_3D_models( false, true );
897  render_3D_models( true, true );
898 
899  glDisable( GL_BLEND );
901 
902  glDepthMask( GL_TRUE );
903 
904  // Render Grid
905  // /////////////////////////////////////////////////////////////////////////
906 
908  {
909  glDisable( GL_LIGHTING );
910 
911  if( glIsList( m_ogl_disp_list_grid ) )
912  glCallList( m_ogl_disp_list_grid );
913 
914  glEnable( GL_LIGHTING );
915  }
916 
917 
918  // Render 3D arrows
919  // /////////////////////////////////////////////////////////////////////////
922 
923  // Return back to the original viewport (this is important if we want
924  // to take a screenshot after the render)
925  // /////////////////////////////////////////////////////////////////////////
926  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
927 
928  return false;
929 }
930 
931 
933 {
934  glEnable( GL_LINE_SMOOTH );
935  glShadeModel( GL_SMOOTH );
936 
937  // 4-byte pixel alignment
938  glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
939 
940  // Initialize the open GL texture to draw the filled semi-circle of the segments
942 
943  if( !circleImage )
944  return false;
945 
946  circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 2) - 0,
947  (SIZE_OF_CIRCLE_TEXTURE / 2) - 0,
948  (SIZE_OF_CIRCLE_TEXTURE / 2) - 4,
949  0xFF );
950 
951  //circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1,
952  // (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1,
953  // (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 2, 0xFF );
954 
955  CIMAGE *circleImage_Copy = new CIMAGE( *circleImage );
956 
957  circleImage->EfxFilter( circleImage_Copy, IMAGE_FILTER::BLUR_3X3 );
958 
959  m_ogl_circle_texture = OGL_LoadTexture( *circleImage );
960 
961  //circleImage_Copy->SaveAsPNG("circleImage.png");
962  delete circleImage_Copy;
963  circleImage_Copy = 0;
964 
965  //circleImage->SaveAsPNG("circleImage_blured.png");
966  delete circleImage;
967  circleImage = 0;
968 
969  init_lights();
970 
971  // Use this mode if you want see the triangle lines (debug proposes)
972  //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
973 
975 
976  return true;
977 }
978 
979 
981 {
982  glEnable( GL_COLOR_MATERIAL );
983  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
984 
985  const SFVEC4F ambient = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
986  const SFVEC4F diffuse = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
987  const SFVEC4F emissive = SFVEC4F( 0.0f, 0.0f, 0.0f, 1.0f );
988  const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
989 
990  glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
991  glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
992 
993  glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r );
994  glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r );
995  glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r );
996 }
997 
998 
1000 {
1001  if( glIsList( m_ogl_disp_list_grid ) )
1002  glDeleteLists( m_ogl_disp_list_grid, 1 );
1003 
1005 
1006  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers.begin();
1007  ii != m_ogl_disp_lists_layers.end();
1008  ++ii )
1009  {
1010  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1011  delete pLayerDispList;
1012  }
1013 
1014  m_ogl_disp_lists_layers.clear();
1015 
1016 
1017  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers_holes_outer.begin();
1019  ++ii )
1020  {
1021  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1022  delete pLayerDispList;
1023  }
1024 
1026 
1027 
1028  for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers_holes_inner.begin();
1030  ++ii )
1031  {
1032  CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
1033  delete pLayerDispList;
1034  }
1035 
1037 
1038  for( MAP_TRIANGLES::const_iterator ii = m_triangles.begin();
1039  ii != m_triangles.end();
1040  ++ii )
1041  {
1042  CLAYER_TRIANGLES *pointer = static_cast<CLAYER_TRIANGLES*>(ii->second);
1043  delete pointer;
1044  }
1045 
1046  m_triangles.clear();
1047 
1048 
1049  for( MAP_3DMODEL::const_iterator ii = m_3dmodel_map.begin();
1050  ii != m_3dmodel_map.end();
1051  ++ii )
1052  {
1053  C_OGL_3DMODEL *pointer = static_cast<C_OGL_3DMODEL*>(ii->second);
1054  delete pointer;
1055  }
1056 
1057  m_3dmodel_map.clear();
1058 
1059 
1060  delete m_ogl_disp_list_board;
1062 
1065 
1068 
1071 
1072  delete m_ogl_disp_list_via;
1073  m_ogl_disp_list_via = 0;
1074 
1077 
1080 }
1081 
1082 
1084  float aZPosition,
1085  bool aDrawMiddleSegments,
1086  bool aSkipRenderHoles )
1087 {
1088  wxASSERT( (aLayerID == B_Mask) || (aLayerID == F_Mask) );
1089 
1090  if( m_ogl_disp_list_board )
1091  {
1092  if( m_ogl_disp_lists_layers.find( aLayerID ) !=
1093  m_ogl_disp_lists_layers.end() )
1094  {
1095  CLAYERS_OGL_DISP_LISTS *pLayerDispListMask = m_ogl_disp_lists_layers.at( aLayerID );
1096 
1099  aZPosition,
1101 
1103  aZPosition,
1105 
1106  set_layer_material( aLayerID );
1107 
1109 
1110  if( aSkipRenderHoles )
1111  {
1113  aDrawMiddleSegments );
1114  }
1115  else
1116  {
1118  pLayerDispListMask,
1120  aDrawMiddleSegments );
1121  }
1122  }
1123  else
1124  {
1125  // This case there is no layer with mask, so we will render the full board as mask
1126 
1129  aZPosition,
1131 
1133  aZPosition,
1135 
1136  set_layer_material( aLayerID );
1137 
1139 
1140  if( aSkipRenderHoles )
1141  {
1143  aDrawMiddleSegments );
1144  }
1145  else
1146  {
1148  NULL,
1150  aDrawMiddleSegments );
1151  }
1152  }
1153  }
1154 }
1155 
1156 
1157 void C3D_RENDER_OGL_LEGACY::render_3D_models( bool aRenderTopOrBot,
1158  bool aRenderTransparentOnly )
1159 {
1161 
1162  // Go for all modules
1163  for( auto module : m_boardAdapter.GetBoard()->Modules() )
1164  {
1165  if( !module->Models().empty() )
1166  if( m_boardAdapter.ShouldModuleBeDisplayed((MODULE_ATTR_T) module->GetAttributes() ) )
1167  if( ( aRenderTopOrBot && !module->IsFlipped() )
1168  || ( !aRenderTopOrBot && module->IsFlipped() ) )
1169  render_3D_module( module, aRenderTransparentOnly );
1170  }
1171 
1173 }
1174 
1175 
1177  bool aRenderTransparentOnly )
1178 {
1179  if( !module->Models().empty() )
1180  {
1181  const double zpos = m_boardAdapter.GetModulesZcoord3DIU( module->IsFlipped() );
1182 
1183  glPushMatrix();
1184 
1185  wxPoint pos = module->GetPosition();
1186 
1187  glTranslatef( pos.x * m_boardAdapter.BiuTo3Dunits(),
1188  -pos.y * m_boardAdapter.BiuTo3Dunits(),
1189  zpos );
1190 
1191  if( module->GetOrientation() )
1192  glRotated( (double) module->GetOrientation() / 10.0, 0.0, 0.0, 1.0 );
1193 
1194  if( module->IsFlipped() )
1195  {
1196  glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
1197  glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
1198  }
1199 
1200  double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3Dunits() * UNITS3D_TO_UNITSPCB;
1201 
1202  glScaled( modelunit_to_3d_units_factor,
1203  modelunit_to_3d_units_factor,
1204  modelunit_to_3d_units_factor );
1205 
1206  // Get the list of model files for this model
1207  for( auto& sM : module->Models () )
1208  {
1209  if( sM.m_Filename.empty() )
1210  continue;
1211 
1212  // Check if the model is present in our cache map
1213  auto cache_i = m_3dmodel_map.find( sM.m_Filename );
1214 
1215  if( cache_i == m_3dmodel_map.end() )
1216  continue;
1217 
1218  if( const C_OGL_3DMODEL *modelPtr = cache_i->second )
1219  {
1220  bool opaque = sM.m_Opacity >= 1.0;
1221 
1222  if( ( !aRenderTransparentOnly && modelPtr->Have_opaque() && opaque ) ||
1223  ( aRenderTransparentOnly && ( modelPtr->Have_transparent() || !opaque ) ) )
1224  {
1225  glPushMatrix();
1226 
1227  // FIXME: don't do this over and over again unless the
1228  // values have changed. cache the matrix somewhere.
1229  glm::mat4 mtx( 1 );
1230  mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
1231  mtx = glm::rotate(
1232  mtx, glm::radians( (float) -sM.m_Rotation.z ), { 0.0f, 0.0f, 1.0f } );
1233  mtx = glm::rotate(
1234  mtx, glm::radians( (float) -sM.m_Rotation.y ), { 0.0f, 1.0f, 0.0f } );
1235  mtx = glm::rotate(
1236  mtx, glm::radians( (float) -sM.m_Rotation.x ), { 1.0f, 0.0f, 0.0f } );
1237  mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } );
1238  glMultMatrixf( glm::value_ptr( mtx ) );
1239 
1240  if( aRenderTransparentOnly )
1241  modelPtr->Draw_transparent( sM.m_Opacity );
1242  else
1243  modelPtr->Draw_opaque();
1244 
1246  {
1247  glEnable( GL_BLEND );
1248  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1249 
1250  glDisable( GL_LIGHTING );
1251 
1252  glLineWidth( 1 );
1253  modelPtr->Draw_bboxes();
1254 
1255  glLineWidth( 4 );
1256  modelPtr->Draw_bbox();
1257 
1258  glEnable( GL_LIGHTING );
1259  glDisable( GL_BLEND );
1260  }
1261 
1262  glPopMatrix();
1263  }
1264  }
1265  }
1266 
1267  glPopMatrix();
1268  }
1269 }
1270 
1271 
1272 // create a 3D grid to an openGL display list: an horizontal grid (XY plane and Z = 0,
1273 // and a vertical grid (XZ plane and Y = 0)
1275 {
1276  if( glIsList( m_ogl_disp_list_grid ) )
1277  glDeleteLists( m_ogl_disp_list_grid, 1 );
1278 
1280 
1281  if( aGridType == GRID3D_TYPE::NONE )
1282  return;
1283 
1284  m_ogl_disp_list_grid = glGenLists( 1 );
1285 
1286  if( !glIsList( m_ogl_disp_list_grid ) )
1287  return;
1288 
1289  glNewList( m_ogl_disp_list_grid, GL_COMPILE );
1290 
1291  glEnable( GL_BLEND );
1292  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1293 
1294  const double zpos = 0.0;
1295 
1296  // Color of grid lines
1297  const SFVEC3F gridColor = m_boardAdapter.GetColor( DARKGRAY );
1298 
1299  // Color of grid lines every 5 lines
1300  const SFVEC3F gridColor_marker = m_boardAdapter.GetColor( LIGHTGRAY );
1301  const double scale = m_boardAdapter.BiuTo3Dunits();
1302  const double transparency = 0.35;
1303 
1304  double griSizeMM = 0.0;
1305 
1306  switch( aGridType )
1307  {
1308  default:
1309  case GRID3D_TYPE::NONE:
1310  return;
1311  case GRID3D_TYPE::GRID_1MM:
1312  griSizeMM = 1.0;
1313  break;
1315  griSizeMM = 2.5;
1316  break;
1317  case GRID3D_TYPE::GRID_5MM:
1318  griSizeMM = 5.0;
1319  break;
1321  griSizeMM = 10.0;
1322  break;
1323  }
1324 
1325  glNormal3f( 0.0, 0.0, 1.0 );
1326 
1327  const wxSize brd_size = m_boardAdapter.GetBoardSizeBIU();
1328  wxPoint brd_center_pos = m_boardAdapter.GetBoardPosBIU();
1329 
1330  brd_center_pos.y = -brd_center_pos.y;
1331 
1332  const int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) ) * 1.2;
1333  const int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) ) * 1.2;
1334 
1335  // Grid limits, in 3D units
1336  double xmin = (brd_center_pos.x - xsize / 2) * scale;
1337  double xmax = (brd_center_pos.x + xsize / 2) * scale;
1338  double ymin = (brd_center_pos.y - ysize / 2) * scale;
1339  double ymax = (brd_center_pos.y + ysize / 2) * scale;
1340  double zmin = Millimeter2iu( -50 ) * scale;
1341  double zmax = Millimeter2iu( 100 ) * scale;
1342 
1343  // Draw horizontal grid centered on 3D origin (center of the board)
1344  for( int ii = 0; ; ii++ )
1345  {
1346  if( (ii % 5) )
1347  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1348  else
1349  glColor4f( gridColor_marker.r,
1350  gridColor_marker.g,
1351  gridColor_marker.b,
1352  transparency );
1353 
1354  const int delta = KiROUND( ii * griSizeMM * IU_PER_MM );
1355 
1356  if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
1357  {
1358  glBegin( GL_LINES );
1359  glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
1360  glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
1361  glEnd();
1362 
1363  if( ii != 0 )
1364  {
1365  glBegin( GL_LINES );
1366  glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
1367  glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
1368  glEnd();
1369  }
1370  }
1371 
1372  if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
1373  {
1374  glBegin( GL_LINES );
1375  glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
1376  glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
1377  glEnd();
1378 
1379  if( ii != 0 )
1380  {
1381  glBegin( GL_LINES );
1382  glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
1383  glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
1384  glEnd();
1385  }
1386  }
1387 
1388  if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
1389  break;
1390  }
1391 
1392  // Draw vertical grid on Z axis
1393  glNormal3f( 0.0, -1.0, 0.0 );
1394 
1395  // Draw vertical grid lines (parallel to Z axis)
1396  double posy = -brd_center_pos.y * scale;
1397 
1398  for( int ii = 0; ; ii++ )
1399  {
1400  if( (ii % 5) )
1401  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1402  else
1403  glColor4f( gridColor_marker.r,
1404  gridColor_marker.g,
1405  gridColor_marker.b,
1406  transparency );
1407 
1408  const double delta = ii * griSizeMM * IU_PER_MM;
1409 
1410  glBegin( GL_LINES );
1411  xmax = (brd_center_pos.x + delta) * scale;
1412 
1413  glVertex3f( xmax, posy, zmin );
1414  glVertex3f( xmax, posy, zmax );
1415  glEnd();
1416 
1417  if( ii != 0 )
1418  {
1419  glBegin( GL_LINES );
1420  xmin = (brd_center_pos.x - delta) * scale;
1421  glVertex3f( xmin, posy, zmin );
1422  glVertex3f( xmin, posy, zmax );
1423  glEnd();
1424  }
1425 
1426  if( delta > xsize / 2.0f )
1427  break;
1428  }
1429 
1430  // Draw horizontal grid lines on Z axis (parallel to X axis)
1431  for( int ii = 0; ; ii++ )
1432  {
1433  if( (ii % 5) )
1434  glColor4f( gridColor.r, gridColor.g, gridColor.b, transparency );
1435  else
1436  glColor4f( gridColor_marker.r,
1437  gridColor_marker.g,
1438  gridColor_marker.b,
1439  transparency );
1440 
1441  const double delta = ii * griSizeMM * IU_PER_MM * scale;
1442 
1443  if( delta <= zmax )
1444  {
1445  // Draw grid lines on Z axis (positive Z axis coordinates)
1446  glBegin( GL_LINES );
1447  glVertex3f( xmin, posy, delta );
1448  glVertex3f( xmax, posy, delta );
1449  glEnd();
1450  }
1451 
1452  if( delta <= -zmin && ( ii != 0 ) )
1453  {
1454  // Draw grid lines on Z axis (negative Z axis coordinates)
1455  glBegin( GL_LINES );
1456  glVertex3f( xmin, posy, -delta );
1457  glVertex3f( xmax, posy, -delta );
1458  glEnd();
1459  }
1460 
1461  if( ( delta > zmax ) && ( delta > -zmin ) )
1462  break;
1463  }
1464 
1465  glDisable( GL_BLEND );
1466 
1467  glEndList();
1468 }
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
double GetOrientation() const
Definition: class_module.h:211
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)
The CLAYER_TRIANGLES class stores arrays of triangles to be used to create display lists.
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:288
Implementation of conversion functions that require both schematic and board internal units.
SFVEC3D m_SolderPasteColor
in realistic mode: solder paste color
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer
void render_3D_models(bool aRenderTopOrBot, bool aRenderTransparentOnly)
render_3D_models
glm::vec4 SFVEC4F
Definition: xv3d_types.h:49
SFVEC3D m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
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
void init_lights(void)
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.
SFVEC3D m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
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)
SFVEC3D m_BgColorTop
background top color
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
PCB_LAYER_ID
A quick note on layer IDs:
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:266
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.
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:65
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.
SFVEC3F GetLayerColor(PCB_LAYER_ID aLayerId) const
GetLayerColor - get the technical color of a layer.
SFVEC3D m_BgColorBot
background bottom color
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:81
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
SFVEC3D m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_outer_with_npth
SFVEC3D m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
std::list< MODULE_3D_SETTINGS > & Models()
Definition: class_module.h:201
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
SFVEC3D m_BoardBodyColor
in realistic mode: FR4 board color
void SetItIsTransparent(bool aSetTransparent)
bool Redraw(bool aIsMoving, REPORTER *aStatusReporter, REPORTER *aWarningReporter) override
Redraw - Ask to redraw the view.
SFVEC3D m_CopperColor
in realistic mode: copper color
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
Defines math related functions.
wxPoint GetBoardPosBIU() const noexcept
GetBoardPosBIU - Get the board size.
wxPoint GetPosition() const override
Definition: class_module.h:206
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)
SFVEC3F GetColor(COLOR4D aColor) const
GetColor.
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.
SFVEC3F get_layer_color(PCB_LAYER_ID aLayerID)
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 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.