KiCad PCB EDA Suite
raytracing/create_scene.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 <[email protected]>
5  * Copyright (C) 2015-2021 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 
25 #include "render_3d_raytrace.h"
26 #include "shapes3D/plane_3d.h"
28 #include "shapes3D/layer_item_3d.h"
29 #include "shapes3D/cylinder_3d.h"
30 #include "shapes3D/triangle_3d.h"
31 #include "shapes2D/layer_item_2d.h"
32 #include "shapes2D/ring_2d.h"
33 #include "shapes2D/polygon_2d.h"
36 #include "accelerators/bvh_pbrt.h"
37 #include "3d_fastmath.h"
38 #include "3d_math.h"
39 
40 #include <board.h>
41 #include <footprint.h>
42 
43 #include <base_units.h>
44 #include <profile.h> // To use GetRunningMicroSecs or another profiling utility
45 
54 static float TransparencyControl( float aGrayColorValue, float aTransparency )
55 {
56  const float aaa = aTransparency * aTransparency * aTransparency;
57 
58  // 1.00-1.05*(1.0-x)^3
59  float ca = 1.0f - aTransparency;
60  ca = 1.00f - 1.05f * ca * ca * ca;
61 
62  return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
63 }
64 
68 #define UNITS3D_TO_UNITSPCB ( IU_PER_MM )
69 
70 
72 {
75 
78 
79  double mmTo3Dunits = IU_PER_MM * m_boardAdapter.BiuTo3dUnits();
80 
82  {
83  m_boardMaterial = BOARD_NORMAL( 0.40f * mmTo3Dunits );
84 
85  m_copperMaterial = COPPER_NORMAL( 4.0f * mmTo3Dunits, &m_boardMaterial );
86 
87  m_platedCopperMaterial = PLATED_COPPER_NORMAL( 0.5f * mmTo3Dunits );
88 
90 
91  m_plasticMaterial = PLASTIC_NORMAL( 0.05f * mmTo3Dunits );
92 
93  m_shinyPlasticMaterial = PLASTIC_SHINE_NORMAL( 0.1f * mmTo3Dunits );
94 
95  m_brushedMetalMaterial = BRUSHED_METAL_NORMAL( 0.05f * mmTo3Dunits );
96 
97  m_silkScreenMaterial = SILK_SCREEN_NORMAL( 0.25f * mmTo3Dunits );
98  }
99 
100  // http://devernay.free.fr/cours/opengl/materials.html
101  // Copper
102  const SFVEC3F copperSpecularLinear =
103  ConvertSRGBToLinear( glm::clamp( (SFVEC3F) m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
104  SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) ) );
105 
108  SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
109 
111  m_materials.m_Copper.SetGenerator( &m_platedCopperMaterial );
112 
113  m_materials.m_NonPlatedCopper = BLINN_PHONG_MATERIAL(
114  ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ), SFVEC3F( 0.0f, 0.0f, 0.0f ),
115  SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
116 
118  m_materials.m_NonPlatedCopper.SetGenerator( &m_copperMaterial );
119 
123  SFVEC3F( 0.0f, 0.0f, 0.0f ),
127  0.10f * 128.0f, 0.0f, 0.0f );
128 
130  SFVEC3F( 0.0f, 0.0f, 0.0f ),
131  glm::clamp( ( ( SFVEC3F )( 1.0f ) - ConvertSRGBToLinear(
133  SFVEC3F( 0.0f ), SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
134 
136  m_materials.m_SilkS.SetGenerator( &m_silkScreenMaterial );
137 
138  // Assume that SolderMaskTop == SolderMaskBot
139  const float solderMask_gray =
142  / 3.0f;
143 
144  const float solderMask_transparency = TransparencyControl( solderMask_gray,
146 
147  m_materials.m_SolderMask = BLINN_PHONG_MATERIAL(
149  SFVEC3F( 0.0f, 0.0f, 0.0f ),
150  SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
151  solderMask_transparency, 0.16f );
152 
153  m_materials.m_SolderMask.SetCastShadows( true );
154  m_materials.m_SolderMask.SetRefractionRayCount( 1 );
155 
157  m_materials.m_SolderMask.SetGenerator( &m_solderMaskMaterial );
158 
159  m_materials.m_EpoxyBoard =
160  BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f,
161  10.0f / 255.0f ) ),
162  SFVEC3F( 0.0f, 0.0f, 0.0f ),
163  ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f, 8.0f / 255.0f,
164  10.0f / 255.0f ) ),
165  0.1f * 128.0f, 1.0f - m_boardAdapter.m_BoardBodyColor.a, 0.0f );
166 
167  m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
168 
170  m_materials.m_EpoxyBoard.SetGenerator( &m_boardMaterial );
171 
173 
174  m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ),
175  ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
176  0.10f * 128.0f, 0.0f, 0.50f );
177  m_materials.m_Floor.SetCastShadows( false );
178  m_materials.m_Floor.SetReflectionRecursionCount( 1 );
179 }
180 
181 
182 void RENDER_3D_RAYTRACE::createObject( CONTAINER_3D& aDstContainer, const OBJECT_2D* aObject2D,
183  float aZMin, float aZMax, const MATERIAL* aMaterial,
184  const SFVEC3F& aObjColor )
185 {
186  switch( aObject2D->GetObjectType() )
187  {
189  {
191 
192  XY_PLANE* objPtr;
193  objPtr = new XY_PLANE( BBOX_3D(
194  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
195  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
196  objPtr->SetMaterial( aMaterial );
197  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
198  aDstContainer.Add( objPtr );
199 
200  objPtr = new XY_PLANE( BBOX_3D(
201  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
202  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
203  objPtr->SetMaterial( aMaterial );
204  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
205  aDstContainer.Add( objPtr );
206  break;
207  }
208 
210  {
212 
213  const ROUND_SEGMENT_2D* aRoundSeg2D = static_cast<const ROUND_SEGMENT_2D*>( aObject2D );
214  ROUND_SEGMENT* objPtr = new ROUND_SEGMENT( *aRoundSeg2D, aZMin, aZMax );
215  objPtr->SetMaterial( aMaterial );
216  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
217  aDstContainer.Add( objPtr );
218  break;
219  }
220 
221  default:
222  {
223  LAYER_ITEM* objPtr = new LAYER_ITEM( aObject2D, aZMin, aZMax );
224  objPtr->SetMaterial( aMaterial );
225  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
226  aDstContainer.Add( objPtr );
227  break;
228  }
229  }
230 }
231 
232 
234  PCB_LAYER_ID aLayer_id,
235  const MATERIAL* aMaterialLayer,
236  const SFVEC3F& aLayerColor,
237  float aLayerZOffset )
238 {
239  if( aContainer2d == nullptr )
240  return;
241 
242  const LIST_OBJECT2D& listObject2d = aContainer2d->GetList();
243 
244  if( listObject2d.size() == 0 )
245  return;
246 
247  for( const OBJECT_2D* object2d_A : listObject2d )
248  {
249  // not yet used / implemented (can be used in future to clip the objects in the
250  // board borders
251  OBJECT_2D* object2d_C = CSGITEM_FULL;
252 
253  std::vector<const OBJECT_2D*>* object2d_B = CSGITEM_EMPTY;
254 
255  object2d_B = new std::vector<const OBJECT_2D*>();
256 
257  // Subtract holes but not in SolderPaste
258  // (can be added as an option in future)
259  if( !( aLayer_id == B_Paste || aLayer_id == F_Paste ) )
260  {
261  // Check if there are any layerhole that intersects this object
262  // Eg: a segment is cut by a via hole or THT hole.
263  const MAP_CONTAINER_2D_BASE& layerHolesMap = m_boardAdapter.GetLayerHoleMap();
264 
265  if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
266  {
267  const BVH_CONTAINER_2D* holes2d = layerHolesMap.at( aLayer_id );
268 
269  CONST_LIST_OBJECT2D intersecting;
270 
271  holes2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
272 
273  for( const OBJECT_2D* hole2d : intersecting )
274  object2d_B->push_back( hole2d );
275  }
276 
277  // Check if there are any THT that intersects this object. If we're processing a silk
278  // layer and the flag is set, then clip the silk at the outer edge of the annular ring,
279  // rather than the at the outer edge of the copper plating.
280  const BVH_CONTAINER_2D& throughHoleOuter =
283  && ( ( aLayer_id == B_SilkS ) || ( aLayer_id == F_SilkS ) ) ) ?
286 
287  if( !throughHoleOuter.GetList().empty() )
288  {
289  CONST_LIST_OBJECT2D intersecting;
290 
291  throughHoleOuter.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
292 
293  for( const OBJECT_2D* hole2d : intersecting )
294  object2d_B->push_back( hole2d );
295  }
296  }
297 
298  if( !m_antioutlineBoard2dObjects->GetList().empty() )
299  {
300  CONST_LIST_OBJECT2D intersecting;
301 
302  m_antioutlineBoard2dObjects->GetIntersectingObjects( object2d_A->GetBBox(),
303  intersecting );
304 
305  for( const OBJECT_2D* obj : intersecting )
306  object2d_B->push_back( obj );
307  }
308 
309  const MAP_CONTAINER_2D_BASE& mapLayers = m_boardAdapter.GetLayerMap();
310 
313  && ( ( aLayer_id == B_SilkS && mapLayers.find( B_Mask ) != mapLayers.end() )
314  || ( aLayer_id == F_SilkS && mapLayers.find( F_Mask ) != mapLayers.end() ) ) )
315  {
316  const PCB_LAYER_ID layerMask_id = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
317 
318  const BVH_CONTAINER_2D* containerMaskLayer2d = mapLayers.at( layerMask_id );
319 
320  CONST_LIST_OBJECT2D intersecting;
321 
322  if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
323  containerMaskLayer2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
324 
325  for( const OBJECT_2D* obj2d : intersecting )
326  object2d_B->push_back( obj2d );
327  }
328 
329  if( object2d_B->empty() )
330  {
331  delete object2d_B;
332  object2d_B = CSGITEM_EMPTY;
333  }
334 
335  if( ( object2d_B == CSGITEM_EMPTY ) && ( object2d_C == CSGITEM_FULL ) )
336  {
337  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
338  m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
339  m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
340  objPtr->SetMaterial( aMaterialLayer );
341  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
342  m_objectContainer.Add( objPtr );
343  }
344  else
345  {
346  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, object2d_C,
347  object2d_A->GetBoardItem() );
348  m_containerWithObjectsToDelete.Add( itemCSG2d );
349 
350  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
351  m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
352  m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
353 
354  objPtr->SetMaterial( aMaterialLayer );
355  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
356 
357  m_objectContainer.Add( objPtr );
358  }
359  }
360 }
361 
362 
363 extern void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline );
364 
365 
366 void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter,
367  bool aOnlyLoadCopperAndShapes )
368 {
369  m_reloadRequested = false;
370 
371  m_modelMaterialMap.clear();
372 
375 
376  unsigned stats_startReloadTime = GetRunningMicroSecs();
377 
378  if( !aOnlyLoadCopperAndShapes )
379  {
380  m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
381 
382  SFVEC3F camera_pos = m_boardAdapter.GetBoardCenter();
383  m_camera.SetBoardLookAtPos( camera_pos );
384  }
385 
388 
389  setupMaterials();
390 
391  if( aStatusReporter )
392  aStatusReporter->Report( _( "Load Raytracing: board" ) );
393 
394  // Create and add the outline board
397 
400 
401  if( !aOnlyLoadCopperAndShapes )
402  {
403  const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
404 
405  if( outlineCount > 0 )
406  {
407  float divFactor = 0.0f;
408 
410  divFactor = m_boardAdapter.GetAverageViaHoleDiameter() * 18.0f;
411  else if( m_boardAdapter.GetHoleCount() )
412  divFactor = m_boardAdapter.GetAverageHoleDiameter() * 8.0f;
413 
414  SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly();
415 
416  // Calculate an antiboard outline
417  SHAPE_POLY_SET antiboardPoly;
418 
420 
421  antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
422  antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
423 
424  for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
425  {
427  m_boardAdapter.BiuTo3dUnits(), -1.0f,
428  *m_boardAdapter.GetBoard(), ii );
429  }
430 
432 
433  boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
434 
435  for( int ii = 0; ii < outlineCount; ii++ )
436  {
438  m_boardAdapter.BiuTo3dUnits(), divFactor,
439  *m_boardAdapter.GetBoard(), ii );
440  }
441 
443  {
444  const LIST_OBJECT2D& listObjects = m_outlineBoard2dObjects->GetList();
445 
446  for( const OBJECT_2D* object2d_A : listObjects )
447  {
448  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
449 
450  // Check if there are any THT that intersects this outline object part
451  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
452  {
453  const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
454  CONST_LIST_OBJECT2D intersecting;
455 
456  throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
457 
458  for( const OBJECT_2D* hole : intersecting )
459  {
460  if( object2d_A->Intersects( hole->GetBBox() ) )
461  object2d_B->push_back( hole );
462  }
463  }
464 
465  if( !m_antioutlineBoard2dObjects->GetList().empty() )
466  {
467  CONST_LIST_OBJECT2D intersecting;
468 
469  m_antioutlineBoard2dObjects->GetIntersectingObjects( object2d_A->GetBBox(),
470  intersecting );
471 
472  for( const OBJECT_2D* obj : intersecting )
473  object2d_B->push_back( obj );
474  }
475 
476  if( object2d_B->empty() )
477  {
478  delete object2d_B;
479  object2d_B = CSGITEM_EMPTY;
480  }
481 
482  if( object2d_B == CSGITEM_EMPTY )
483  {
484  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
487 
488  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
490  m_objectContainer.Add( objPtr );
491  }
492  else
493  {
494 
495  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
496  CSGITEM_FULL,
498 
499  m_containerWithObjectsToDelete.Add( itemCSG2d );
500 
501  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
504 
505  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
507  m_objectContainer.Add( objPtr );
508  }
509  }
510 
511  // Add cylinders of the board body to container
512  // Note: This is actually a workaround for the holes in the board.
513  // The issue is because if a hole is in a border of a divided polygon ( ex
514  // a polygon or dummy block) it will cut also the render of the hole.
515  // So this will add a full hole.
516  // In fact, that is not need if the hole have copper.
517  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
518  {
520 
521  for( const OBJECT_2D* hole2d : holeList )
522  {
523  if( !m_antioutlineBoard2dObjects->GetList().empty() )
524  {
525  CONST_LIST_OBJECT2D intersecting;
526 
528  intersecting );
529 
530  // Do not add cylinder if it intersects the edge of the board
531  if( !intersecting.empty() )
532  continue;
533  }
534 
535  switch( hole2d->GetObjectType() )
536  {
538  {
539  const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
540 
541  CYLINDER* objPtr = new CYLINDER( hole2d->GetCentroid(),
544  radius );
545 
546  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
548 
549  m_objectContainer.Add( objPtr );
550  }
551  break;
552 
553  default:
554  break;
555  }
556  }
557  }
558  }
559  }
560  }
561 
562  if( aStatusReporter )
563  aStatusReporter->Report( _( "Load Raytracing: layers" ) );
564 
565  // Add layers maps (except B_Mask and F_Mask)
566  for( auto entry : m_boardAdapter.GetLayerMap() )
567  {
568  PCB_LAYER_ID layer_id = entry.first;
569  const BVH_CONTAINER_2D* container2d = entry.second;
570 
571  // Only process layers that exist
572  if( !container2d )
573  continue;
574 
575  if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
576  continue;
577 
578  // Mask layers are not processed here because they are a special case
579  if( layer_id == B_Mask || layer_id == F_Mask )
580  continue;
581 
582  MATERIAL* materialLayer = &m_materials.m_SilkS;
583  SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
584 
585  switch( layer_id )
586  {
587  case B_Adhes:
588  case F_Adhes:
589  break;
590 
591  case B_Paste:
592  case F_Paste:
593  materialLayer = &m_materials.m_Paste;
594 
596  layerColor = m_boardAdapter.m_SolderPasteColor;
597  else
598  layerColor = m_boardAdapter.GetLayerColor( layer_id );
599 
600  break;
601 
602  case B_SilkS:
603  materialLayer = &m_materials.m_SilkS;
604 
607  else
608  layerColor = m_boardAdapter.GetLayerColor( layer_id );
609 
610  break;
611 
612  case F_SilkS:
613  materialLayer = &m_materials.m_SilkS;
614 
617  else
618  layerColor = m_boardAdapter.GetLayerColor( layer_id );
619 
620  break;
621 
622  case Dwgs_User:
623  case Cmts_User:
624  case Eco1_User:
625  case Eco2_User:
626  case Edge_Cuts:
627  case Margin:
628  break;
629 
630  case B_CrtYd:
631  case F_CrtYd:
632  break;
633 
634  case B_Fab:
635  case F_Fab:
636  break;
637 
638  default:
640  {
642  layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
643  else
644  layerColor = m_boardAdapter.m_CopperColor;
645  }
646  else
647  {
648  layerColor = m_boardAdapter.GetLayerColor( layer_id );
649  }
650 
651  materialLayer = &m_materials.m_NonPlatedCopper;
652  break;
653  }
654 
655  createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
656  } // for each layer on map
657 
658  // Create plated copper
661  {
665 
669  }
670 
671  if( !aOnlyLoadCopperAndShapes )
672  {
673  // Add Mask layer
674  // Solder mask layers are "negative" layers so the elements that we have in the container
675  // should remove the board outline. We will check for all objects in the outline if it
676  // intersects any object in the layer container and also any hole.
678  {
679  const MATERIAL* materialLayer = &m_materials.m_SolderMask;
680 
681  for( auto entry : m_boardAdapter.GetLayerMap() )
682  {
683  PCB_LAYER_ID layer_id = entry.first;
684  const BVH_CONTAINER_2D* container2d = entry.second;
685 
686  // Only process layers that exist
687  if( !container2d )
688  continue;
689 
690  // Only get the Solder mask layers (and only if the board has them)
691  if( !( layer_id == B_Mask || layer_id == F_Mask ) )
692  continue;
693 
694  SFVEC3F layerColor;
695 
697  {
698  if( layer_id == B_Mask )
700  else
702  }
703  else
704  {
705  layerColor = m_boardAdapter.GetLayerColor( layer_id );
706  }
707 
708  const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
709  const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
710 
711  // Get the outline board objects
712  for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
713  {
714  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
715 
716  // Check if there are any THT that intersects this outline object part
717  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
718  {
719  const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
720  CONST_LIST_OBJECT2D intersecting;
721 
722  throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
723 
724  for( const OBJECT_2D* hole : intersecting )
725  {
726  if( object2d_A->Intersects( hole->GetBBox() ) )
727  object2d_B->push_back( hole );
728  }
729  }
730 
731  // Check if there are any objects in the layer to subtract with the current
732  // object
733  if( !container2d->GetList().empty() )
734  {
735  CONST_LIST_OBJECT2D intersecting;
736 
737  container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
738 
739  for( const OBJECT_2D* obj : intersecting )
740  object2d_B->push_back( obj );
741  }
742 
743  if( object2d_B->empty() )
744  {
745  delete object2d_B;
746  object2d_B = CSGITEM_EMPTY;
747  }
748 
749  if( object2d_B == CSGITEM_EMPTY )
750  {
751 #if 0
752  createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
753  materialLayer, layerColor );
754 #else
755  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
756 
757  objPtr->SetMaterial( materialLayer );
758  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
759 
760  m_objectContainer.Add( objPtr );
761 #endif
762  }
763  else
764  {
765  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
766  CSGITEM_FULL,
767  object2d_A->GetBoardItem() );
768 
769  m_containerWithObjectsToDelete.Add( itemCSG2d );
770 
771  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
772  objPtr->SetMaterial( materialLayer );
773  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
774 
775  m_objectContainer.Add( objPtr );
776  }
777  }
778  }
779  }
780 
781  addPadsAndVias();
782  }
783 
784 #ifdef PRINT_STATISTICS_3D_VIEWER
785  unsigned stats_endConvertTime = GetRunningMicroSecs();
786  unsigned stats_startLoad3DmodelsTime = stats_endConvertTime;
787 #endif
788 
789  if( aStatusReporter )
790  aStatusReporter->Report( _( "Loading 3D models..." ) );
791 
792  load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
793 
794 #ifdef PRINT_STATISTICS_3D_VIEWER
795  unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs();
796 #endif
797 
798  if( !aOnlyLoadCopperAndShapes )
799  {
800  // Add floor
802  {
803  BBOX_3D boardBBox = m_boardAdapter.GetBBox();
804 
805  if( boardBBox.IsInitialized() )
806  {
807  boardBBox.Scale( 3.0f );
808 
809  if( m_objectContainer.GetList().size() > 0 )
810  {
811  BBOX_3D containerBBox = m_objectContainer.GetBBox();
812 
813  containerBBox.Scale( 1.3f );
814 
815  const SFVEC3F centerBBox = containerBBox.GetCenter();
816 
817  // Floor triangles
818  const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
819 
820  const SFVEC3F v1 =
821  SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
822  + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
823 
824  const SFVEC3F v3 =
825  SFVEC3F( +RANGE_SCALE_3D * 4.0f, +RANGE_SCALE_3D * 4.0f, minZ )
826  + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
827 
828  const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
829  const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
830 
832 
833  TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
834  TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
835 
836  m_objectContainer.Add( newTriangle1 );
837  m_objectContainer.Add( newTriangle2 );
838 
839  newTriangle1->SetMaterial( &m_materials.m_Floor );
840  newTriangle2->SetMaterial( &m_materials.m_Floor );
841 
842  newTriangle1->SetColor( backgroundColor );
843  newTriangle2->SetColor( backgroundColor );
844 
845  // Ceiling triangles
846  const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
847 
848  const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
849  const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
850  const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
851  const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
852 
853  TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
854  TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
855 
856  m_objectContainer.Add( newTriangle3 );
857  m_objectContainer.Add( newTriangle4 );
858 
859  newTriangle3->SetMaterial( &m_materials.m_Floor );
860  newTriangle4->SetMaterial( &m_materials.m_Floor );
861 
862  newTriangle3->SetColor( backgroundColor );
863  newTriangle4->SetColor( backgroundColor );
864  }
865  }
866  }
867 
868  // Init initial lights
869  for( LIGHT* light : m_lights )
870  delete light;
871 
872  m_lights.clear();
873 
874  auto IsColorZero =
875  []( const SFVEC3F& aSource )
876  {
877  return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
878  && ( aSource.b < ( 1.0f / 255.0f ) ) );
879  };
880 
881  m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ),
883  m_cameraLight->SetCastShadows( false );
884 
885  if( !IsColorZero( m_boardAdapter.m_RtCameraLightColor ) )
886  m_lights.push_back( m_cameraLight );
887 
888  const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
889 
890  if( !IsColorZero( m_boardAdapter.m_RtLightColorTop ) )
891  {
892  m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
893  +RANGE_SCALE_3D * 2.0f ),
895  }
896 
897  if( !IsColorZero( m_boardAdapter.m_RtLightColorBottom ) )
898  {
899  m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
900  -RANGE_SCALE_3D * 2.0f ),
902  }
903 
904  wxASSERT( m_boardAdapter.m_RtLightColor.size()
906 
907  for( size_t i = 0; i < m_boardAdapter.m_RtLightColor.size(); ++i )
908  {
909  if( !IsColorZero( m_boardAdapter.m_RtLightColor[i] ) )
910  {
912 
913  m_lights.push_back( new DIRECTIONAL_LIGHT(
914  SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
916  }
917  }
918  }
919 
920  // Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
921  // class would require reimplementing bounding box calculation (feel free to do this if you
922  // have time and patience).
923  if( m_objectContainer.GetList().size() > 0 )
924  {
925  float ratio =
927  m_camera.SetMaxZoom( m_camera.GetMaxZoom() * ratio );
928 
930  / -m_camera.GetCameraInitPos().z ) );
931  }
932 
933  // Create an accelerator
934  delete m_accelerator;
936 
937  if( aStatusReporter )
938  {
939  // Calculation time in seconds
940  double calculation_time = (double) GetRunningMicroSecs() - stats_startReloadTime / 1e6;
941 
942  aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
943  }
944 }
945 
946 
948 {
949  PCB_LAYER_ID top_layer, bottom_layer;
950  int radiusBUI = ( aVia->GetDrillValue() / 2 );
951 
952  aVia->LayerPair( &top_layer, &bottom_layer );
953 
954  float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
956 
957  float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
959 
960  const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
961  -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
962 
963  RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
964  ( radiusBUI + m_boardAdapter.GetHolePlatingThickness() )
965  * m_boardAdapter.BiuTo3dUnits(), *aVia );
966 
968 
969  LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
970 
971  objPtr->SetMaterial( &m_materials.m_Copper );
972 
975  else if( aVia->GetViaType() == VIATYPE::MICROVIA )
977  else if( aVia->GetViaType() == VIATYPE::BLIND_BURIED )
979  else
981 
982  m_objectContainer.Add( objPtr );
983 }
984 
985 
987 {
988  const OBJECT_2D* object2d_A = nullptr;
989 
990  SFVEC3F objColor;
991 
993  objColor = m_boardAdapter.m_CopperColor;
994  else
996 
997  const wxSize drillsize = aPad->GetDrillSize();
998  const bool hasHole = drillsize.x && drillsize.y;
999 
1000  if( !hasHole )
1001  return;
1002 
1003  CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1004 
1005  const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
1006  + m_boardAdapter.GetCopperThickness() * 0.99f;
1007 
1008  const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
1009  - m_boardAdapter.GetCopperThickness() * 0.99f;
1010 
1011  if( drillsize.x == drillsize.y ) // usual round hole
1012  {
1013  SFVEC2F center = SFVEC2F( aPad->GetPosition().x * m_boardAdapter.BiuTo3dUnits(),
1014  -aPad->GetPosition().y * m_boardAdapter.BiuTo3dUnits() );
1015 
1016  int innerRadius = drillsize.x / 2;
1017  int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1018 
1019  RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1020  outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1021 
1023 
1024  object2d_A = ring;
1025 
1026  // If the object (ring) is intersected by an antioutline board,
1027  // it will use instead a CSG of two circles.
1028  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1029  {
1031  antiOutlineIntersectionList );
1032  }
1033 
1034  if( !antiOutlineIntersectionList.empty() )
1035  {
1036  FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1037  center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1038 
1039  FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1040  center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1041  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1042  object2d_B->push_back( innerCircle );
1043 
1044  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1045  *aPad );
1046 
1047  m_containerWithObjectsToDelete.Add( itemCSG2d );
1048  m_containerWithObjectsToDelete.Add( innerCircle );
1049  m_containerWithObjectsToDelete.Add( outterCircle );
1050 
1051  object2d_A = itemCSG2d;
1052  }
1053  }
1054  else // Oblong hole
1055  {
1056  wxPoint ends_offset;
1057  int width;
1058 
1059  if( drillsize.x > drillsize.y ) // Horizontal oval
1060  {
1061  ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1062  width = drillsize.y;
1063  }
1064  else // Vertical oval
1065  {
1066  ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1067  width = drillsize.x;
1068  }
1069 
1070  RotatePoint( &ends_offset, aPad->GetOrientation() );
1071 
1072  wxPoint start = aPad->GetPosition() + ends_offset;
1073  wxPoint end = aPad->GetPosition() - ends_offset;
1074 
1075  ROUND_SEGMENT_2D* innerSeg =
1077  -start.y * m_boardAdapter.BiuTo3dUnits() ),
1078  SFVEC2F( end.x * m_boardAdapter.BiuTo3dUnits(),
1079  -end.y * m_boardAdapter.BiuTo3dUnits() ),
1080  width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1081 
1082  ROUND_SEGMENT_2D* outerSeg =
1084  -start.y * m_boardAdapter.BiuTo3dUnits() ),
1085  SFVEC2F( end.x * m_boardAdapter.BiuTo3dUnits(),
1086  -end.y * m_boardAdapter.BiuTo3dUnits() ),
1087  ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1088  * m_boardAdapter.BiuTo3dUnits(), *aPad );
1089 
1090  // NOTE: the round segment width is the "diameter", so we double the thickness
1091  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1092  object2d_B->push_back( innerSeg );
1093 
1094  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1095 
1096  m_containerWithObjectsToDelete.Add( itemCSG2d );
1097  m_containerWithObjectsToDelete.Add( innerSeg );
1098  m_containerWithObjectsToDelete.Add( outerSeg );
1099 
1100  object2d_A = itemCSG2d;
1101 
1102  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1103  {
1105  antiOutlineIntersectionList );
1106  }
1107  }
1108 
1109  if( object2d_A )
1110  {
1111  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1112 
1113  // Check if there are any other THT that intersects this hole
1114  // It will use the non inflated holes
1115  if( !m_boardAdapter.GetThroughHoleIds().GetList().empty() )
1116  {
1117  CONST_LIST_OBJECT2D intersecting;
1118 
1120  intersecting );
1121 
1122  for( const OBJECT_2D* hole2d : intersecting )
1123  {
1124  if( object2d_A->Intersects( hole2d->GetBBox() ) )
1125  object2d_B->push_back( hole2d );
1126  }
1127  }
1128 
1129  for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1130  object2d_B->push_back( obj );
1131 
1132  if( object2d_B->empty() )
1133  {
1134  delete object2d_B;
1135  object2d_B = CSGITEM_EMPTY;
1136  }
1137 
1138  if( object2d_B == CSGITEM_EMPTY )
1139  {
1140  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1141 
1142  objPtr->SetMaterial( &m_materials.m_Copper );
1143  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1144  m_objectContainer.Add( objPtr );
1145  }
1146  else
1147  {
1148  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1149  *aPad );
1150 
1151  m_containerWithObjectsToDelete.Add( itemCSG2d );
1152 
1153  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1154 
1155  objPtr->SetMaterial( &m_materials.m_Copper );
1156  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1157 
1158  m_objectContainer.Add( objPtr );
1159  }
1160  }
1161 }
1162 
1163 
1165 {
1166  if( !m_boardAdapter.GetBoard() )
1167  return;
1168 
1169  // Insert plated vertical holes inside the board
1170 
1171  // Insert vias holes (vertical cylinders)
1172  for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1173  {
1174  if( track->Type() == PCB_VIA_T )
1175  {
1176  const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1177  insertHole( via );
1178  }
1179  }
1180 
1181  // Insert pads holes (vertical cylinders)
1182  for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1183  {
1184  for( PAD* pad : footprint->Pads() )
1185  {
1186  if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1187  insertHole( pad );
1188  }
1189  }
1190 }
1191 
1192 
1193 void RENDER_3D_RAYTRACE::load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMaterialInformation )
1194 {
1195  if( !m_boardAdapter.GetBoard() )
1196  return;
1197 
1201  {
1202  return;
1203  }
1204 
1205  // Go for all footprints
1206  for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
1207  {
1208  if( !fp->Models().empty()
1209  && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1210  {
1211  double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1212 
1213  wxPoint pos = fp->GetPosition();
1214 
1215  glm::mat4 fpMatrix = glm::mat4( 1.0f );
1216 
1217  fpMatrix = glm::translate( fpMatrix,
1218  SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
1219  -pos.y * m_boardAdapter.BiuTo3dUnits(),
1220  zpos ) );
1221 
1222  if( fp->GetOrientation() )
1223  {
1224  fpMatrix = glm::rotate( fpMatrix,
1225  ( (float) ( fp->GetOrientation() / 10.0f ) / 180.0f ) * glm::pi<float>(),
1226  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1227  }
1228 
1229  if( fp->IsFlipped() )
1230  {
1231  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1232 
1233  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1234  }
1235 
1236  const double modelunit_to_3d_units_factor =
1238 
1239  fpMatrix = glm::scale(
1240  fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1241  modelunit_to_3d_units_factor ) );
1242 
1243  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( fp );
1244 
1245  // Get the list of model files for this model
1247  auto sM = fp->Models().begin();
1248  auto eM = fp->Models().end();
1249 
1250  while( sM != eM )
1251  {
1252  if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
1253  && ( sM->m_Show && !sM->m_Filename.empty() ) )
1254  {
1255  // get it from cache
1256  const S3DMODEL* modelPtr = cacheMgr->GetModel( sM->m_Filename );
1257 
1258  // only add it if the return is not NULL.
1259  if( modelPtr )
1260  {
1261  glm::mat4 modelMatrix = fpMatrix;
1262 
1263  modelMatrix = glm::translate( modelMatrix,
1264  SFVEC3F( sM->m_Offset.x, sM->m_Offset.y, sM->m_Offset.z ) );
1265 
1266  modelMatrix = glm::rotate( modelMatrix,
1267  (float) -( sM->m_Rotation.z / 180.0f ) * glm::pi<float>(),
1268  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1269 
1270  modelMatrix = glm::rotate( modelMatrix,
1271  (float) -( sM->m_Rotation.y / 180.0f ) * glm::pi<float>(),
1272  SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1273 
1274  modelMatrix = glm::rotate( modelMatrix,
1275  (float) -( sM->m_Rotation.x / 180.0f ) * glm::pi<float>(),
1276  SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1277 
1278  modelMatrix = glm::scale( modelMatrix,
1279  SFVEC3F( sM->m_Scale.x, sM->m_Scale.y, sM->m_Scale.z ) );
1280 
1281  addModels( aDstContainer, modelPtr, modelMatrix, (float) sM->m_Opacity,
1282  aSkipMaterialInformation, boardItem );
1283  }
1284  }
1285 
1286  ++sM;
1287  }
1288  }
1289  }
1290 }
1291 
1292 
1294 {
1295  MODEL_MATERIALS* materialVector;
1296 
1297  // Try find if the materials already exists in the map list
1298  if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1299  {
1300  // Found it, so get the pointer
1301  materialVector = &m_modelMaterialMap[a3DModel];
1302  }
1303  else
1304  {
1305  // Materials was not found in the map, so it will create a new for
1306  // this model.
1307 
1308  m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1309  materialVector = &m_modelMaterialMap[a3DModel];
1310 
1311  materialVector->resize( a3DModel->m_MaterialsSize );
1312 
1313  for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1314  {
1316  {
1317  const SMATERIAL& material = a3DModel->m_Materials[imat];
1318 
1319  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1320 
1321  float reflectionFactor = 0.0f;
1322 
1323  if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1324  {
1325  reflectionFactor = glm::clamp(
1326  glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1327  0.5f );
1328  }
1329 
1330  BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1331 
1332  blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1333  ConvertSRGBToLinear( material.m_Emissive ),
1334  ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1335  material.m_Transparency, reflectionFactor );
1336 
1338  {
1339  // Guess material type and apply a normal perturbator
1340  if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1341  && ( material.m_Shininess < 0.36f )
1342  && ( material.m_Transparency == 0.0f )
1343  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1344  && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1345  < 0.15f )
1346  && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1347  < 0.15f ) ) )
1348  {
1349  // This may be a black plastic..
1350  blinnMaterial.SetGenerator( &m_plasticMaterial );
1351  }
1352  else
1353  {
1354  if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1355  && ( material.m_Shininess < 0.30f )
1356  && ( material.m_Transparency == 0.0f )
1357  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1358  || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1359  || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1360  > 0.25f ) ) )
1361  {
1362  // This may be a color plastic ...
1363  blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1364  }
1365  else
1366  {
1367  if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1368  && ( material.m_Shininess > 0.35f )
1369  && ( material.m_Transparency == 0.0f )
1370  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1371  < 0.40f )
1372  && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1373  < 0.40f )
1374  && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1375  < 0.40f ) ) )
1376  {
1377  // This may be a brushed metal
1378  blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1379  }
1380  }
1381  }
1382  }
1383  }
1384  else
1385  {
1386  ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1387  SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1388  }
1389  }
1390  }
1391 
1392  return materialVector;
1393 }
1394 
1395 
1396 void RENDER_3D_RAYTRACE::addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
1397  const glm::mat4& aModelMatrix, float aFPOpacity,
1398  bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem )
1399 {
1400  // Validate a3DModel pointers
1401  wxASSERT( a3DModel != nullptr );
1402 
1403  if( a3DModel == nullptr )
1404  return;
1405 
1406  wxASSERT( a3DModel->m_Materials != nullptr );
1407  wxASSERT( a3DModel->m_Meshes != nullptr );
1408  wxASSERT( a3DModel->m_MaterialsSize > 0 );
1409  wxASSERT( a3DModel->m_MeshesSize > 0 );
1410  wxASSERT( aFPOpacity > 0.0f );
1411  wxASSERT( aFPOpacity <= 1.0f );
1412 
1413  if( aFPOpacity > 1.0f )
1414  {
1415  aFPOpacity = 1.0f;
1416  }
1417 
1418  if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1419  && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1420  {
1421  MODEL_MATERIALS* materialVector = nullptr;
1422 
1423  if( !aSkipMaterialInformation )
1424  {
1425  materialVector = getModelMaterial( a3DModel );
1426  }
1427 
1428  const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1429 
1430  for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1431  {
1432  const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1433 
1434  // Validate the mesh pointers
1435  wxASSERT( mesh.m_Positions != nullptr );
1436  wxASSERT( mesh.m_FaceIdx != nullptr );
1437  wxASSERT( mesh.m_Normals != nullptr );
1438  wxASSERT( mesh.m_FaceIdxSize > 0 );
1439  wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1440 
1441 
1442  if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1443  && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1444  && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1445  && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1446  {
1447  float fpTransparency;
1448  const BLINN_PHONG_MATERIAL* blinn_material;
1449 
1450  if( !aSkipMaterialInformation )
1451  {
1452  blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1453 
1454  fpTransparency =
1455  1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1456  }
1457 
1458  // Add all face triangles
1459  for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1460  {
1461  const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1462  const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1463  const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1464 
1465  wxASSERT( idx0 < mesh.m_VertexSize );
1466  wxASSERT( idx1 < mesh.m_VertexSize );
1467  wxASSERT( idx2 < mesh.m_VertexSize );
1468 
1469  if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1470  && ( idx2 < mesh.m_VertexSize ) )
1471  {
1472  const SFVEC3F& v0 = mesh.m_Positions[idx0];
1473  const SFVEC3F& v1 = mesh.m_Positions[idx1];
1474  const SFVEC3F& v2 = mesh.m_Positions[idx2];
1475 
1476  const SFVEC3F& n0 = mesh.m_Normals[idx0];
1477  const SFVEC3F& n1 = mesh.m_Normals[idx1];
1478  const SFVEC3F& n2 = mesh.m_Normals[idx2];
1479 
1480  // Transform vertex with the model matrix
1481  const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1482  const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1483  const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1484 
1485  const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1486  const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1487  const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1488 
1489  TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1490 
1491  newTriangle->SetBoardItem( aBoardItem );
1492 
1493  aDstContainer.Add( newTriangle );
1494 
1495  if( !aSkipMaterialInformation )
1496  {
1497  newTriangle->SetMaterial( blinn_material );
1498  newTriangle->SetModelTransparency( fpTransparency );
1499 
1500  if( mesh.m_Color == nullptr )
1501  {
1502  const SFVEC3F diffuseColor =
1503  a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1504 
1506  newTriangle->SetColor( ConvertSRGBToLinear(
1507  MaterialDiffuseToColorCAD( diffuseColor ) ) );
1508  else
1509  newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1510  }
1511  else
1512  {
1514  newTriangle->SetColor(
1516  mesh.m_Color[idx0] ) ),
1518  mesh.m_Color[idx1] ) ),
1520  mesh.m_Color[idx2] ) ) );
1521  else
1522  newTriangle->SetColor(
1523  ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1524  ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1525  ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1526  }
1527  }
1528  }
1529  }
1530  }
1531  }
1532  }
1533 }
Use a gray shading based on diffuse material.
void SetMinZoom(float minZoom)
Definition: camera.h:180
Implement a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_To...
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
float GetTransparency() const
Definition: material.h:273
void SetColor(SFVEC3F aObjColor)
Definition: plane_3d.h:49
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: camera.h:112
BOARD_ADAPTER & m_boardAdapter
to draw micro vias
Definition: layer_ids.h:190
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
Definition: container_2d.h:39
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:140
SFVEC3F m_Ambient
Definition: c3dmodel.h:39
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
Procedural generation of the copper normals.
Definition: material.h:75
Defines math related functions.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
A base light class to derive to implement other light classes.
Definition: light.h:40
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
SOLDER_MASK_NORMAL m_solderMaskMaterial
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
void SetColor(SFVEC3F aObjColor)
Definition: cylinder_3d.h:48
void SetModelTransparency(float aModelTransparency)
Definition: object_3d.h:66
static void SetDefaultReflectionRecursionCount(unsigned int aCount)
Definition: material.h:257
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:198
bool IsFootprintShown(FOOTPRINT_ATTR_T aFPAttributes) const
Test if footprint should be displayed in relation to attributes and the flags.
static void SetDefaultRefractionRecursionCount(unsigned int aCount)
Definition: material.h:252
Implementation of conversion functions that require both schematic and board internal units.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
unsigned int m_convertedDummyBlockCount
MODEL_MATERIALS * getModelMaterial(const S3DMODEL *a3DModel)
COPPER_NORMAL m_copperMaterial
VIATYPE GetViaType() const
Definition: pcb_track.h:352
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:41
const SFVEC3F & GetCameraInitPos() const
Definition: camera.h:131
static constexpr double IU_PER_MM
Mock up a conversion function.
const BVH_CONTAINER_2D & GetThroughHoleAnnularRings() const noexcept
Get the through hole annular rings container.
PLATED_COPPER_NORMAL m_platedCopperMaterial
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
const MAP_CONTAINER_2D_BASE & GetLayerMap() const noexcept
Get the map of containers that have the objects per layer.
float GetAverageHoleDiameter() const noexcept
Average diameter of through holes.
void SetGenerator(const MATERIAL_GENERATOR *aGenerator)
Definition: material.h:328
#define UNITS3D_TO_UNITSPCB
Scale conversion from 3d model units to pcb units.
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
std::vector< SFVEC2F > m_RtLightSphericalCoords
const LIST_OBJECT & GetList() const
Definition: container_3d.h:59
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
Procedural generation of the plastic normals.
Definition: material.h:145
std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
static float TransparencyControl(float aGrayColorValue, float aTransparency)
Perform an interpolation step to easy control the transparency based on the gray color value and tran...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
Cache for storing the 3D shapes.
Definition: 3d_cache.h:52
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:378
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:70
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
std::list< LIGHT * > m_lights
Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20....
Definition: light.h:70
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SFVEC3F m_RtCameraLightColor
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
FOOTPRINT_ATTR_T
The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes() and FOOTPRINT::Get...
Definition: footprint.h:66
#define CSGITEM_FULL
Definition: layer_item_2d.h:39
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:191
CONTAINER_2D m_containerWithObjectsToDelete
A vertical cylinder.
Definition: cylinder_3d.h:37
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
S3DMODEL * GetModel(const wxString &aModelFileName)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:643
const BVH_CONTAINER_2D & GetThroughHoleIds() const noexcept
Get the through hole inner diameter container.
Base material class that can be used to derive other material implementations.
Definition: material.h:239
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
float GetMaxZoom()
Definition: camera.h:186
const SFVEC2F & Max() const
Definition: bbox_2d.h:172
void SetColor(const SFVEC3F &aColor)
static void SetDefaultReflectionRayCount(unsigned int aCount)
Definition: material.h:247
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition: bbox_3d.cpp:132
static constexpr float MIN_DISTANCE_IU
const wxSize & GetDrillSize() const
Definition: pad.h:243
void addModels(CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
like PAD_PTH, but not plated
void Scale(float aScale)
Scales a bounding box by its center.
Definition: bbox_3d.cpp:182
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
unsigned int m_converted2dRoundSegmentCount
const BVH_CONTAINER_2D * GetPlatedPadsBack() const noexcept
int m_RtRecursiveReflectionCount
SFVEC4F m_BgColorTop
background top color
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
double GetOrientation() const
Return the rotation angle of the pad in a variety of units (the basic call returns tenths of degrees)...
Definition: pad.h:349
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:189
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
S3D_CACHE * Get3dCacheManager() const noexcept
Return the 3D cache manager pointer.
Definition: board_adapter.h:88
#define CSGITEM_EMPTY
Definition: layer_item_2d.h:38
Represent a set of closed polygons.
float GetLayerTopZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the top z position.
Use all material properties from model file.
const BBOX_2D & GetBBox() const
Definition: object_2d.h:103
const void SetBoardItem(BOARD_ITEM *aBoardItem)
Definition: object_3d.h:55
float GetMaxDimension() const
Definition: bbox_3d.cpp:167
FOOTPRINTS & Footprints()
Definition: board.h:234
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
MATERIAL_MODE GetMaterialMode() const noexcept
SFVEC3F m_RtLightColorTop
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation)
static OBJECT_2D_STATS & Instance()
Definition: object_2d.h:137
void ConvertPolygonToBlocks(const SHAPE_POLY_SET &aMainPath, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (PO...
Definition: polygon_2d.cpp:378
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
static OBJECT_3D_STATS & Instance()
Definition: object_3d.h:132
const BOARD_ITEM & GetBoardItem() const
Definition: object_2d.h:66
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...
Definition: pcb_track.cpp:434
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
const BOARD * GetBoard() const noexcept
Get current board to be rendered.
#define _(s)
const BVH_CONTAINER_2D & GetThroughHoleOds() const noexcept
Get the inflated through hole outside diameters container.
int m_RtRecursiveRefractionCount
std::vector< SFVEC3F > m_RtLightColor
OBJECT_2D_TYPE GetObjectType() const
Definition: object_2d.h:107
float m_Shininess
Definition: c3dmodel.h:43
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
Get the current polygon of the epoxy board.
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:51
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition: bbox_3d.cpp:88
int m_RtRefractionSampleCount
SFVEC4F GetItemColor(int aItemId) const
Get the technical color of a layer.
void createObject(CONTAINER_3D &aDstContainer, const OBJECT_2D *aObject2D, float aZMin, float aZMax, const MATERIAL *aMaterial, const SFVEC3F &aObjColor)
Create one or more 3D objects form a 2D object and Z positions.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:796
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
void SetCastShadows(bool aCastShadow)
Definition: light.h:59
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
float GetFootprintZPos(bool aIsFlipped) const
Get the position of the footprint in 3d integer units considering if it is flipped or not.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void ResetStats()
Definition: object_3d.h:115
bool m_reloadRequested
The window size that this camera is working.
Procedural generation of the shiny brushed metal.
Definition: material.h:194
const BBOX_3D & GetBBox() const noexcept
Get the board outling bounding box.
unsigned int GetViaCount() const noexcept
Get number of vias in this board.
A triangle object.
Definition: triangle_3d.h:42
DIRECTIONAL_LIGHT * m_cameraLight
const SFVEC2F & Min() const
Definition: bbox_2d.h:167
const BBOX_3D & GetBBox() const
Definition: container_3d.h:63
A light source based only on a directional vector.
Definition: light.h:115
unsigned int GetHoleCount() const noexcept
Get number of holes in this board.
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
Get the technical color of a layer.
const int scale
multilayer pads, usually with holes
Definition: layer_ids.h:209
const BVH_CONTAINER_2D * GetPlatedPadsFront() const noexcept
to draw blind/buried vias
Definition: layer_ids.h:191
Make solid geometry for objects on layers.
Definition: layer_item_2d.h:79
wxPoint GetPosition() const override
Definition: pad.h:178
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:147
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
BOARD_NORMAL m_boardMaterial
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapset time (in microsecondes) to class PROF_COUNTER.
SFVEC3F m_Emissive
Definition: c3dmodel.h:41
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
void createItemsFromContainer(const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
SFVEC4F m_CopperColor
in realistic mode: copper color
Definition: layer_ids.h:71
void insertHole(const PCB_VIA *aVia)
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
const SFVEC3F & GetBoardCenter() const noexcept
The board center position in 3D units.
Procedural generation of the shiny plastic normals.
Definition: material.h:169
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
Definition: 3d_math.h:43
float GetAverageViaHoleDiameter() const noexcept
Thee average diameter of the via holes.
void SetColor(SFVEC3F aObjColor)
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
Defines math related functions.
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
void SetMaxZoom(float maxZoom)
Definition: camera.h:187
std::list< OBJECT_2D * > LIST_OBJECT2D
Definition: container_2d.h:36
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:166
float GetCopperThickness() const noexcept
Get the current copper layer thickness.
A plane that is parallel to XY plane.
Definition: plane_3d.h:37
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
void ResetStats()
Definition: object_2d.h:122
static void SetDefaultRefractionRayCount(unsigned int aCount)
Definition: material.h:242
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
Definition: pad.h:57
Procedural generation of the solder mask.
Definition: material.h:125
SFVEC3F m_RtLightColorBottom
const MAP_CONTAINER_2D_BASE & GetLayerHoleMap() const noexcept
Get the map of container that have the holes per layer.
virtual bool Intersects(const BBOX_2D &aBBox) const =0
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
PLASTIC_NORMAL m_plasticMaterial
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
ACCELERATOR_3D * m_accelerator
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
CONTAINER_2D * m_outlineBoard2dObjects
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:62
int m_RtReflectionSampleCount
struct RENDER_3D_RAYTRACE::@5 m_materials
TRACKS & Tracks()
Definition: board.h:231
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
const wxPoint & GetStart() const
Definition: pcb_track.h:108
SFVEC3F m_Specular
Definition: c3dmodel.h:42
virtual void Clear()
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.
int GetHolePlatingThickness() const noexcept
Get the current copper layer thickness.
SILK_SCREEN_NORMAL m_silkScreenMaterial