KiCad PCB EDA Suite
c3d_render_createscene.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
31 #include "c3d_render_raytracing.h"
32 #include "shapes3D/cplane.h"
33 #include "shapes3D/croundseg.h"
34 #include "shapes3D/clayeritem.h"
35 #include "shapes3D/ccylinder.h"
36 #include "shapes3D/ctriangle.h"
38 #include "shapes2D/cring2d.h"
39 #include "shapes2D/cpolygon2d.h"
41 #include "accelerators/cbvh_pbrt.h"
42 #include "3d_fastmath.h"
43 #include "3d_math.h"
44 
45 #include <class_board.h>
46 #include <class_module.h>
47 
48 #include <base_units.h>
49 #include <profile.h> // To use GetRunningMicroSecs or another profiling utility
50 
54 #define UNITS3D_TO_UNITSPCB (IU_PER_MM)
55 
57 {
58  double mmTo3Dunits = IU_PER_MM * m_boardAdapter.BiuTo3Dunits();
59 
61  {
62  m_board_normal_perturbator = CBOARDNORMAL( 0.5f * mmTo3Dunits );
63 
64  m_copper_normal_perturbator = CCOPPERNORMAL( 4.0f * mmTo3Dunits,
66 
68 
69  m_plastic_normal_perturbator = CPLASTICNORMAL( 0.15f * mmTo3Dunits );
70 
72 
74  }
75 
76  // http://devernay.free.fr/cours/opengl/materials.html
77 
78  // Copper
81  (SFVEC3F)(0.18f), // ambient
82  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
83  glm::clamp( ((SFVEC3F)(1.0f) -
85  SFVEC3F( 0.0f ),
86  SFVEC3F( 0.35f ) ), // specular
87  0.4f * 128.0f, // shiness
88  0.0f, // transparency
89  0.0f );
90 
92  m_materials.m_Copper.SetNormalPerturbator( &m_copper_normal_perturbator );
93 
97  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
100  0.10f * 128.0f, // shiness
101  0.0f, // transparency
102  0.0f );
103 
104  m_materials.m_SilkS = CBLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 0.11f ) ), // ambient
105  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
106  glm::clamp(
107  ( ( SFVEC3F )( 1.0f )
109  SFVEC3F( 0.0f ),
110  SFVEC3F( 0.10f ) ), // specular
111  0.078125f * 128.0f, // shiness
112  0.0f, // transparency
113  0.0f );
114 
115  const float solderMaskTop_gray =
118  / 3.0f;
119 
120  const float solderMaskTop_transparency = solderMaskTop_gray * 0.40f + 0.005f;
121 
122  m_materials.m_SolderMask = CBLINN_PHONG_MATERIAL(
124  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
125  glm::clamp(
126  ( ( SFVEC3F )( 1.0f )
128  SFVEC3F( 0.0f ),
129  SFVEC3F( solderMaskTop_gray * 2.0f ) ), // specular
130  0.85f * 128.0f, // shiness
131  solderMaskTop_transparency, // transparency
132  0.16f ); // reflection
133 
134  const float solderMaskBot_gray =
137  / 3.0f;
138 
139  const float solderMaskBot_transparency = solderMaskBot_gray * 0.40f + 0.005f;
140 
141  m_materials.m_SolderMask = CBLINN_PHONG_MATERIAL(
143  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
144  glm::clamp(
145  ( ( SFVEC3F )( 1.0f )
147  SFVEC3F( 0.0f ),
148  SFVEC3F( solderMaskBot_gray * 2.0f ) ), // specular
149  0.85f * 128.0f, // shiness
150  solderMaskBot_transparency, // transparency
151  0.16f );
152 
153  m_materials.m_SolderMask.SetCastShadows( true );
154  m_materials.m_SolderMask.SetNrRefractionsSamples( 1 );
155  m_materials.m_SolderMask.SetNrReflectionsSamples( 2 );
156 
158  m_materials.m_SolderMask.SetNormalPerturbator( &m_solder_mask_normal_perturbator );
159 
160  m_materials.m_EpoxyBoard = CBLINN_PHONG_MATERIAL(
161  ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f,
162  14.0f / 255.0f,
163  10.0f / 255.0f ) ), // ambient
164  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
165  ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f,
166  8.0f / 255.0f,
167  10.0f / 255.0f ) ), // specular
168  0.1f * 128.0f, // shiness
169  0.10f, // transparency
170  0.0f ); // reflection
171 
172  m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
173  m_materials.m_EpoxyBoard.SetNrRefractionsSamples( 3 );
174 
176  m_materials.m_EpoxyBoard.SetNormalPerturbator( &m_board_normal_perturbator );
177 
179  //SFVEC3F bgBot = (SFVEC3F)m_boardAdapter.m_BgColorBot;
180 
182  bgTop * 0.125f, // ambient
183  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
184  (SFVEC3F(1.0f) - bgTop) / 3.0f, // specular
185  0.10f * 128.0f, // shiness
186  0.0f, // transparency
187  0.50f ); // reflection
188  m_materials.m_Floor.SetCastShadows( false );
189 }
190 
191 
192 
202  const COBJECT2D* aObject2D, float aZMin, float aZMax, const CMATERIAL* aMaterial,
203  const SFVEC3F& aObjColor )
204 {
205  switch( aObject2D->GetObjectType() )
206  {
208  {
210 #if 1
211  CXYPLANE* objPtr;
212  objPtr = new CXYPLANE( CBBOX(
213  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
214  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
215  objPtr->SetMaterial( aMaterial );
216  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
217  aDstContainer.Add( objPtr );
218 
219  objPtr = new CXYPLANE( CBBOX(
220  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
221  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
222  objPtr->SetMaterial( aMaterial );
223  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
224  aDstContainer.Add( objPtr );
225 #else
226  objPtr = new CDUMMYBLOCK( CBBOX(
227  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
228  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
229  objPtr->SetMaterial( aMaterial );
230  aDstContainer.Add( objPtr );
231 #endif
232  }
233  break;
234 
236  {
238 
239  const CROUNDSEGMENT2D* aRoundSeg2D = static_cast<const CROUNDSEGMENT2D*>( aObject2D );
240  CROUNDSEG* objPtr = new CROUNDSEG( *aRoundSeg2D, aZMin, aZMax );
241  objPtr->SetMaterial( aMaterial );
242  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
243  aDstContainer.Add( objPtr );
244  }
245  break;
246 
247 
248  default:
249  {
250  CLAYERITEM* objPtr = new CLAYERITEM( aObject2D, aZMin, aZMax );
251  objPtr->SetMaterial( aMaterial );
252  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
253  aDstContainer.Add( objPtr );
254  }
255  break;
256  }
257 }
258 
259 
260 void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
261 {
262  m_reloadRequested = false;
263 
264  m_model_materials.clear();
265 
268 
269 #ifdef PRINT_STATISTICS_3D_VIEWER
270  printf("InitSettings...\n");
271 #endif
272 
273  unsigned stats_startReloadTime = GetRunningMicroSecs();
274 
275  m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
276 
277 #ifdef PRINT_STATISTICS_3D_VIEWER
278  unsigned stats_endReloadTime = GetRunningMicroSecs();
279  unsigned stats_startConvertTime = GetRunningMicroSecs();
280  #endif
281 
283  m_camera.SetBoardLookAtPos( camera_pos );
284 
287 
288  setupMaterials();
289 
290  // Create and add the outline board
291  // /////////////////////////////////////////////////////////////////////////
292 
293 #ifdef PRINT_STATISTICS_3D_VIEWER
294  printf("Create outline board...\n");
295 #endif
296 
298 
300 
301  const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
302 
303  if( outlineCount > 0 )
304  {
305  float divFactor = 0.0f;
306 
309  else
311  divFactor = m_boardAdapter.GetStats_Med_Hole_Diameter3DU() * 8.0f;
312 
313  SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly();
314  boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
315 
316  for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ )
317  {
319  boardPolyCopy,
322  divFactor,
323  *dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ),
324  iOutlinePolyIdx );
325  }
326 
328  {
329  const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList();
330 
331  for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin();
332  object2d_iterator != listObjects.end();
333  ++object2d_iterator )
334  {
335  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*object2d_iterator);
336 
337  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
338 
339  // Check if there are any THT that intersects this outline object part
340  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
341  {
342 
343  CONST_LIST_OBJECT2D intersectionList;
345  object2d_A->GetBBox(),
346  intersectionList );
347 
348  if( !intersectionList.empty() )
349  {
350  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
351  hole != intersectionList.end();
352  ++hole )
353  {
354  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
355 
356  if( object2d_A->Intersects( hole2d->GetBBox() ) )
357  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
358  object2d_B->push_back( hole2d );
359  }
360  }
361  }
362 
363  if( object2d_B->empty() )
364  {
365  delete object2d_B;
366  object2d_B = CSGITEM_EMPTY;
367  }
368 
369  if( object2d_B == CSGITEM_EMPTY )
370  {
371  #if 0
375  &m_materials.m_EpoxyBoard,
376  g_epoxyColor );
377  #else
378  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
381 
382  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
384  m_object_container.Add( objPtr );
385  #endif
386  }
387  else
388  {
389  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D(
390  object2d_A,
391  object2d_B,
392  CSGITEM_FULL,
393  (const BOARD_ITEM &)*m_boardAdapter.GetBoard() );
394 
395  m_containerWithObjectsToDelete.Add( itemCSG2d );
396 
397  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
400 
401  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
403  m_object_container.Add( objPtr );
404  }
405  }
406 
407  // Add cylinders of the board body to container
408  // Note: This is actually a workarround for the holes in the board.
409  // The issue is because if a hole is in a border of a divided polygon ( ex
410  // a polygon or dummyblock) it will cut also the render of the hole.
411  // So this will add a full hole.
412  // In fact, that is not need if the hole have copper.
413  // /////////////////////////////////////////////////////////////////////////
414  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
415  {
417 
418  for( LIST_OBJECT2D::const_iterator hole = holeList.begin();
419  hole != holeList.end();
420  ++hole )
421  {
422  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
423 
424  switch( hole2d->GetObjectType() )
425  {
427  {
428  const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
429 
430  CVCYLINDER *objPtr = new CVCYLINDER(
431  hole2d->GetCentroid(),
434  radius );
435 
436  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
438 
439  m_object_container.Add( objPtr );
440  }
441  break;
442 
443  default:
444  break;
445  }
446  }
447  }
448  }
449  }
450 
451 
452  // Add layers maps (except B_Mask and F_Mask)
453  // /////////////////////////////////////////////////////////////////////////
454 
455 #ifdef PRINT_STATISTICS_3D_VIEWER
456  printf("Add layers maps...\n");
457 #endif
458 
459  for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin();
460  ii != m_boardAdapter.GetMapLayers().end();
461  ++ii )
462  {
463  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
464 
465  // Mask kayers are not processed here because they are a special case
466  if( (layer_id == B_Mask) || (layer_id == F_Mask) )
467  continue;
468 
469  CMATERIAL *materialLayer = &m_materials.m_SilkS;
470  SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
471 
472  switch( layer_id )
473  {
474  case B_Adhes:
475  case F_Adhes:
476  break;
477 
478  case B_Paste:
479  case F_Paste:
480  materialLayer = &m_materials.m_Paste;
481 
483  layerColor = m_boardAdapter.m_SolderPasteColor;
484  else
485  layerColor = m_boardAdapter.GetLayerColor( layer_id );
486  break;
487 
488  case B_SilkS:
489  materialLayer = &m_materials.m_SilkS;
490 
493  else
494  layerColor = m_boardAdapter.GetLayerColor( layer_id );
495  break;
496  case F_SilkS:
497  materialLayer = &m_materials.m_SilkS;
498 
501  else
502  layerColor = m_boardAdapter.GetLayerColor( layer_id );
503  break;
504 
505  case Dwgs_User:
506  case Cmts_User:
507  case Eco1_User:
508  case Eco2_User:
509  case Edge_Cuts:
510  case Margin:
511  break;
512 
513  case B_CrtYd:
514  case F_CrtYd:
515  break;
516 
517  case B_Fab:
518  case F_Fab:
519  break;
520 
521  default:
522  materialLayer = &m_materials.m_Copper;
523 
525  layerColor = m_boardAdapter.m_CopperColor;
526  else
527  layerColor = m_boardAdapter.GetLayerColor( layer_id );
528  break;
529  }
530 
531  const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
532  const LIST_OBJECT2D &listObject2d = container2d->GetList();
533 
534  for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
535  itemOnLayer != listObject2d.end();
536  ++itemOnLayer )
537  {
538  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
539 
540  // not yet used / implemented (can be used in future to clip the objects in the board borders
541  COBJECT2D *object2d_C = CSGITEM_FULL;
542 
543  std::vector<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY;
544 
545  object2d_B = new std::vector<const COBJECT2D*>();
546 
547  // Subtract holes but not in SolderPaste
548  // (can be added as an option in future)
549  if( !( ( layer_id == B_Paste ) || ( layer_id == F_Paste ) ) )
550  {
551  // Check if there are any layerhole that intersects this object
552  // Eg: a segment is cutted by a via hole or THT hole.
553  // /////////////////////////////////////////////////////////////
554  const MAP_CONTAINER_2D &layerHolesMap = m_boardAdapter.GetMapLayersHoles();
555 
556  if( layerHolesMap.find(layer_id) != layerHolesMap.end() )
557  {
558  MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(layer_id);
559 
560  const CBVHCONTAINER2D *containerLayerHoles2d =
561  static_cast<const CBVHCONTAINER2D *>(ii_hole->second);
562 
563  CONST_LIST_OBJECT2D intersectionList;
564  containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(),
565  intersectionList );
566 
567  if( !intersectionList.empty() )
568  {
569  for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer =
570  intersectionList.begin();
571  holeOnLayer != intersectionList.end();
572  ++holeOnLayer )
573  {
574  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*holeOnLayer);
575 
576  //if( object2d_A->Intersects( hole2d->GetBBox() ) )
577  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
578  object2d_B->push_back( hole2d );
579  }
580  }
581  }
582 
583  // Check if there are any THT that intersects this object
584  // /////////////////////////////////////////////////////////////
585  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
586  {
587  CONST_LIST_OBJECT2D intersectionList;
588 
590  object2d_A->GetBBox(),
591  intersectionList );
592 
593  if( !intersectionList.empty() )
594  {
595  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
596  hole != intersectionList.end();
597  ++hole )
598  {
599  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
600 
601  //if( object2d_A->Intersects( hole2d->GetBBox() ) )
602  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
603  object2d_B->push_back( hole2d );
604  }
605  }
606  }
607  }
608 
609 
610  const MAP_CONTAINER_2D& mapLayers = m_boardAdapter.GetMapLayers();
611 
613  ( ( ( layer_id == B_SilkS ) &&
614  ( mapLayers.find( B_Mask ) != mapLayers.end() ) ) ||
615  ( ( layer_id == F_SilkS ) &&
616  ( mapLayers.find( F_Mask ) != mapLayers.end() ) ) ) )
617  {
618  const PCB_LAYER_ID layerMask_id = ( layer_id == B_SilkS ) ? B_Mask : F_Mask;
619 
620  const CBVHCONTAINER2D *containerMaskLayer2d =
621  static_cast<const CBVHCONTAINER2D*>( mapLayers.at( layerMask_id ) );
622 
623  CONST_LIST_OBJECT2D intersectionList;
624 
625  if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
626  containerMaskLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(),
627  intersectionList );
628 
629  if( !intersectionList.empty() )
630  {
631  for( CONST_LIST_OBJECT2D::const_iterator objOnLayer =
632  intersectionList.begin();
633  objOnLayer != intersectionList.end();
634  ++objOnLayer )
635  {
636  const COBJECT2D* obj2d = static_cast<const COBJECT2D*>( *objOnLayer );
637 
638  object2d_B->push_back( obj2d );
639  }
640  }
641  }
642 
643  if( object2d_B->empty() )
644  {
645  delete object2d_B;
646  object2d_B = CSGITEM_EMPTY;
647  }
648 
649  if( (object2d_B == CSGITEM_EMPTY) &&
650  (object2d_C == CSGITEM_FULL) )
651  {
652 #if 0
654  object2d_A,
657  materialLayer,
658  layerColor );
659 #else
660  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
662  m_boardAdapter.GetLayerTopZpos3DU( layer_id ) );
663  objPtr->SetMaterial( materialLayer );
664  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
665  m_object_container.Add( objPtr );
666 #endif
667  }
668  else
669  {
670 #if 1
671  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
672  object2d_B,
673  object2d_C,
674  object2d_A->GetBoardItem() );
675  m_containerWithObjectsToDelete.Add( itemCSG2d );
676 
677  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
679  m_boardAdapter.GetLayerTopZpos3DU( layer_id ) );
680 
681  objPtr->SetMaterial( materialLayer );
682  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
683 
684  m_object_container.Add( objPtr );
685 #endif
686  }
687  }
688  }// for each layer on map
689 
690 
691 
692  // Add Mask layer
693  // Solder mask layers are "negative" layers so the elements that we have
694  // (in the container) should remove the board outline.
695  // We will check for all objects in the outline if it intersects any object
696  // in the layer container and also any hole.
697  // /////////////////////////////////////////////////////////////////////////
699  (m_outlineBoard2dObjects->GetList().size() >= 1) )
700  {
701  const CMATERIAL *materialLayer = &m_materials.m_SolderMask;
702 
703  for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin();
704  ii != m_boardAdapter.GetMapLayers().end();
705  ++ii )
706  {
707  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
708 
709  const CBVHCONTAINER2D *containerLayer2d =
710  static_cast<const CBVHCONTAINER2D *>(ii->second);
711 
712  // Only get the Solder mask layers
713  if( !((layer_id == B_Mask) || (layer_id == F_Mask)) )
714  continue;
715 
716  SFVEC3F layerColor;
718  {
719  if( layer_id == B_Mask )
721  else
723  }
724  else
725  layerColor = m_boardAdapter.GetLayerColor( layer_id );
726 
727  const float zLayerMin = m_boardAdapter.GetLayerBottomZpos3DU( layer_id );
728  const float zLayerMax = m_boardAdapter.GetLayerTopZpos3DU( layer_id );
729 
730  // Get the outline board objects
731  const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList();
732 
733  for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin();
734  object2d_iterator != listObjects.end();
735  ++object2d_iterator )
736  {
737  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*object2d_iterator);
738 
739  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
740 
741  // Check if there are any THT that intersects this outline object part
742  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
743  {
744 
745  CONST_LIST_OBJECT2D intersectionList;
746 
748  object2d_A->GetBBox(),
749  intersectionList );
750 
751  if( !intersectionList.empty() )
752  {
753  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
754  hole != intersectionList.end();
755  ++hole )
756  {
757  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
758 
759  if( object2d_A->Intersects( hole2d->GetBBox() ) )
760  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
761  object2d_B->push_back( hole2d );
762  }
763  }
764  }
765 
766  // Check if there are any objects in the layer to subtract with the
767  // corrent object
768  if( !containerLayer2d->GetList().empty() )
769  {
770  CONST_LIST_OBJECT2D intersectionList;
771 
772  containerLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(),
773  intersectionList );
774 
775  if( !intersectionList.empty() )
776  {
777  for( CONST_LIST_OBJECT2D::const_iterator obj = intersectionList.begin();
778  obj != intersectionList.end();
779  ++obj )
780  {
781  const COBJECT2D *obj2d = static_cast<const COBJECT2D *>(*obj);
782 
783  //if( object2d_A->Intersects( obj2d->GetBBox() ) )
784  //if( object2d_A->GetBBox().Intersects( obj2d->GetBBox() ) )
785  object2d_B->push_back( obj2d );
786  }
787  }
788  }
789 
790  if( object2d_B->empty() )
791  {
792  delete object2d_B;
793  object2d_B = CSGITEM_EMPTY;
794  }
795 
796  if( object2d_B == CSGITEM_EMPTY )
797  {
798  #if 0
800  object2d_A,
801  zLayerMin,
802  zLayerMax,
803  materialLayer,
804  layerColor );
805  #else
806  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
807  zLayerMin,
808  zLayerMax );
809 
810  objPtr->SetMaterial( materialLayer );
811  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
812 
813  m_object_container.Add( objPtr );
814  #endif
815  }
816  else
817  {
818  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
819  object2d_B,
820  CSGITEM_FULL,
821  object2d_A->GetBoardItem() );
822 
823  m_containerWithObjectsToDelete.Add( itemCSG2d );
824 
825  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
826  zLayerMin,
827  zLayerMax );
828  objPtr->SetMaterial( materialLayer );
829  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
830 
831  m_object_container.Add( objPtr );
832  }
833  }
834  }
835  }
836 
838 
839 #ifdef PRINT_STATISTICS_3D_VIEWER
840  unsigned stats_endConvertTime = GetRunningMicroSecs();
841  unsigned stats_startLoad3DmodelsTime = stats_endConvertTime;
842 #endif
843 
844 
845  load_3D_models();
846 
847 
848 #ifdef PRINT_STATISTICS_3D_VIEWER
849  unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs();
850 #endif
851 
852  // Add floor
853  // /////////////////////////////////////////////////////////////////////////
855  {
856  CBBOX boardBBox = m_boardAdapter.GetBBox3DU();
857 
858  if( boardBBox.IsInitialized() )
859  {
860  boardBBox.Scale( 3.0f );
861 
862  if( m_object_container.GetList().size() > 0 )
863  {
864  CBBOX containerBBox = m_object_container.GetBBox();
865 
866  containerBBox.Scale( 1.3f );
867 
868  const SFVEC3F centerBBox = containerBBox.GetCenter();
869 
870  // Floor triangles
871  const float minZ = glm::min( containerBBox.Min().z,
872  boardBBox.Min().z );
873 
874  const SFVEC3F v1 = SFVEC3F( -RANGE_SCALE_3D * 4.0f,
875  -RANGE_SCALE_3D * 4.0f,
876  minZ ) +
877  SFVEC3F( centerBBox.x,
878  centerBBox.y,
879  0.0f );
880 
881  const SFVEC3F v3 = SFVEC3F( +RANGE_SCALE_3D * 4.0f,
882  +RANGE_SCALE_3D * 4.0f,
883  minZ ) +
884  SFVEC3F( centerBBox.x,
885  centerBBox.y,
886  0.0f );
887 
888  const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
889  const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
890 
891  SFVEC3F backgroundColor =
892  ConvertSRGBToLinear( static_cast<SFVEC3F>( m_boardAdapter.m_BgColorTop ) );
893 
894  CTRIANGLE *newTriangle1 = new CTRIANGLE( v1, v2, v3 );
895  CTRIANGLE *newTriangle2 = new CTRIANGLE( v3, v4, v1 );
896 
897  m_object_container.Add( newTriangle1 );
898  m_object_container.Add( newTriangle2 );
899 
900  newTriangle1->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
901  newTriangle2->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
902 
903  newTriangle1->SetColor( backgroundColor );
904  newTriangle2->SetColor( backgroundColor );
905 
906  // Ceiling triangles
907  const float maxZ = glm::max( containerBBox.Max().z,
908  boardBBox.Max().z );
909 
910  const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
911  const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
912  const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
913  const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
914 
915  CTRIANGLE *newTriangle3 = new CTRIANGLE( v7, v6, v5 );
916  CTRIANGLE *newTriangle4 = new CTRIANGLE( v5, v8, v7 );
917 
918  m_object_container.Add( newTriangle3 );
919  m_object_container.Add( newTriangle4 );
920 
921  newTriangle3->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
922  newTriangle4->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
923 
924  newTriangle3->SetColor( backgroundColor );
925  newTriangle4->SetColor( backgroundColor );
926  }
927  }
928  }
929 
930 
931  // Init initial lights
932  // /////////////////////////////////////////////////////////////////////////
933  m_lights.Clear();
934 
935  // This will work as the front camera light.
936  const float light_camera_intensity = 0.20f;
937  const float light_top_bottom = 0.25f;
938  const float light_directional_intensity = ( 1.0f - ( light_camera_intensity +
939  light_top_bottom * 0.5f ) ) / 4.0f;
940 
941  m_camera_light = new CDIRECTIONALLIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ),
942  SFVEC3F( light_camera_intensity ) );
943  m_camera_light->SetCastShadows( false );
945 
946  // Option 1 - using Point Lights
947 
948  const SFVEC3F &boarCenter = m_boardAdapter.GetBBox3DU().GetCenter();
949 
950  m_lights.Add( new CPOINTLIGHT( SFVEC3F( boarCenter.x, boarCenter.y, +RANGE_SCALE_3D * 2.0f ),
951  SFVEC3F( light_top_bottom ) ) );
952 
953  m_lights.Add( new CPOINTLIGHT( SFVEC3F( boarCenter.x, boarCenter.y, -RANGE_SCALE_3D * 2.0f ),
954  SFVEC3F( light_top_bottom ) ) );
955 
956 
957  // http://www.flashandmath.com/mathlets/multicalc/coords/shilmay23fin.html
958 
959  // Option 2 - Top/Bottom direction lights
960  /*
961  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 0.03f,
962  glm::pi<float>() * 0.25f ),
963  SFVEC3F( light_top_bottom ) ) );
964 
965  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 0.97f,
966  glm::pi<float>() * 1.25f ),
967  SFVEC3F( light_top_bottom ) ) );
968  */
969 
970  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 1.0f / 8.0f,
971  glm::pi<float>() * 1 / 4.0f ),
972  SFVEC3F( light_directional_intensity ) ) );
973  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 1.0f / 8.0f,
974  glm::pi<float>() * 3 / 4.0f ),
975  SFVEC3F( light_directional_intensity ) ) );
976  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 1.0f / 8.0f,
977  glm::pi<float>() * 5 / 4.0f ),
978  SFVEC3F( light_directional_intensity ) ) );
979  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 1.0f / 8.0f,
980  glm::pi<float>() * 7 / 4.0f ),
981  SFVEC3F( light_directional_intensity ) ) );
982 
983 
984  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 7.0f / 8.0f,
985  glm::pi<float>() * 1 / 4.0f ),
986  SFVEC3F( light_directional_intensity ) ) );
987  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 7.0f / 8.0f,
988  glm::pi<float>() * 3 / 4.0f ),
989  SFVEC3F( light_directional_intensity ) ) );
990  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 7.0f / 8.0f,
991  glm::pi<float>() * 5 / 4.0f ),
992  SFVEC3F( light_directional_intensity ) ) );
993  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * 7.0f / 8.0f,
994  glm::pi<float>() * 7 / 4.0f ),
995  SFVEC3F( light_directional_intensity ) ) );
996 
997 
998  // Create an accelerator
999  // /////////////////////////////////////////////////////////////////////////
1000 
1001 #ifdef PRINT_STATISTICS_3D_VIEWER
1002  unsigned stats_startAcceleratorTime = GetRunningMicroSecs();
1003 #endif
1004 
1005  if( m_accelerator )
1006  {
1007  delete m_accelerator;
1008  }
1009  m_accelerator = 0;
1010 
1012 
1013 #ifdef PRINT_STATISTICS_3D_VIEWER
1014  unsigned stats_endAcceleratorTime = GetRunningMicroSecs();
1015 #endif
1016 
1017 #ifdef PRINT_STATISTICS_3D_VIEWER
1018  printf( "C3D_RENDER_RAYTRACING::reload times:\n" );
1019  printf( " Reload board: %.3f ms\n", (float)( stats_endReloadTime -
1020  stats_startReloadTime ) /
1021 
1022  1000.0f );
1023  printf( " Convert to 3D objects: %.3f ms\n", (float)( stats_endConvertTime -
1024  stats_startConvertTime ) /
1025  1000.0f );
1026  printf( " Accelerator construction: %.3f ms\n", (float)( stats_endAcceleratorTime -
1027  stats_startAcceleratorTime ) /
1028  1000.0f );
1029  printf( " Load and add 3D models: %.3f ms\n", (float)( stats_endLoad3DmodelsTime -
1030  stats_startLoad3DmodelsTime ) /
1031  1000.0f );
1032  printf( "Optimizations\n" );
1033 
1034  printf( " m_stats_converted_dummy_to_plane: %u\n",
1036 
1037  printf( " m_stats_converted_roundsegment2d_to_roundsegment: %u\n",
1039 
1042 #endif
1043 
1044  if( aStatusReporter )
1045  {
1046  // Calculation time in seconds
1047  const double calculation_time = (double)( GetRunningMicroSecs() -
1048  stats_startReloadTime ) / 1e6;
1049 
1050  aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
1051  }
1052 }
1053 
1054 
1055 
1056 // Based on draw3DViaHole from
1057 // 3d_draw_helper_functions.cpp
1059 {
1060  PCB_LAYER_ID top_layer, bottom_layer;
1061  int radiusBUI = (aVia->GetDrillValue() / 2);
1062 
1063  aVia->LayerPair( &top_layer, &bottom_layer );
1064 
1065  float topZ = m_boardAdapter.GetLayerBottomZpos3DU( top_layer ) +
1067 
1068  float botZ = m_boardAdapter.GetLayerBottomZpos3DU( bottom_layer ) -
1070 
1071  const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3Dunits(),
1072  -aVia->GetStart().y * m_boardAdapter.BiuTo3Dunits() );
1073 
1074  CRING2D *ring = new CRING2D( center,
1075  radiusBUI * m_boardAdapter.BiuTo3Dunits(),
1076  ( radiusBUI + m_boardAdapter.GetCopperThicknessBIU() ) *
1078  *aVia );
1079 
1081 
1082 
1083  CLAYERITEM *objPtr = new CLAYERITEM( ring, topZ, botZ );
1084 
1085  objPtr->SetMaterial( &m_materials.m_Copper );
1086 
1089  else
1090  objPtr->SetColor( ConvertSRGBToLinear(
1091  m_boardAdapter.GetItemColor( LAYER_VIAS + static_cast<int>( aVia->GetViaType() ) ) ) );
1092 
1093  m_object_container.Add( objPtr );
1094 }
1095 
1096 
1097 // Based on draw3DPadHole from
1098 // 3d_draw_helper_functions.cpp
1100 {
1101  const COBJECT2D *object2d_A = NULL;
1102 
1103  SFVEC3F objColor;
1104 
1106  objColor = (SFVEC3F)m_boardAdapter.m_CopperColor;
1107  else
1109 
1110  const wxSize drillsize = aPad->GetDrillSize();
1111  const bool hasHole = drillsize.x && drillsize.y;
1112 
1113  if( !hasHole )
1114  return;
1115 
1116  const float topZ = m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) +
1118 
1119  const float botZ = m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) -
1121 
1122  if( drillsize.x == drillsize.y ) // usual round hole
1123  {
1124  SFVEC2F center = SFVEC2F( aPad->GetPosition().x * m_boardAdapter.BiuTo3Dunits(),
1125  -aPad->GetPosition().y * m_boardAdapter.BiuTo3Dunits() );
1126 
1127  CRING2D *ring = new CRING2D( center,
1128  ( drillsize.x / 2 ) * m_boardAdapter.BiuTo3Dunits(),
1129  (( drillsize.x / 2 ) +
1132  *aPad );
1133 
1135 
1136  object2d_A = ring;
1137  }
1138  else // Oblong hole
1139  {
1140  wxPoint ends_offset;
1141  int width;
1142 
1143  if( drillsize.x > drillsize.y ) // Horizontal oval
1144  {
1145  ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1146  width = drillsize.y;
1147  }
1148  else // Vertical oval
1149  {
1150  ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1151  width = drillsize.x;
1152  }
1153 
1154  RotatePoint( &ends_offset, aPad->GetOrientation() );
1155 
1156  wxPoint start = aPad->GetPosition() + ends_offset;
1157  wxPoint end = aPad->GetPosition() - ends_offset;
1158 
1159  CROUNDSEGMENT2D *innerSeg = new CROUNDSEGMENT2D(
1160  SFVEC2F( start.x * m_boardAdapter.BiuTo3Dunits(),
1161  -start.y * m_boardAdapter.BiuTo3Dunits() ),
1163  -end.y * m_boardAdapter.BiuTo3Dunits() ),
1164  width * m_boardAdapter.BiuTo3Dunits(),
1165  *aPad );
1166 
1167  CROUNDSEGMENT2D *outerSeg = new CROUNDSEGMENT2D(
1168  SFVEC2F( start.x * m_boardAdapter.BiuTo3Dunits(),
1169  -start.y * m_boardAdapter.BiuTo3Dunits() ),
1171  -end.y * m_boardAdapter.BiuTo3Dunits() ),
1172  ( width + m_boardAdapter.GetCopperThicknessBIU() * 2 ) *
1174  *aPad );
1175 
1176  // NOTE: the round segment width is the "diameter", so we double the thickness
1177 
1178  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
1179  object2d_B->push_back( innerSeg );
1180 
1181  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( outerSeg,
1182  object2d_B,
1183  CSGITEM_FULL,
1184  *aPad );
1185 
1186  m_containerWithObjectsToDelete.Add( itemCSG2d );
1187  m_containerWithObjectsToDelete.Add( innerSeg );
1188  m_containerWithObjectsToDelete.Add( outerSeg );
1189 
1190  object2d_A = itemCSG2d;
1191  }
1192 
1193 
1194  if( object2d_A )
1195  {
1196  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
1197 
1198  // Check if there are any other THT that intersects this hole
1199  // It will use the non inflated holes
1200  if( !m_boardAdapter.GetThroughHole_Inner().GetList().empty() )
1201  {
1202 
1203  CONST_LIST_OBJECT2D intersectionList;
1205  intersectionList );
1206 
1207  if( !intersectionList.empty() )
1208  {
1209  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
1210  hole != intersectionList.end();
1211  ++hole )
1212  {
1213  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
1214 
1215  if( object2d_A->Intersects( hole2d->GetBBox() ) )
1216  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
1217  object2d_B->push_back( hole2d );
1218  }
1219  }
1220  }
1221 
1222  if( object2d_B->empty() )
1223  {
1224  delete object2d_B;
1225  object2d_B = CSGITEM_EMPTY;
1226  }
1227 
1228  if( object2d_B == CSGITEM_EMPTY )
1229  {
1230  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, topZ, botZ );
1231 
1232  objPtr->SetMaterial( &m_materials.m_Copper );
1233  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1234  m_object_container.Add( objPtr );
1235  }
1236  else
1237  {
1238  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
1239  object2d_B,
1240  CSGITEM_FULL,
1241  (const BOARD_ITEM &)*aPad );
1242 
1243  m_containerWithObjectsToDelete.Add( itemCSG2d );
1244 
1245  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, topZ, botZ );
1246 
1247  objPtr->SetMaterial( &m_materials.m_Copper );
1248  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1249 
1250  m_object_container.Add( objPtr );
1251  }
1252  }
1253 }
1254 
1255 
1257 {
1258  // Insert plated vertical holes inside the board
1259  // /////////////////////////////////////////////////////////////////////////
1260 
1261  // Insert vias holes (vertical cylinders)
1262  for( auto track : m_boardAdapter.GetBoard()->Tracks() )
1263  {
1264  if( track->Type() == PCB_VIA_T )
1265  {
1266  const VIA *via = static_cast<const VIA*>(track);
1267  insert3DViaHole( via );
1268  }
1269  }
1270 
1271  // Insert pads holes (vertical cylinders)
1272  for( auto module : m_boardAdapter.GetBoard()->Modules() )
1273  {
1274  for( auto pad : module->Pads() )
1275  if( pad->GetAttribute () != PAD_ATTRIB_HOLE_NOT_PLATED )
1276  {
1277  insert3DPadHole( pad );
1278  }
1279  }
1280 }
1281 
1282 
1284 {
1285  // Go for all modules
1286  for( auto module : m_boardAdapter.GetBoard()->Modules() )
1287  {
1288  if((!module->Models().empty() ) &&
1289  m_boardAdapter.ShouldModuleBeDisplayed((MODULE_ATTR_T)module->GetAttributes() ) )
1290  {
1291  double zpos = m_boardAdapter.GetModulesZcoord3DIU( module->IsFlipped() );
1292 
1293  wxPoint pos = module->GetPosition();
1294 
1295  glm::mat4 moduleMatrix = glm::mat4( 1.0f );
1296 
1297  moduleMatrix = glm::translate( moduleMatrix,
1299  -pos.y * m_boardAdapter.BiuTo3Dunits(),
1300  zpos ) );
1301 
1302  if( module->GetOrientation() )
1303  {
1304  moduleMatrix = glm::rotate( moduleMatrix,
1305  ( (float)(module->GetOrientation() / 10.0f) / 180.0f ) *
1306  glm::pi<float>(),
1307  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1308  }
1309 
1310 
1311  if( module->IsFlipped() )
1312  {
1313  moduleMatrix = glm::rotate( moduleMatrix,
1314  glm::pi<float>(),
1315  SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1316 
1317  moduleMatrix = glm::rotate( moduleMatrix,
1318  glm::pi<float>(),
1319  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1320  }
1321 
1322  const double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3Dunits() *
1324 
1325  moduleMatrix = glm::scale( moduleMatrix,
1326  SFVEC3F( modelunit_to_3d_units_factor,
1327  modelunit_to_3d_units_factor,
1328  modelunit_to_3d_units_factor ) );
1329 
1330 
1331  // Get the list of model files for this model
1333  auto sM = module->Models().begin();
1334  auto eM = module->Models().end();
1335 
1336  while( sM != eM )
1337  {
1338  if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON ) &&
1339  ( sM->m_Show && !sM->m_Filename.empty() ) )
1340  {
1341  // get it from cache
1342  const S3DMODEL *modelPtr = cacheMgr->GetModel( sM->m_Filename );
1343 
1344  // only add it if the return is not NULL
1345  if( modelPtr )
1346  {
1347  glm::mat4 modelMatrix = moduleMatrix;
1348 
1349  modelMatrix = glm::translate( modelMatrix,
1350  SFVEC3F( sM->m_Offset.x,
1351  sM->m_Offset.y,
1352  sM->m_Offset.z ) );
1353 
1354  modelMatrix = glm::rotate( modelMatrix,
1355  (float)-( sM->m_Rotation.z / 180.0f ) *
1356  glm::pi<float>(),
1357  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1358 
1359  modelMatrix = glm::rotate( modelMatrix,
1360  (float)-( sM->m_Rotation.y / 180.0f ) *
1361  glm::pi<float>(),
1362  SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1363 
1364  modelMatrix = glm::rotate( modelMatrix,
1365  (float)-( sM->m_Rotation.x / 180.0f ) *
1366  glm::pi<float>(),
1367  SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1368 
1369  modelMatrix = glm::scale( modelMatrix,
1370  SFVEC3F( sM->m_Scale.x,
1371  sM->m_Scale.y,
1372  sM->m_Scale.z ) );
1373 
1374  add_3D_models( modelPtr, modelMatrix, (float)sM->m_Opacity );
1375  }
1376  }
1377 
1378  ++sM;
1379  }
1380  }
1381  }
1382 }
1383 
1384 
1386  const glm::mat4 &aModelMatrix,
1387  float aModuleOpacity )
1388 {
1389 
1390  // Validate a3DModel pointers
1391  wxASSERT( a3DModel != NULL );
1392 
1393  if( a3DModel == NULL )
1394  return;
1395 
1396  wxASSERT( a3DModel->m_Materials != NULL );
1397  wxASSERT( a3DModel->m_Meshes != NULL );
1398  wxASSERT( a3DModel->m_MaterialsSize > 0 );
1399  wxASSERT( a3DModel->m_MeshesSize > 0 );
1400  wxASSERT( aModuleOpacity > 0.0f );
1401  wxASSERT( aModuleOpacity <= 1.0f );
1402 
1403  if( aModuleOpacity > 1.0f )
1404  {
1405  aModuleOpacity = 1.0f;
1406  }
1407 
1408  if( (a3DModel->m_Materials != NULL) && (a3DModel->m_Meshes != NULL) &&
1409  (a3DModel->m_MaterialsSize > 0) && (a3DModel->m_MeshesSize > 0) )
1410  {
1411 
1412  MODEL_MATERIALS *materialVector;
1413 
1414  // Try find if the materials already exists in the map list
1415  if( m_model_materials.find( a3DModel ) != m_model_materials.end() )
1416  {
1417  // Found it, so get the pointer
1418  materialVector = &m_model_materials[a3DModel];
1419  }
1420  else
1421  {
1422  // Materials was not found in the map, so it will create a new for
1423  // this model.
1424 
1425  m_model_materials[a3DModel] = MODEL_MATERIALS();
1426  materialVector = &m_model_materials[a3DModel];
1427 
1428  materialVector->resize( a3DModel->m_MaterialsSize );
1429 
1430  for( unsigned int imat = 0;
1431  imat < a3DModel->m_MaterialsSize;
1432  ++imat )
1433  {
1435  {
1436  const SMATERIAL &material = a3DModel->m_Materials[imat];
1437 
1438  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1439 
1440  float reflectionFactor = 0.0f;
1441 
1442  if( (material.m_Shininess - 0.35f) > FLT_EPSILON )
1443  {
1444  reflectionFactor = glm::clamp( glm::sqrt( (material.m_Shininess - 0.35f) ) *
1445  0.40f - 0.05f,
1446  0.0f,
1447  0.5f );
1448  }
1449 
1450  CBLINN_PHONG_MATERIAL &blinnMaterial = (*materialVector)[imat];
1451 
1452  SFVEC3F ambient;
1453 
1455  {
1456  // apply a gain to the (dark) ambient colors
1457 
1458  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoKHgrMC4yMCleKDEvMi4wMCkpLTAuMzUiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjAsImVxIjoieCIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0xLjI0OTUwNTMzOTIyMzYyIiwiMS42Nzc4MzQ0MTg1NjcxODQzIiwiLTAuNDM1NTA0NjQyODEwOTMwMjYiLCIxLjM2NTkzNTIwODEzNzI1OCJdLCJzaXplIjpbNjQ5LDM5OV19XQ--
1459  // ambient = glm::max( (glm::pow((material.m_Ambient + 0.20f), SFVEC3F(1.0f / 2.00f)) - SFVEC3F(0.35f)), material.m_Ambient );
1460 
1461  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoKHgrMC4yMCleKDEvMS41OCkpLTAuMzUiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjAsImVxIjoieCIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0xLjI0OTUwNTMzOTIyMzYyIiwiMS42Nzc4MzQ0MTg1NjcxODQzIiwiLTAuNDM1NTA0NjQyODEwOTMwMjYiLCIxLjM2NTkzNTIwODEzNzI1OCJdLCJzaXplIjpbNjQ5LDM5OV19XQ--
1462  //ambient = glm::max( (glm::pow((material.m_Ambient + 0.20f), SFVEC3F(1.0f / 1.58f)) - SFVEC3F(0.35f)), material.m_Ambient );
1463 
1464  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoKHgrMC4yMCleKDEvMS41NCkpLTAuMzQiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjAsImVxIjoieCIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0yLjcyMTA5NTg0MjA1MDYwNSIsIjEuODUyODcyNTI5NDk3NTIyMyIsIi0xLjQyMTM3NjAxOTkyOTA4MDYiLCIxLjM5MzM3Mzc0NzE3NzQ2MTIiXSwic2l6ZSI6WzY0OSwzOTldfV0-
1465  ambient = ConvertSRGBToLinear(
1466  glm::pow((material.m_Ambient + 0.30f), SFVEC3F(1.0f / 1.54f)) - SFVEC3F(0.34f) );
1467  }
1468  else
1469  {
1470  ambient = ConvertSRGBToLinear( material.m_Ambient );
1471  }
1472 
1473 
1474  blinnMaterial = CBLINN_PHONG_MATERIAL(
1475  ambient,
1476  ConvertSRGBToLinear( material.m_Emissive ),
1477  ConvertSRGBToLinear( material.m_Specular ),
1478  material.m_Shininess * 180.0f,
1479  material.m_Transparency,
1480  reflectionFactor );
1481 
1483  {
1484  // Guess material type and apply a normal perturbator
1485 
1486  if( ( RGBtoGray(material.m_Diffuse) < 0.3f ) &&
1487  ( material.m_Shininess < 0.36f ) &&
1488  ( material.m_Transparency == 0.0f ) &&
1489  ( (glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f) &&
1490  (glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) < 0.15f) &&
1491  (glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) < 0.15f) ) )
1492  {
1493  // This may be a black plastic..
1494 
1495  if( material.m_Shininess < 0.26f )
1497  else
1499  }
1500  else
1501  {
1502  if( ( RGBtoGray(material.m_Diffuse) > 0.3f ) &&
1503  ( material.m_Shininess < 0.30f ) &&
1504  ( material.m_Transparency == 0.0f ) &&
1505  ( (glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f) ||
1506  (glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f) ||
1507  (glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) > 0.25f) ) )
1508  {
1509  // This may be a color plastic ...
1511  }
1512  else
1513  {
1514  if( ( RGBtoGray(material.m_Diffuse) > 0.6f ) &&
1515  ( material.m_Shininess > 0.35f ) &&
1516  ( material.m_Transparency == 0.0f ) &&
1517  ( (glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.40f) &&
1518  (glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) < 0.40f) &&
1519  (glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) < 0.40f) ) )
1520  {
1521  // This may be a brushed metal
1523  }
1524  }
1525  }
1526  }
1527  }
1528  else
1529  {
1530  (*materialVector)[imat] = CBLINN_PHONG_MATERIAL( SFVEC3F( 0.2f ),
1531  SFVEC3F( 0.0f ),
1532  SFVEC3F( 0.0f ),
1533  0.0f,
1534  0.0f,
1535  0.0f );
1536  }
1537  }
1538  }
1539 
1540  const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1541 
1542  for( unsigned int mesh_i = 0;
1543  mesh_i < a3DModel->m_MeshesSize;
1544  ++mesh_i )
1545  {
1546  const SMESH &mesh = a3DModel->m_Meshes[mesh_i];
1547 
1548  // Validate the mesh pointers
1549  wxASSERT( mesh.m_Positions != NULL );
1550  wxASSERT( mesh.m_FaceIdx != NULL );
1551  wxASSERT( mesh.m_Normals != NULL );
1552  wxASSERT( mesh.m_FaceIdxSize > 0 );
1553  wxASSERT( (mesh.m_FaceIdxSize % 3) == 0 );
1554 
1555 
1556  if( (mesh.m_Positions != NULL) &&
1557  (mesh.m_Normals != NULL) &&
1558  (mesh.m_FaceIdx != NULL) &&
1559  (mesh.m_FaceIdxSize > 0) &&
1560  (mesh.m_VertexSize > 0) &&
1561  ((mesh.m_FaceIdxSize % 3) == 0) &&
1562  (mesh.m_MaterialIdx < a3DModel->m_MaterialsSize) )
1563  {
1564  const CBLINN_PHONG_MATERIAL &blinn_material = (*materialVector)[mesh.m_MaterialIdx];
1565 
1566  const float moduleTransparency = 1.0f - ( ( 1.0f - blinn_material.GetTransparency() ) * aModuleOpacity );
1567 
1568  // Add all face triangles
1569  for( unsigned int faceIdx = 0;
1570  faceIdx < mesh.m_FaceIdxSize;
1571  faceIdx += 3 )
1572  {
1573  const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1574  const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1575  const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1576 
1577  wxASSERT( idx0 < mesh.m_VertexSize );
1578  wxASSERT( idx1 < mesh.m_VertexSize );
1579  wxASSERT( idx2 < mesh.m_VertexSize );
1580 
1581  if( ( idx0 < mesh.m_VertexSize ) &&
1582  ( idx1 < mesh.m_VertexSize ) &&
1583  ( idx2 < mesh.m_VertexSize ) )
1584  {
1585  const SFVEC3F &v0 = mesh.m_Positions[idx0];
1586  const SFVEC3F &v1 = mesh.m_Positions[idx1];
1587  const SFVEC3F &v2 = mesh.m_Positions[idx2];
1588 
1589  const SFVEC3F &n0 = mesh.m_Normals[idx0];
1590  const SFVEC3F &n1 = mesh.m_Normals[idx1];
1591  const SFVEC3F &n2 = mesh.m_Normals[idx2];
1592 
1593  // Transform vertex with the model matrix
1594  const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f) );
1595  const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f) );
1596  const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f) );
1597 
1598  const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1599  const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1600  const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1601 
1602  CTRIANGLE *newTriangle = new CTRIANGLE( vt0, vt2, vt1,
1603  nt0, nt2, nt1 );
1604 
1605  m_object_container.Add( newTriangle );
1606  newTriangle->SetMaterial( (const CMATERIAL *)&blinn_material );
1607 
1608  newTriangle->SetModelTransparency( moduleTransparency );
1609 
1610  if( mesh.m_Color == NULL )
1611  {
1612  const SFVEC3F diffuseColor =
1613  a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1614 
1616  newTriangle->SetColor( ConvertSRGBToLinear( MaterialDiffuseToColorCAD( diffuseColor ) ) );
1617  else
1618  newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1619  }
1620  else
1621  {
1623  newTriangle->SetColor( ConvertSRGBToLinear( MaterialDiffuseToColorCAD( mesh.m_Color[idx0] ) ),
1626  else
1627  newTriangle->SetColor( ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1628  ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1629  ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1630  }
1631  }
1632  }
1633  }
1634  }
1635  }
1636 }
Use a gray shading based on diffuse material.
void GetListObjectsIntersects(const CBBOX2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
GetListObjectsIntersects - Get a list of objects that intersects a bbox.
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
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.
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:147
const CBBOX & GetBBox() const
Definition: ccontainer.h:67
std::map< PCB_LAYER_ID, CBVHCONTAINER2D * > MAP_CONTAINER_2D
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:50
SFVEC3F m_Ambient
Definition: c3dmodel.h:39
const SFVEC3F & Max() const
Function Max return the maximum vertex pointer.
Definition: cbbox.h:212
Defines math related functions.
int OutlineCount() const
Returns the number of outlines in the set
CPLASTICNORMAL m_plastic_normal_perturbator
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
OBJECT2D_TYPE GetObjectType() const
Definition: cobject2d.h:125
const LIST_OBJECT & GetList() const
Definition: ccontainer.h:63
CBOARDNORMAL m_board_normal_perturbator
Directional light - a light based only on a direction vector.
Definition: clight.h:114
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
multilayer pads, usually with holes
void PrintStats()
Definition: cobject2d.cpp:65
Implementation of conversion functions that require both schematic and board internal units.
SFVEC3D m_SolderPasteColor
in realistic mode: solder paste color
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
const SFVEC2F & Min() const
Function Min return the minimun vertex pointer.
Definition: cbbox2d.h:176
A base material class that can be used to derive a material implementation.
Definition: cmaterial.h:195
const wxPoint & GetStart() const
Definition: class_track.h:118
float GetStats_Med_Hole_Diameter3DU() const noexcept
GetStats_Med_Hole_Diameter3DU - Average diameter of holes.
SFVEC3D m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
CCOPPERNORMAL m_copper_normal_perturbator
void create_3d_object_from(CCONTAINER &aDstContainer, const COBJECT2D *aObject2D, float aZMin, float aZMax, const CMATERIAL *aMaterial, const SFVEC3F &aObjColor)
Function create_3d_object_from.
const MAP_CONTAINER_2D & GetMapLayersHoles() const noexcept
GetMapLayersHoles -Get the map of container that have the holes per layer.
std::list< const COBJECT2D * > CONST_LIST_OBJECT2D
Definition: ccontainer2d.h:38
const CBBOX & GetBBox3DU() const noexcept
GetBBox3DU - Get the bbox of the pcb board.
float GetLayerTopZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerTopZpos3DU - Get the top z position.
float GetCopperThickness3DU() const noexcept
GetCopperThickness3DU - Get the current copper layer thickness.
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
InitSettings - Function to be called by the render when it need to reload the settings for the board.
void SetMaterial(const CMATERIAL *aMaterial)
Definition: cobject.h:66
A dummy block is used to fill the polygons.
Definition: cdummyblock.h:39
void insert3DViaHole(const VIA *aVia)
CPLASTICSHINENORMAL m_plastic_shine_normal_perturbator
void SetColor(SFVEC3F aObjColor)
Definition: croundseg.h:48
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
S3D_CACHE.
Definition: 3d_cache.h:54
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
void PrintStats()
Definition: cobject.cpp:64
void SetNormalPerturbator(const CPROCEDURALGENERATOR *aPerturbator)
Definition: cmaterial.h:250
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
CMETALBRUSHEDNORMAL m_brushed_metal_normal_perturbator
SFVEC3D m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
#define UNITS3D_TO_UNITSPCB
Scale convertion from 3d model units to pcb units.
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.
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
const MAP_CONTAINER_2D & GetMapLayers() const noexcept
GetMapLayers - Get the map of container that have the objects per layer.
A plane that is parallel to XY plane.
Definition: cplane.h:38
unsigned int m_stats_converted_dummy_to_plane
SFVEC3D m_BgColorTop
background top color
S3DMODEL * GetModel(const wxString &aModelFileName)
Function GetModel attempts to load the scene data for a model and to translate it into an S3D_MODEL s...
Definition: 3d_cache.cpp:654
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
#define CSGITEM_EMPTY
This class is used to make constructive solig geometry for items objects on layers.
std::vector< CBLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
SFVEC3F GetCenter() const
Function GetCenter return the center point of the bounding box.
Definition: cbbox.cpp:135
CGENERICACCELERATOR * m_accelerator
void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(const SHAPE_POLY_SET &aMainPath, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Convert_path_polygon_to_polygon_blocks_and_dummy_blocks This function will use a polygon in the forma...
Definition: cpolygon2d.cpp:404
void SetColor(const SFVEC3F &aColor)
Definition: ctriangle.cpp:156
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
const BOARD_ITEM & GetBoardItem() const
Definition: cobject2d.h:75
PCB_LAYER_ID
A quick note on layer IDs:
void SetColor(SFVEC3F aObjColor)
Definition: ccylinder.h:51
void SetColor(SFVEC3F aObjColor)
Definition: cplane.h:52
const CBVHCONTAINER2D & GetThroughHole_Outer() const noexcept
GetThroughHole_Outer - Get the inflated ThroughHole container.
float GetLayerBottomZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerBottomZpos3DU - Get the bottom z position.
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
#define NULL
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:266
int GetCopperThicknessBIU() const noexcept
GetCopperThicknessBIU - Get the current copper layer thickness.
SHAPE_POLY_SET.
Use all material properties from model file.
void SetModelTransparency(float aModelTransparency)
Definition: cobject.h:74
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: cmaterial.h:278
S3D_CACHE * Get3DCacheManager() const noexcept
Get3DCacheManager - Return the 3d cache manager pointer.
Definition: board_adapter.h:89
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
CCONTAINER2D m_containerWithObjectsToDelete
This will store the list of created objects special for RT, that will be clear in the end.
const BOARD * GetBoard() const noexcept
GetBoard - Get current board to be rendered.
void Add(CLIGHT *aLight)
Add - Add a light to the container.
Definition: clight.h:186
Point light based on: http://ogldev.atspace.co.uk/www/tutorial20/tutorial20.html.
Definition: clight.h:67
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
const CBVHCONTAINER2D & GetThroughHole_Inner() const noexcept
GetThroughHole_Inner - Get the ThroughHole container.
unsigned int m_stats_converted_roundsegment2d_to_roundsegment
float m_Shininess
Definition: c3dmodel.h:43
const SFVEC2F & Max() const
Function Max return the maximum vertex pointer.
Definition: cbbox2d.h:183
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
GetBoardPoly - Get the current polygon of the epoxy board.
#define CSGITEM_FULL
void SetColor(SFVEC3F aObjColor)
Definition: clayeritem.h:46
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
A triangle object.
Definition: ctriangle.h:42
CDIRECTIONALLIGHT * m_camera_light
void Add(COBJECT *aObject)
Definition: ccontainer.h:52
SFVEC3F GetLayerColor(PCB_LAYER_ID aLayerId) const
GetLayerColor - get the technical color of a layer.
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
static COBJECT2D_STATS & Instance()
Definition: cobject2d.h:152
void Scale(float aScale)
Function Scale scales a bounding box by its center.
Definition: cbbox.cpp:194
A vertical cylinder.
Definition: ccylinder.h:38
BOARD_ADAPTER & m_boardAdapter
settings refrence in use for this render
const SFVEC3F & Min() const
Function Min return the minimun vertex pointer.
Definition: cbbox.h:205
float GetTransparency() const
Definition: cmaterial.h:213
void ResetStats()
Definition: cobject.h:116
SFVEC3D m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
void Add(COBJECT2D *aObject)
Definition: ccontainer2d.h:52
Implements a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_T...
SFVEC3D m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
CSOLDERMASKNORMAL m_solder_mask_normal_perturbator
const int scale
const SFVEC3F & GetBoardCenter3DU() const noexcept
GetBoardCenter - the board center position in 3d units.
bool ShouldModuleBeDisplayed(MODULE_ATTR_T aModuleAttributs) const
ShouldModuleBeDisplayed - Test if module should be displayed in relation to attributs and the flags.
SFVEC2F GetExtent() const
Function GetExtent.
Definition: cbbox2d.cpp:127
struct C3D_RENDER_RAYTRACING::@3 m_materials
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
bool m_reloadRequested
!TODO: this must be reviewed in order to flag change types
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:154
std::list< COBJECT2D * > LIST_OBJECT2D
Definition: ccontainer2d.h:37
#define _(s)
Definition: 3d_actions.cpp:33
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
SFVEC3F m_Emissive
Definition: c3dmodel.h:41
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:313
unsigned int GetStats_Nr_Holes() const noexcept
GetStats_Nr_Holes - Get statistics of the nr of holes.
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
void add_3D_models(const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aModuleOpacity)
SFVEC3D m_BoardBodyColor
in realistic mode: FR4 board color
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: ccamera.h:118
static COBJECT3D_STATS & Instance()
Definition: cobject.h:133
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
void SetCastShadows(bool aCastShadow)
Definition: clight.h:57
SFVEC3F GetItemColor(int aItemId) const
GetItemColor - get the technical color of a layer.
const wxSize & GetDrillSize() const
Definition: class_pad.h:226
SFVEC3D m_CopperColor
in realistic mode: copper color
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
SphericalToCartesian.
Definition: 3d_math.h:43
void ResetStats()
Definition: cobject2d.h:135
VIATYPE GetViaType() const
Definition: class_track.h:368
float GetModulesZcoord3DIU(bool aIsFlipped) const
GetModulesZcoord3DIU - Get the position of the module in 3d integer units considering if it is flippe...
Defines math related functions.
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
CCONTAINER2D * m_outlineBoard2dObjects
const SFVEC2F & GetCentroid() const
Definition: cobject2d.h:123
const CBBOX2D & GetBBox() const
Definition: cobject2d.h:121
unsigned int GetStats_Nr_Vias() const noexcept
GetStats_Nr_Vias - Get statistics of the nr of vias.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
float GetStats_Med_Via_Hole_Diameter3DU() const noexcept
GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes.
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
void reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
void insert3DPadHole(const D_PAD *aPad)
const wxPoint GetPosition() const override
Definition: class_pad.h:161
const LIST_OBJECT2D & GetList() const
Definition: ccontainer2d.h:64
void Clear()
Clear - Remove all lights from the container.
Definition: clight.h:165
MATERIAL_MODE MaterialModeGet() const noexcept
MaterialModeGet.
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
virtual bool Intersects(const CBBOX2D &aBBox) const =0
Function Intersects.
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:61
CBBOX manages a bounding box defined by two SFVEC3F min max points.
Definition: cbbox.h:40
MAP_MODEL_MATERIALS m_model_materials
Stores materials of the 3D models.
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
bool IsInitialized() const
Function IsInitialized check if this bounding box is already initialized.
Definition: cbbox.cpp:87
TRACKS & Tracks()
Definition: class_board.h:257
SFVEC3F m_Specular
Definition: c3dmodel.h:42