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 <board.h>
46 #include <footprint.h>
47 
48 #include <base_units.h>
49 #include <profile.h> // To use GetRunningMicroSecs or another profiling utility
50 
59 static float TransparencyControl( float aGrayColorValue, float aTransparency )
60 {
61  const float aaa = aTransparency * aTransparency * aTransparency;
62 
63  // 1.00-1.05*(1.0-x)^3
64  float ca = 1.0f - aTransparency;
65  ca = 1.00f - 1.05f * ca * ca * ca;
66 
67  return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
68 }
69 
73 #define UNITS3D_TO_UNITSPCB (IU_PER_MM)
74 
76 {
79 
82 
83  double mmTo3Dunits = IU_PER_MM * m_boardAdapter.BiuTo3Dunits();
84 
86  {
87  m_board_normal_perturbator = CBOARDNORMAL( 0.40f * mmTo3Dunits );
88 
89  m_copper_normal_perturbator = CCOPPERNORMAL( 4.0f * mmTo3Dunits,
91 
93 
95 
96  m_plastic_normal_perturbator = CPLASTICNORMAL( 0.05f * mmTo3Dunits );
97 
99 
101 
102  m_silkscreen_normal_perturbator = CSILKSCREENNORMAL( 0.25f * mmTo3Dunits );
103  }
104 
105  // http://devernay.free.fr/cours/opengl/materials.html
106 
107  // Copper
108  const SFVEC3F copperSpecularLinear = ConvertSRGBToLinear(
109  glm::clamp( (SFVEC3F)m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
110  SFVEC3F( 0.0f ),
111  SFVEC3F( 1.0f ) ) );
112 
114  SFVEC3F( 0.0f ), // emissive
115  copperSpecularLinear, // specular
116  0.4f * 128.0f, // shiness
117  0.0f, // transparency
118  0.0f );
119 
121  m_materials.m_Copper.SetNormalPerturbator( &m_platedcopper_normal_perturbator );
122 
123  m_materials.m_NonPlatedCopper = CBLINN_PHONG_MATERIAL(
124  ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ),// ambient
125  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
126  SFVEC3F( 0.256f, 0.137f, 0.086f ), // specular
127  0.15f * 128.0f, // shiness
128  0.0f, // transparency
129  0.0f );
130 
132  m_materials.m_NonPlatedCopper.SetNormalPerturbator( &m_copper_normal_perturbator );
133 
137  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
140  0.10f * 128.0f, // shiness
141  0.0f, // transparency
142  0.0f );
143 
144  m_materials.m_SilkS = CBLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 0.11f ) ), // ambient
145  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
146  glm::clamp(
147  ( ( SFVEC3F )( 1.0f )
149  SFVEC3F( 0.0f ),
150  SFVEC3F( 0.10f ) ), // specular
151  0.078125f * 128.0f, // shiness
152  0.0f, // transparency
153  0.0f );
154 
156  m_materials.m_SilkS.SetNormalPerturbator( &m_silkscreen_normal_perturbator );
157 
158  // Assume that SolderMaskTop == SolderMaskBot
159  const float solderMask_gray =
162  / 3.0f;
163 
164  const float solderMask_transparency = TransparencyControl( solderMask_gray,
165  1.0f - m_boardAdapter.m_SolderMaskColorTop.a ); // opacity to transparency
166 
167  m_materials.m_SolderMask = CBLINN_PHONG_MATERIAL(
169  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
170  SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), // specular
171  0.85f * 128.0f, // shiness
172  solderMask_transparency, // transparency
173  0.16f ); // reflection
174 
175  m_materials.m_SolderMask.SetCastShadows( true );
176  m_materials.m_SolderMask.SetNrRefractionsSamples( 1 );
177 
179  m_materials.m_SolderMask.SetNormalPerturbator( &m_solder_mask_normal_perturbator );
180 
181  m_materials.m_EpoxyBoard = CBLINN_PHONG_MATERIAL(
182  ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f,
183  14.0f / 255.0f,
184  10.0f / 255.0f ) ), // ambient
185  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
186  ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f,
187  8.0f / 255.0f,
188  10.0f / 255.0f ) ), // specular
189  0.1f * 128.0f, // shiness
190  1.0f - m_boardAdapter.m_BoardBodyColor.a, // opacity to transparency
191  0.0f ); // reflection
192 
193  m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
194 
196  m_materials.m_EpoxyBoard.SetNormalPerturbator( &m_board_normal_perturbator );
197 
199  //SFVEC3F bgBot = (SFVEC3F)m_boardAdapter.m_BgColorBot;
200 
202  bgTop * 0.125f, // ambient
203  SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
204  (SFVEC3F(1.0f) - bgTop) / 3.0f, // specular
205  0.10f * 128.0f, // shiness
206  0.0f, // transparency
207  0.50f ); // reflection
208  m_materials.m_Floor.SetCastShadows( false );
209  m_materials.m_Floor.SetReflectionsRecursiveLevel( 1 );
210 }
211 
212 
213 
223  const COBJECT2D* aObject2D, float aZMin, float aZMax, const CMATERIAL* aMaterial,
224  const SFVEC3F& aObjColor )
225 {
226  switch( aObject2D->GetObjectType() )
227  {
229  {
231 #if 1
232  CXYPLANE* objPtr;
233  objPtr = new CXYPLANE( CBBOX(
234  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
235  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
236  objPtr->SetMaterial( aMaterial );
237  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
238  aDstContainer.Add( objPtr );
239 
240  objPtr = new CXYPLANE( CBBOX(
241  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
242  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
243  objPtr->SetMaterial( aMaterial );
244  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
245  aDstContainer.Add( objPtr );
246 #else
247  objPtr = new CDUMMYBLOCK( CBBOX(
248  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
249  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
250  objPtr->SetMaterial( aMaterial );
251  aDstContainer.Add( objPtr );
252 #endif
253  }
254  break;
255 
257  {
259 
260  const CROUNDSEGMENT2D* aRoundSeg2D = static_cast<const CROUNDSEGMENT2D*>( aObject2D );
261  CROUNDSEG* objPtr = new CROUNDSEG( *aRoundSeg2D, aZMin, aZMax );
262  objPtr->SetMaterial( aMaterial );
263  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
264  aDstContainer.Add( objPtr );
265  }
266  break;
267 
268 
269  default:
270  {
271  CLAYERITEM* objPtr = new CLAYERITEM( aObject2D, aZMin, aZMax );
272  objPtr->SetMaterial( aMaterial );
273  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
274  aDstContainer.Add( objPtr );
275  }
276  break;
277  }
278 }
279 
281  PCB_LAYER_ID aLayer_id,
282  const CMATERIAL *aMaterialLayer,
283  const SFVEC3F &aLayerColor,
284  float aLayerZOffset )
285 {
286  if( aContainer2d == nullptr )
287  return;
288 
289  const LIST_OBJECT2D &listObject2d = aContainer2d->GetList();
290 
291  if( listObject2d.size() == 0 )
292  return;
293 
294  for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
295  itemOnLayer != listObject2d.end();
296  ++itemOnLayer )
297  {
298  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
299 
300  // not yet used / implemented (can be used in future to clip the objects in the board borders
301  COBJECT2D *object2d_C = CSGITEM_FULL;
302 
303  std::vector<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY;
304 
305  object2d_B = new std::vector<const COBJECT2D*>();
306 
307  // Subtract holes but not in SolderPaste
308  // (can be added as an option in future)
309  if( !( ( aLayer_id == B_Paste ) || ( aLayer_id == F_Paste ) ) )
310  {
311  // Check if there are any layerhole that intersects this object
312  // Eg: a segment is cutted by a via hole or THT hole.
313  // /////////////////////////////////////////////////////////////
314  const MAP_CONTAINER_2D &layerHolesMap = m_boardAdapter.GetMapLayersHoles();
315 
316  if( layerHolesMap.find(aLayer_id) != layerHolesMap.end() )
317  {
318  MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(aLayer_id);
319 
320  const CBVHCONTAINER2D *containerLayerHoles2d =
321  static_cast<const CBVHCONTAINER2D *>(ii_hole->second);
322 
323  CONST_LIST_OBJECT2D intersectionList;
324  containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(),
325  intersectionList );
326 
327  if( !intersectionList.empty() )
328  {
329  for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer =
330  intersectionList.begin();
331  holeOnLayer != intersectionList.end();
332  ++holeOnLayer )
333  {
334  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*holeOnLayer);
335 
336  //if( object2d_A->Intersects( hole2d->GetBBox() ) )
337  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
338  object2d_B->push_back( hole2d );
339  }
340  }
341  }
342 
343  // Check if there are any THT that intersects this object
344  // /////////////////////////////////////////////////////////////
345 
346  // If we're processing a silk screen layer and the flag is set, then
347  // clip the silk screening at the outer edge of the annular ring, rather
348  // than the at the outer edge of the copper plating.
349  const CBVHCONTAINER2D& throughHoleOuter =
352  && ( ( aLayer_id == B_SilkS ) || ( aLayer_id == F_SilkS ) ) ) ?
355 
356  if( !throughHoleOuter.GetList().empty() )
357  {
358  CONST_LIST_OBJECT2D intersectionList;
359 
360  throughHoleOuter.GetListObjectsIntersects(
361  object2d_A->GetBBox(), intersectionList );
362 
363  if( !intersectionList.empty() )
364  {
365  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
366  hole != intersectionList.end();
367  ++hole )
368  {
369  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
370 
371  //if( object2d_A->Intersects( hole2d->GetBBox() ) )
372  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
373  object2d_B->push_back( hole2d );
374  }
375  }
376  }
377  }
378 
379  if( !m_antioutlineBoard2dObjects->GetList().empty() )
380  {
381  CONST_LIST_OBJECT2D intersectionList;
382 
384  object2d_A->GetBBox(), intersectionList );
385 
386  if( !intersectionList.empty() )
387  {
388  for( const COBJECT2D *obj : intersectionList )
389  {
390  object2d_B->push_back( obj );
391  }
392  }
393  }
394 
395  const MAP_CONTAINER_2D& mapLayers = m_boardAdapter.GetMapLayers();
396 
399  ( ( ( aLayer_id == B_SilkS ) &&
400  ( mapLayers.find( B_Mask ) != mapLayers.end() ) ) ||
401  ( ( aLayer_id == F_SilkS ) &&
402  ( mapLayers.find( F_Mask ) != mapLayers.end() ) ) ) )
403  {
404  const PCB_LAYER_ID layerMask_id = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
405 
406  const CBVHCONTAINER2D *containerMaskLayer2d =
407  static_cast<const CBVHCONTAINER2D*>( mapLayers.at( layerMask_id ) );
408 
409  CONST_LIST_OBJECT2D intersectionList;
410 
411  if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
412  containerMaskLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(),
413  intersectionList );
414 
415  if( !intersectionList.empty() )
416  {
417  for( CONST_LIST_OBJECT2D::const_iterator objOnLayer =
418  intersectionList.begin();
419  objOnLayer != intersectionList.end();
420  ++objOnLayer )
421  {
422  const COBJECT2D* obj2d = static_cast<const COBJECT2D*>( *objOnLayer );
423 
424  object2d_B->push_back( obj2d );
425  }
426  }
427  }
428 
429  if( object2d_B->empty() )
430  {
431  delete object2d_B;
432  object2d_B = CSGITEM_EMPTY;
433  }
434 
435  if( (object2d_B == CSGITEM_EMPTY) &&
436  (object2d_C == CSGITEM_FULL) )
437  {
438  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
439  m_boardAdapter.GetLayerBottomZpos3DU( aLayer_id ) - aLayerZOffset,
440  m_boardAdapter.GetLayerTopZpos3DU( aLayer_id ) + aLayerZOffset );
441  objPtr->SetMaterial( aMaterialLayer );
442  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
443  m_object_container.Add( objPtr );
444  }
445  else
446  {
447  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
448  object2d_B,
449  object2d_C,
450  object2d_A->GetBoardItem() );
451  m_containerWithObjectsToDelete.Add( itemCSG2d );
452 
453  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
454  m_boardAdapter.GetLayerBottomZpos3DU( aLayer_id ) - aLayerZOffset,
455  m_boardAdapter.GetLayerTopZpos3DU( aLayer_id ) + aLayerZOffset );
456 
457  objPtr->SetMaterial( aMaterialLayer );
458  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
459 
460  m_object_container.Add( objPtr );
461  }
462  }
463 }
464 
465 extern void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline );
466 
468  REPORTER* aWarningReporter,
469  bool aOnlyLoadCopperAndShapes )
470 {
471  m_reloadRequested = false;
472 
473  m_model_materials.clear();
474 
477 
478  unsigned stats_startReloadTime = GetRunningMicroSecs();
479 
480  if( !aOnlyLoadCopperAndShapes )
481  {
482  m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
483 
485  m_camera.SetBoardLookAtPos( camera_pos );
486  }
487 
490 
491  setupMaterials();
492 
493  if( aStatusReporter )
494  aStatusReporter->Report( _( "Load Raytracing: board" ) );
495 
496  // Create and add the outline board
497  // /////////////////////////////////////////////////////////////////////////
498 
501 
504 
505  if( !aOnlyLoadCopperAndShapes )
506  {
507  const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
508 
509  if( outlineCount > 0 )
510  {
511  float divFactor = 0.0f;
512 
515  else
517  divFactor = m_boardAdapter.GetStats_Med_Hole_Diameter3DU() * 8.0f;
518 
519  SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly();
520 
521  // Calculate an antiboard outline
522 
523  SHAPE_POLY_SET antiboardPoly;
524 
526 
527  antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
528  antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
529 
530  for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < antiboardPoly.OutlineCount(); iOutlinePolyIdx++ )
531  {
533  antiboardPoly,
536  -1.0f,
537  *dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ),
538  iOutlinePolyIdx );
539  }
540 
542 
543  boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
544 
545  for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ )
546  {
548  boardPolyCopy,
551  divFactor,
552  *dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ),
553  iOutlinePolyIdx );
554  }
555 
557  {
558  const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList();
559 
560  for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin();
561  object2d_iterator != listObjects.end();
562  ++object2d_iterator )
563  {
564  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*object2d_iterator);
565 
566  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
567 
568  // Check if there are any THT that intersects this outline object part
569  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
570  {
571 
572  CONST_LIST_OBJECT2D intersectionList;
574  object2d_A->GetBBox(),
575  intersectionList );
576 
577  if( !intersectionList.empty() )
578  {
579  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
580  hole != intersectionList.end();
581  ++hole )
582  {
583  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
584 
585  if( object2d_A->Intersects( hole2d->GetBBox() ) )
586  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
587  object2d_B->push_back( hole2d );
588  }
589  }
590  }
591 
592  if( !m_antioutlineBoard2dObjects->GetList().empty() )
593  {
594  CONST_LIST_OBJECT2D intersectionList;
595 
597  object2d_A->GetBBox(),
598  intersectionList );
599 
600  if( !intersectionList.empty() )
601  {
602  for( const COBJECT2D *obj : intersectionList )
603  {
604  object2d_B->push_back( obj );
605  }
606  }
607  }
608 
609  if( object2d_B->empty() )
610  {
611  delete object2d_B;
612  object2d_B = CSGITEM_EMPTY;
613  }
614 
615  if( object2d_B == CSGITEM_EMPTY )
616  {
617  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
620 
621  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
623  m_object_container.Add( objPtr );
624  }
625  else
626  {
627 
628  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D(
629  object2d_A,
630  object2d_B,
631  CSGITEM_FULL,
632  (const BOARD_ITEM &)*m_boardAdapter.GetBoard() );
633 
634  m_containerWithObjectsToDelete.Add( itemCSG2d );
635 
636  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
639 
640  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
642  m_object_container.Add( objPtr );
643 
644  }
645  }
646 
647  // Add cylinders of the board body to container
648  // Note: This is actually a workarround for the holes in the board.
649  // The issue is because if a hole is in a border of a divided polygon ( ex
650  // a polygon or dummyblock) it will cut also the render of the hole.
651  // So this will add a full hole.
652  // In fact, that is not need if the hole have copper.
653  // /////////////////////////////////////////////////////////////////////////
654  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
655  {
657 
658  for( LIST_OBJECT2D::const_iterator hole = holeList.begin();
659  hole != holeList.end();
660  ++hole )
661  {
662  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
663 
664  if( !m_antioutlineBoard2dObjects->GetList().empty() )
665  {
666  CONST_LIST_OBJECT2D intersectionList;
667 
669  hole2d->GetBBox(), intersectionList );
670 
671  if( !intersectionList.empty() )
672  {
673  // Do not add cylinder if it intersects the edge of the board
674 
675  continue;
676  }
677  }
678 
679  switch( hole2d->GetObjectType() )
680  {
682  {
683  const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
684 
685  CVCYLINDER *objPtr = new CVCYLINDER(
686  hole2d->GetCentroid(),
689  radius );
690 
691  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
693 
694  m_object_container.Add( objPtr );
695  }
696  break;
697 
698  default:
699  break;
700  }
701  }
702  }
703  }
704  }
705  }
706 
707  if( aStatusReporter )
708  aStatusReporter->Report( _( "Load Raytracing: layers" ) );
709 
710  // Add layers maps (except B_Mask and F_Mask)
711  // /////////////////////////////////////////////////////////////////////////
712 
713  for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin();
714  ii != m_boardAdapter.GetMapLayers().end();
715  ++ii )
716  {
717  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
718 
719  if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
720  continue;
721 
722  // Mask layers are not processed here because they are a special case
723  if( (layer_id == B_Mask) || (layer_id == F_Mask) )
724  continue;
725 
726  CMATERIAL *materialLayer = &m_materials.m_SilkS;
727  SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
728 
729  switch( layer_id )
730  {
731  case B_Adhes:
732  case F_Adhes:
733  break;
734 
735  case B_Paste:
736  case F_Paste:
737  materialLayer = &m_materials.m_Paste;
738 
740  layerColor = m_boardAdapter.m_SolderPasteColor;
741  else
742  layerColor = m_boardAdapter.GetLayerColor( layer_id );
743  break;
744 
745  case B_SilkS:
746  materialLayer = &m_materials.m_SilkS;
747 
750  else
751  layerColor = m_boardAdapter.GetLayerColor( layer_id );
752  break;
753  case F_SilkS:
754  materialLayer = &m_materials.m_SilkS;
755 
758  else
759  layerColor = m_boardAdapter.GetLayerColor( layer_id );
760  break;
761 
762  case Dwgs_User:
763  case Cmts_User:
764  case Eco1_User:
765  case Eco2_User:
766  case Edge_Cuts:
767  case Margin:
768  break;
769 
770  case B_CrtYd:
771  case F_CrtYd:
772  break;
773 
774  case B_Fab:
775  case F_Fab:
776  break;
777 
778  default:
780  {
782  layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
783  else
784  layerColor = m_boardAdapter.m_CopperColor;
785  }
786  else
787  layerColor = m_boardAdapter.GetLayerColor( layer_id );
788 
789  materialLayer = &m_materials.m_NonPlatedCopper;
790  break;
791  }
792 
793  const CBVHCONTAINER2D* container2d = static_cast<const CBVHCONTAINER2D*>(ii->second);
794 
795  createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
796  }// for each layer on map
797 
798  // Create plated copper
801  {
804 
807  }
808 
809  if( !aOnlyLoadCopperAndShapes )
810  {
811  // Add Mask layer
812  // Solder mask layers are "negative" layers so the elements that we have
813  // (in the container) should remove the board outline.
814  // We will check for all objects in the outline if it intersects any object
815  // in the layer container and also any hole.
816  // /////////////////////////////////////////////////////////////////////////
818  (m_outlineBoard2dObjects->GetList().size() >= 1) )
819  {
820  const CMATERIAL *materialLayer = &m_materials.m_SolderMask;
821 
822  for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin();
823  ii != m_boardAdapter.GetMapLayers().end();
824  ++ii )
825  {
826  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
827 
828  const CBVHCONTAINER2D *containerLayer2d =
829  static_cast<const CBVHCONTAINER2D *>(ii->second);
830 
831  // Only get the Solder mask layers
832  if( !( layer_id == B_Mask || layer_id == F_Mask ) )
833  continue;
834 
835  SFVEC3F layerColor;
837  {
838  if( layer_id == B_Mask )
840  else
842  }
843  else
844  layerColor = m_boardAdapter.GetLayerColor( layer_id );
845 
846  const float zLayerMin = m_boardAdapter.GetLayerBottomZpos3DU( layer_id );
847  const float zLayerMax = m_boardAdapter.GetLayerTopZpos3DU( layer_id );
848 
849  // Get the outline board objects
850  const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList();
851 
852  for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin();
853  object2d_iterator != listObjects.end();
854  ++object2d_iterator )
855  {
856  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*object2d_iterator);
857 
858  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
859 
860  // Check if there are any THT that intersects this outline object part
861  if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() )
862  {
863 
864  CONST_LIST_OBJECT2D intersectionList;
865 
867  object2d_A->GetBBox(),
868  intersectionList );
869 
870  if( !intersectionList.empty() )
871  {
872  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
873  hole != intersectionList.end();
874  ++hole )
875  {
876  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
877 
878  if( object2d_A->Intersects( hole2d->GetBBox() ) )
879  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
880  object2d_B->push_back( hole2d );
881  }
882  }
883  }
884 
885  // Check if there are any objects in the layer to subtract with the
886  // corrent object
887  if( !containerLayer2d->GetList().empty() )
888  {
889  CONST_LIST_OBJECT2D intersectionList;
890 
891  containerLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(),
892  intersectionList );
893 
894  if( !intersectionList.empty() )
895  {
896  for( CONST_LIST_OBJECT2D::const_iterator obj = intersectionList.begin();
897  obj != intersectionList.end();
898  ++obj )
899  {
900  const COBJECT2D *obj2d = static_cast<const COBJECT2D *>(*obj);
901 
902  //if( object2d_A->Intersects( obj2d->GetBBox() ) )
903  //if( object2d_A->GetBBox().Intersects( obj2d->GetBBox() ) )
904  object2d_B->push_back( obj2d );
905  }
906  }
907  }
908 
909  if( object2d_B->empty() )
910  {
911  delete object2d_B;
912  object2d_B = CSGITEM_EMPTY;
913  }
914 
915  if( object2d_B == CSGITEM_EMPTY )
916  {
917  #if 0
919  object2d_A,
920  zLayerMin,
921  zLayerMax,
922  materialLayer,
923  layerColor );
924  #else
925  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
926  zLayerMin,
927  zLayerMax );
928 
929  objPtr->SetMaterial( materialLayer );
930  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
931 
932  m_object_container.Add( objPtr );
933  #endif
934  }
935  else
936  {
937  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
938  object2d_B,
939  CSGITEM_FULL,
940  object2d_A->GetBoardItem() );
941 
942  m_containerWithObjectsToDelete.Add( itemCSG2d );
943 
944  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d,
945  zLayerMin,
946  zLayerMax );
947  objPtr->SetMaterial( materialLayer );
948  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
949 
950  m_object_container.Add( objPtr );
951  }
952  }
953  }
954  }
955 
957  }
958 
959 #ifdef PRINT_STATISTICS_3D_VIEWER
960  unsigned stats_endConvertTime = GetRunningMicroSecs();
961  unsigned stats_startLoad3DmodelsTime = stats_endConvertTime;
962 #endif
963 
964  if( aStatusReporter )
965  aStatusReporter->Report( _( "Loading 3D models" ) );
966 
967  load_3D_models( m_object_container, aOnlyLoadCopperAndShapes );
968 
969 
970 #ifdef PRINT_STATISTICS_3D_VIEWER
971  unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs();
972 #endif
973 
974  if( !aOnlyLoadCopperAndShapes )
975  {
976  // Add floor
977  // /////////////////////////////////////////////////////////////////////////
979  {
980  CBBOX boardBBox = m_boardAdapter.GetBBox3DU();
981 
982  if( boardBBox.IsInitialized() )
983  {
984  boardBBox.Scale( 3.0f );
985 
986  if( m_object_container.GetList().size() > 0 )
987  {
988  CBBOX containerBBox = m_object_container.GetBBox();
989 
990  containerBBox.Scale( 1.3f );
991 
992  const SFVEC3F centerBBox = containerBBox.GetCenter();
993 
994  // Floor triangles
995  const float minZ = glm::min( containerBBox.Min().z,
996  boardBBox.Min().z );
997 
998  const SFVEC3F v1 = SFVEC3F( -RANGE_SCALE_3D * 4.0f,
999  -RANGE_SCALE_3D * 4.0f,
1000  minZ ) +
1001  SFVEC3F( centerBBox.x,
1002  centerBBox.y,
1003  0.0f );
1004 
1005  const SFVEC3F v3 = SFVEC3F( +RANGE_SCALE_3D * 4.0f,
1006  +RANGE_SCALE_3D * 4.0f,
1007  minZ ) +
1008  SFVEC3F( centerBBox.x,
1009  centerBBox.y,
1010  0.0f );
1011 
1012  const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
1013  const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
1014 
1015  SFVEC3F backgroundColor =
1016  ConvertSRGBToLinear( static_cast<SFVEC3F>( m_boardAdapter.m_BgColorTop ) );
1017 
1018  CTRIANGLE *newTriangle1 = new CTRIANGLE( v1, v2, v3 );
1019  CTRIANGLE *newTriangle2 = new CTRIANGLE( v3, v4, v1 );
1020 
1021  m_object_container.Add( newTriangle1 );
1022  m_object_container.Add( newTriangle2 );
1023 
1024  newTriangle1->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
1025  newTriangle2->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
1026 
1027  newTriangle1->SetColor( backgroundColor );
1028  newTriangle2->SetColor( backgroundColor );
1029 
1030  // Ceiling triangles
1031  const float maxZ = glm::max( containerBBox.Max().z,
1032  boardBBox.Max().z );
1033 
1034  const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
1035  const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
1036  const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
1037  const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
1038 
1039  CTRIANGLE *newTriangle3 = new CTRIANGLE( v7, v6, v5 );
1040  CTRIANGLE *newTriangle4 = new CTRIANGLE( v5, v8, v7 );
1041 
1042  m_object_container.Add( newTriangle3 );
1043  m_object_container.Add( newTriangle4 );
1044 
1045  newTriangle3->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
1046  newTriangle4->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor );
1047 
1048  newTriangle3->SetColor( backgroundColor );
1049  newTriangle4->SetColor( backgroundColor );
1050  }
1051  }
1052  }
1053 
1054 
1055  // Init initial lights
1056  // /////////////////////////////////////////////////////////////////////////
1057  m_lights.Clear();
1058 
1059  auto IsColorZero = [] ( const SFVEC3F& aSource )
1060  {
1061  return ( ( aSource.r < ( 1.0f / 255.0f ) ) &&
1062  ( aSource.g < ( 1.0f / 255.0f ) ) &&
1063  ( aSource.b < ( 1.0f / 255.0f ) ) );
1064  };
1065 
1066  m_camera_light = new CDIRECTIONALLIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ),
1068  m_camera_light->SetCastShadows( false );
1069 
1070  if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorCamera ) )
1072 
1073  const SFVEC3F& boardCenter = m_boardAdapter.GetBBox3DU().GetCenter();
1074 
1075  if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorTop ) )
1076  m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, +RANGE_SCALE_3D * 2.0f ),
1078 
1079  if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorBottom ) )
1080  m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, -RANGE_SCALE_3D * 2.0f ),
1082 
1083  wxASSERT( m_boardAdapter.m_raytrace_lightColor.size()
1085 
1086  for( size_t i = 0; i < m_boardAdapter.m_raytrace_lightColor.size(); ++i )
1087  {
1088  if( !IsColorZero( m_boardAdapter.m_raytrace_lightColor[i] ) )
1089  {
1091 
1092  m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi<float>() * sc.x,
1093  glm::pi<float>() * sc.y ),
1095  }
1096  }
1097  }
1098 
1099  // Create an accelerator
1100  // /////////////////////////////////////////////////////////////////////////
1101  if( m_accelerator )
1102  {
1103  delete m_accelerator;
1104  }
1105  m_accelerator = 0;
1106 
1108 
1109  if( aStatusReporter )
1110  {
1111  // Calculation time in seconds
1112  const double calculation_time = (double)( GetRunningMicroSecs() -
1113  stats_startReloadTime ) / 1e6;
1114 
1115  aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
1116  }
1117 }
1118 
1119 
1120 
1121 // Based on draw3DViaHole from
1122 // 3d_draw_helper_functions.cpp
1124 {
1125  PCB_LAYER_ID top_layer, bottom_layer;
1126  int radiusBUI = (aVia->GetDrillValue() / 2);
1127 
1128  aVia->LayerPair( &top_layer, &bottom_layer );
1129 
1130  float topZ = m_boardAdapter.GetLayerBottomZpos3DU( top_layer ) +
1132 
1133  float botZ = m_boardAdapter.GetLayerBottomZpos3DU( bottom_layer ) -
1135 
1136  const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3Dunits(),
1137  -aVia->GetStart().y * m_boardAdapter.BiuTo3Dunits() );
1138 
1139  CRING2D *ring = new CRING2D( center,
1140  radiusBUI * m_boardAdapter.BiuTo3Dunits(),
1141  ( radiusBUI + m_boardAdapter.GetHolePlatingThicknessBIU() ) *
1143  *aVia );
1144 
1146 
1147 
1148  CLAYERITEM *objPtr = new CLAYERITEM( ring, topZ, botZ );
1149 
1150  objPtr->SetMaterial( &m_materials.m_Copper );
1151 
1154  else
1155  objPtr->SetColor( ConvertSRGBToLinear(
1156  m_boardAdapter.GetItemColor( LAYER_VIAS + static_cast<int>( aVia->GetViaType() ) ) ) );
1157 
1158  m_object_container.Add( objPtr );
1159 }
1160 
1161 
1162 // Based on draw3DPadHole from
1163 // 3d_draw_helper_functions.cpp
1165 {
1166  const COBJECT2D *object2d_A = NULL;
1167 
1168  SFVEC3F objColor;
1169 
1171  objColor = (SFVEC3F)m_boardAdapter.m_CopperColor;
1172  else
1174 
1175  const wxSize drillsize = aPad->GetDrillSize();
1176  const bool hasHole = drillsize.x && drillsize.y;
1177 
1178  if( !hasHole )
1179  return;
1180 
1181  CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1182 
1183  const float topZ = m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) +
1185 
1186  const float botZ = m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) -
1188 
1189  if( drillsize.x == drillsize.y ) // usual round hole
1190  {
1191  SFVEC2F center = SFVEC2F( aPad->GetPosition().x * m_boardAdapter.BiuTo3Dunits(),
1192  -aPad->GetPosition().y * m_boardAdapter.BiuTo3Dunits() );
1193 
1194  int innerRadius = drillsize.x / 2;
1195  int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThicknessBIU();
1196 
1197  CRING2D *ring = new CRING2D( center,
1198  innerRadius * m_boardAdapter.BiuTo3Dunits(),
1199  outerRadius * m_boardAdapter.BiuTo3Dunits(),
1200  *aPad );
1201 
1203 
1204  object2d_A = ring;
1205 
1206  // If the object (ring) is intersected by an antioutline board,
1207  // it will use instease a CSG of two circles.
1208  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1209  {
1210 
1212  object2d_A->GetBBox(),
1213  antiOutlineIntersectionList );
1214  }
1215 
1216  if( !antiOutlineIntersectionList.empty() )
1217  {
1218  CFILLEDCIRCLE2D *innerCircle = new CFILLEDCIRCLE2D( center,
1219  innerRadius * m_boardAdapter.BiuTo3Dunits(),
1220  *aPad );
1221 
1222  CFILLEDCIRCLE2D *outterCircle = new CFILLEDCIRCLE2D( center,
1223  outerRadius * m_boardAdapter.BiuTo3Dunits(),
1224  *aPad );
1225  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
1226  object2d_B->push_back( innerCircle );
1227 
1228  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( outterCircle,
1229  object2d_B,
1230  CSGITEM_FULL,
1231  *aPad );
1232 
1233  m_containerWithObjectsToDelete.Add( itemCSG2d );
1234  m_containerWithObjectsToDelete.Add( innerCircle );
1235  m_containerWithObjectsToDelete.Add( outterCircle );
1236 
1237  object2d_A = itemCSG2d;
1238  }
1239  }
1240  else // Oblong hole
1241  {
1242  wxPoint ends_offset;
1243  int width;
1244 
1245  if( drillsize.x > drillsize.y ) // Horizontal oval
1246  {
1247  ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1248  width = drillsize.y;
1249  }
1250  else // Vertical oval
1251  {
1252  ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1253  width = drillsize.x;
1254  }
1255 
1256  RotatePoint( &ends_offset, aPad->GetOrientation() );
1257 
1258  wxPoint start = aPad->GetPosition() + ends_offset;
1259  wxPoint end = aPad->GetPosition() - ends_offset;
1260 
1261  CROUNDSEGMENT2D *innerSeg = new CROUNDSEGMENT2D(
1262  SFVEC2F( start.x * m_boardAdapter.BiuTo3Dunits(),
1263  -start.y * m_boardAdapter.BiuTo3Dunits() ),
1264  SFVEC2F( end.x * m_boardAdapter.BiuTo3Dunits(),
1265  -end.y * m_boardAdapter.BiuTo3Dunits() ),
1266  width * m_boardAdapter.BiuTo3Dunits(),
1267  *aPad );
1268 
1269  CROUNDSEGMENT2D *outerSeg = new CROUNDSEGMENT2D(
1270  SFVEC2F( start.x * m_boardAdapter.BiuTo3Dunits(),
1271  -start.y * m_boardAdapter.BiuTo3Dunits() ),
1272  SFVEC2F( end.x * m_boardAdapter.BiuTo3Dunits(),
1273  -end.y * m_boardAdapter.BiuTo3Dunits() ),
1275  *aPad );
1276 
1277  // NOTE: the round segment width is the "diameter", so we double the thickness
1278 
1279  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
1280  object2d_B->push_back( innerSeg );
1281 
1282  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( outerSeg,
1283  object2d_B,
1284  CSGITEM_FULL,
1285  *aPad );
1286 
1287  m_containerWithObjectsToDelete.Add( itemCSG2d );
1288  m_containerWithObjectsToDelete.Add( innerSeg );
1289  m_containerWithObjectsToDelete.Add( outerSeg );
1290 
1291  object2d_A = itemCSG2d;
1292 
1293  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1294  {
1295 
1297  object2d_A->GetBBox(),
1298  antiOutlineIntersectionList );
1299  }
1300  }
1301 
1302 
1303  if( object2d_A )
1304  {
1305  std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
1306 
1307  // Check if there are any other THT that intersects this hole
1308  // It will use the non inflated holes
1309  if( !m_boardAdapter.GetThroughHole_Inner().GetList().empty() )
1310  {
1311 
1312  CONST_LIST_OBJECT2D intersectionList;
1314  intersectionList );
1315 
1316  if( !intersectionList.empty() )
1317  {
1318  for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
1319  hole != intersectionList.end();
1320  ++hole )
1321  {
1322  const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
1323 
1324  if( object2d_A->Intersects( hole2d->GetBBox() ) )
1325  //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
1326  object2d_B->push_back( hole2d );
1327  }
1328  }
1329  }
1330 
1331  if( !antiOutlineIntersectionList.empty() )
1332  {
1333  for( const COBJECT2D *obj : antiOutlineIntersectionList )
1334  {
1335  object2d_B->push_back( obj );
1336  }
1337  }
1338 
1339  if( object2d_B->empty() )
1340  {
1341  delete object2d_B;
1342  object2d_B = CSGITEM_EMPTY;
1343  }
1344 
1345  if( object2d_B == CSGITEM_EMPTY )
1346  {
1347  CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, topZ, botZ );
1348 
1349  objPtr->SetMaterial( &m_materials.m_Copper );
1350  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1351  m_object_container.Add( objPtr );
1352  }
1353  else
1354  {
1355  CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A,
1356  object2d_B,
1357  CSGITEM_FULL,
1358  (const BOARD_ITEM &)*aPad );
1359 
1360  m_containerWithObjectsToDelete.Add( itemCSG2d );
1361 
1362  CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, topZ, botZ );
1363 
1364  objPtr->SetMaterial( &m_materials.m_Copper );
1365  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1366 
1367  m_object_container.Add( objPtr );
1368  }
1369  }
1370 }
1371 
1372 
1374 {
1375  // Insert plated vertical holes inside the board
1376  // /////////////////////////////////////////////////////////////////////////
1377 
1378  // Insert vias holes (vertical cylinders)
1379  for( TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1380  {
1381  if( track->Type() == PCB_VIA_T )
1382  {
1383  const VIA *via = static_cast<const VIA*>(track);
1384  insert3DViaHole( via );
1385  }
1386  }
1387 
1388  // Insert pads holes (vertical cylinders)
1389  for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1390  {
1391  for( PAD* pad : footprint->Pads() )
1392  if( pad->GetAttribute () != PAD_ATTRIB_NPTH )
1393  {
1394  insert3DPadHole( pad );
1395  }
1396  }
1397 }
1398 
1399 
1400 void C3D_RENDER_RAYTRACING::load_3D_models( CCONTAINER &aDstContainer, bool aSkipMaterialInformation )
1401 {
1402  // Go for all footprints
1403  for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
1404  {
1405  if( !fp->Models().empty()
1406  && m_boardAdapter.ShouldFPBeDisplayed( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1407  {
1408  double zpos = m_boardAdapter.GetModulesZcoord3DIU( fp->IsFlipped() );
1409 
1410  wxPoint pos = fp->GetPosition();
1411 
1412  glm::mat4 fpMatrix = glm::mat4( 1.0f );
1413 
1414  fpMatrix = glm::translate( fpMatrix, SFVEC3F( pos.x * m_boardAdapter.BiuTo3Dunits(),
1415  -pos.y * m_boardAdapter.BiuTo3Dunits(),
1416  zpos ) );
1417 
1418  if( fp->GetOrientation() )
1419  {
1420  fpMatrix = glm::rotate( fpMatrix,
1421  ( (float)(fp->GetOrientation() / 10.0f) / 180.0f ) * glm::pi<float>(),
1422  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1423  }
1424 
1425 
1426  if( fp->IsFlipped() )
1427  {
1428  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1429 
1430  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1431  }
1432 
1433  const double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3Dunits() *
1435 
1436  fpMatrix = glm::scale( fpMatrix,
1437  SFVEC3F( modelunit_to_3d_units_factor,
1438  modelunit_to_3d_units_factor,
1439  modelunit_to_3d_units_factor ) );
1440 
1441  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( fp );
1442 
1443  // Get the list of model files for this model
1445  auto sM = fp->Models().begin();
1446  auto eM = fp->Models().end();
1447 
1448  while( sM != eM )
1449  {
1450  if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON ) &&
1451  ( sM->m_Show && !sM->m_Filename.empty() ) )
1452  {
1453  // get it from cache
1454  const S3DMODEL *modelPtr = cacheMgr->GetModel( sM->m_Filename );
1455 
1456  // only add it if the return is not NULL
1457  if( modelPtr )
1458  {
1459  glm::mat4 modelMatrix = fpMatrix;
1460 
1461  modelMatrix = glm::translate( modelMatrix,
1462  SFVEC3F( sM->m_Offset.x,
1463  sM->m_Offset.y,
1464  sM->m_Offset.z ) );
1465 
1466  modelMatrix = glm::rotate( modelMatrix,
1467  (float)-( sM->m_Rotation.z / 180.0f ) *
1468  glm::pi<float>(),
1469  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1470 
1471  modelMatrix = glm::rotate( modelMatrix,
1472  (float)-( sM->m_Rotation.y / 180.0f ) *
1473  glm::pi<float>(),
1474  SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1475 
1476  modelMatrix = glm::rotate( modelMatrix,
1477  (float)-( sM->m_Rotation.x / 180.0f ) *
1478  glm::pi<float>(),
1479  SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1480 
1481  modelMatrix = glm::scale( modelMatrix,
1482  SFVEC3F( sM->m_Scale.x,
1483  sM->m_Scale.y,
1484  sM->m_Scale.z ) );
1485 
1486  add_3D_models( aDstContainer,
1487  modelPtr,
1488  modelMatrix,
1489  (float)sM->m_Opacity,
1490  aSkipMaterialInformation,
1491  boardItem );
1492  }
1493  }
1494 
1495  ++sM;
1496  }
1497  }
1498  }
1499 }
1500 
1502 {
1503  MODEL_MATERIALS *materialVector;
1504 
1505  // Try find if the materials already exists in the map list
1506  if( m_model_materials.find( a3DModel ) != m_model_materials.end() )
1507  {
1508  // Found it, so get the pointer
1509  materialVector = &m_model_materials[a3DModel];
1510  }
1511  else
1512  {
1513  // Materials was not found in the map, so it will create a new for
1514  // this model.
1515 
1516  m_model_materials[a3DModel] = MODEL_MATERIALS();
1517  materialVector = &m_model_materials[a3DModel];
1518 
1519  materialVector->resize( a3DModel->m_MaterialsSize );
1520 
1521  for( unsigned int imat = 0;
1522  imat < a3DModel->m_MaterialsSize;
1523  ++imat )
1524  {
1526  {
1527  const SMATERIAL &material = a3DModel->m_Materials[imat];
1528 
1529  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1530 
1531  float reflectionFactor = 0.0f;
1532 
1533  if( (material.m_Shininess - 0.35f) > FLT_EPSILON )
1534  {
1535  reflectionFactor = glm::clamp( glm::sqrt( (material.m_Shininess - 0.35f) ) *
1536  0.40f - 0.05f,
1537  0.0f,
1538  0.5f );
1539  }
1540 
1541  CBLINN_PHONG_MATERIAL &blinnMaterial = (*materialVector)[imat];
1542 
1543  blinnMaterial = CBLINN_PHONG_MATERIAL(
1544  ConvertSRGBToLinear( material.m_Ambient ),
1545  ConvertSRGBToLinear( material.m_Emissive ),
1546  ConvertSRGBToLinear( material.m_Specular ),
1547  material.m_Shininess * 180.0f,
1548  material.m_Transparency,
1549  reflectionFactor );
1550 
1552  {
1553  // Guess material type and apply a normal perturbator
1554 
1555  if( ( RGBtoGray( material.m_Diffuse ) < 0.3f ) &&
1556  ( material.m_Shininess < 0.36f ) &&
1557  ( material.m_Transparency == 0.0f ) &&
1558  ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f ) &&
1559  ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) < 0.15f ) &&
1560  ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) < 0.15f ) ) )
1561  {
1562  // This may be a black plastic..
1564  }
1565  else
1566  {
1567  if( ( RGBtoGray( material.m_Diffuse ) > 0.3f ) &&
1568  ( material.m_Shininess < 0.30f ) &&
1569  ( material.m_Transparency == 0.0f ) &&
1570  ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f ) ||
1571  ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f ) ||
1572  ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) > 0.25f ) ) )
1573  {
1574  // This may be a color plastic ...
1576  }
1577  else
1578  {
1579  if( ( RGBtoGray( material.m_Diffuse ) > 0.6f ) &&
1580  ( material.m_Shininess > 0.35f ) &&
1581  ( material.m_Transparency == 0.0f ) &&
1582  ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.40f ) &&
1583  ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) < 0.40f ) &&
1584  ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b ) < 0.40f ) ) )
1585  {
1586  // This may be a brushed metal
1588  }
1589  }
1590  }
1591  }
1592  }
1593  else
1594  {
1595  (*materialVector)[imat] = CBLINN_PHONG_MATERIAL( SFVEC3F( 0.2f ),
1596  SFVEC3F( 0.0f ),
1597  SFVEC3F( 0.0f ),
1598  0.0f,
1599  0.0f,
1600  0.0f );
1601  }
1602  }
1603  }
1604 
1605  return materialVector;
1606 }
1607 
1608 void C3D_RENDER_RAYTRACING::add_3D_models( CCONTAINER &aDstContainer, const S3DMODEL *a3DModel,
1609  const glm::mat4 &aModelMatrix, float aFPOpacity,
1610  bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem )
1611 {
1612 
1613  // Validate a3DModel pointers
1614  wxASSERT( a3DModel != NULL );
1615 
1616  if( a3DModel == NULL )
1617  return;
1618 
1619  wxASSERT( a3DModel->m_Materials != NULL );
1620  wxASSERT( a3DModel->m_Meshes != NULL );
1621  wxASSERT( a3DModel->m_MaterialsSize > 0 );
1622  wxASSERT( a3DModel->m_MeshesSize > 0 );
1623  wxASSERT( aFPOpacity > 0.0f );
1624  wxASSERT( aFPOpacity <= 1.0f );
1625 
1626  if( aFPOpacity > 1.0f )
1627  {
1628  aFPOpacity = 1.0f;
1629  }
1630 
1631  if( (a3DModel->m_Materials != NULL) && (a3DModel->m_Meshes != NULL) &&
1632  (a3DModel->m_MaterialsSize > 0) && (a3DModel->m_MeshesSize > 0) )
1633  {
1634 
1635  MODEL_MATERIALS *materialVector = NULL;
1636 
1637  if( !aSkipMaterialInformation )
1638  {
1639  materialVector = get_3D_model_material( a3DModel );
1640  }
1641 
1642  const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1643 
1644  for( unsigned int mesh_i = 0;
1645  mesh_i < a3DModel->m_MeshesSize;
1646  ++mesh_i )
1647  {
1648  const SMESH &mesh = a3DModel->m_Meshes[mesh_i];
1649 
1650  // Validate the mesh pointers
1651  wxASSERT( mesh.m_Positions != NULL );
1652  wxASSERT( mesh.m_FaceIdx != NULL );
1653  wxASSERT( mesh.m_Normals != NULL );
1654  wxASSERT( mesh.m_FaceIdxSize > 0 );
1655  wxASSERT( (mesh.m_FaceIdxSize % 3) == 0 );
1656 
1657 
1658  if( (mesh.m_Positions != NULL) &&
1659  (mesh.m_Normals != NULL) &&
1660  (mesh.m_FaceIdx != NULL) &&
1661  (mesh.m_FaceIdxSize > 0) &&
1662  (mesh.m_VertexSize > 0) &&
1663  ((mesh.m_FaceIdxSize % 3) == 0) &&
1664  (mesh.m_MaterialIdx < a3DModel->m_MaterialsSize) )
1665  {
1666  float fpTransparency;
1667  const CBLINN_PHONG_MATERIAL *blinn_material;
1668 
1669  if( !aSkipMaterialInformation )
1670  {
1671  blinn_material = &(*materialVector)[mesh.m_MaterialIdx];
1672 
1673  fpTransparency = 1.0f - (( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1674  }
1675 
1676  // Add all face triangles
1677  for( unsigned int faceIdx = 0;
1678  faceIdx < mesh.m_FaceIdxSize;
1679  faceIdx += 3 )
1680  {
1681  const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1682  const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1683  const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1684 
1685  wxASSERT( idx0 < mesh.m_VertexSize );
1686  wxASSERT( idx1 < mesh.m_VertexSize );
1687  wxASSERT( idx2 < mesh.m_VertexSize );
1688 
1689  if( ( idx0 < mesh.m_VertexSize ) &&
1690  ( idx1 < mesh.m_VertexSize ) &&
1691  ( idx2 < mesh.m_VertexSize ) )
1692  {
1693  const SFVEC3F &v0 = mesh.m_Positions[idx0];
1694  const SFVEC3F &v1 = mesh.m_Positions[idx1];
1695  const SFVEC3F &v2 = mesh.m_Positions[idx2];
1696 
1697  const SFVEC3F &n0 = mesh.m_Normals[idx0];
1698  const SFVEC3F &n1 = mesh.m_Normals[idx1];
1699  const SFVEC3F &n2 = mesh.m_Normals[idx2];
1700 
1701  // Transform vertex with the model matrix
1702  const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f) );
1703  const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f) );
1704  const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f) );
1705 
1706  const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1707  const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1708  const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1709 
1710  CTRIANGLE *newTriangle = new CTRIANGLE( vt0, vt2, vt1,
1711  nt0, nt2, nt1 );
1712 
1713  newTriangle->SetBoardItem( aBoardItem );
1714 
1715  aDstContainer.Add( newTriangle );
1716 
1717  if( !aSkipMaterialInformation )
1718  {
1719  newTriangle->SetMaterial( blinn_material );
1720  newTriangle->SetModelTransparency( fpTransparency );
1721 
1722  if( mesh.m_Color == NULL )
1723  {
1724  const SFVEC3F diffuseColor =
1725  a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1726 
1728  newTriangle->SetColor( ConvertSRGBToLinear( MaterialDiffuseToColorCAD( diffuseColor ) ) );
1729  else
1730  newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1731  }
1732  else
1733  {
1735  newTriangle->SetColor( ConvertSRGBToLinear( MaterialDiffuseToColorCAD( mesh.m_Color[idx0] ) ),
1738  else
1739  newTriangle->SetColor( ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1740  ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1741  ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1742  }
1743  }
1744  }
1745  }
1746  }
1747  }
1748  }
1749 }
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.
std::vector< SFVEC3F > m_raytrace_lightColor
SFVEC3F m_raytrace_lightColorBottom
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: track.cpp:422
Definition: track.h:354
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:147
SFVEC3F m_raytrace_lightColorCamera
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
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
const SFVEC3F & Max() const
Function Max return the maximum vertex pointer.
Definition: cbbox.h:211
Defines math related functions.
int OutlineCount() const
Returns the number of outlines in the set
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
CPLASTICNORMAL m_plastic_normal_perturbator
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
CBVHCONTAINER2D * m_antioutlineBoard2dObjects
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
int m_raytrace_nrsamples_refractions
multilayer pads, usually with holes
Implementation of conversion functions that require both schematic and board internal units.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
std::vector< SFVEC2F > m_raytrace_lightSphericalCoords
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:236
const wxPoint & GetStart() const
Definition: track.h:116
static constexpr double IU_PER_MM
Mock up a conversion function.
static void SetDefaultNrRefractionsSamples(unsigned int aNrRefractions)
Definition: cmaterial.h:239
float GetStats_Med_Hole_Diameter3DU() const noexcept
GetStats_Med_Hole_Diameter3DU - Average diameter of holes.
CCOPPERNORMAL m_copper_normal_perturbator
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
MODEL_MATERIALS * get_3D_model_material(const S3DMODEL *a3DModel)
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
SFVEC3F m_raytrace_lightColorTop
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.
CSILKSCREENNORMAL m_silkscreen_normal_perturbator
void SetMaterial(const CMATERIAL *aMaterial)
Definition: cobject.h:72
A dummy block is used to fill the polygons.
Definition: cdummyblock.h:39
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
void insert3DViaHole(const VIA *aVia)
static void SetDefaultRefractionsLevel(unsigned int aRefractionLevel)
Definition: cmaterial.h:242
CPLASTICSHINENORMAL m_plastic_shine_normal_perturbator
void SetColor(SFVEC3F aObjColor)
Definition: croundseg.h:48
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
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
S3D_CACHE.
Definition: 3d_cache.h:54
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
void SetNormalPerturbator(const CPROCEDURALGENERATOR *aPerturbator)
Definition: cmaterial.h:308
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
CMETALBRUSHEDNORMAL m_brushed_metal_normal_perturbator
const CBVHCONTAINER2D * GetPlatedPads_Front() const noexcept
#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.
const void SetBoardItem(BOARD_ITEM *aBoardItem)
Definition: cobject.h:69
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
FOOTPRINT_ATTR_T
Enum FOOTPRINT_ATTR_T is the set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttrib...
Definition: footprint.h:67
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
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:664
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
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:136
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:406
void SetColor(const SFVEC3F &aColor)
Definition: ctriangle.cpp:156
void add_3D_models(CCONTAINER &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
const wxSize & GetDrillSize() const
Definition: pad.h:236
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.
SFVEC4F m_BgColorTop
background top color
float GetLayerBottomZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerBottomZpos3DU - Get the bottom z position.
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
const CBVHCONTAINER2D * GetPlatedPads_Back() const noexcept
#define NULL
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in a variety of units (the basic call r...
Definition: pad.h:334
int GetHolePlatingThicknessBIU() const noexcept
GetCopperThicknessBIU - Get the current copper layer thickness.
void createItemsFromContainer(const CBVHCONTAINER2D *aContainer2d, PCB_LAYER_ID aLayer_id, const CMATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
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 ...
Definition: track.cpp:170
SHAPE_POLY_SET.
Use all material properties from model file.
void SetModelTransparency(float aModelTransparency)
Definition: cobject.h:80
FOOTPRINTS & Footprints()
Definition: board.h:283
void load_3D_models(CCONTAINER &aDstContainer, bool aSkipMaterialInformation)
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: cmaterial.h:338
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.
virtual void Clear()
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
const CBVHCONTAINER2D & GetThroughHole_Inner() const noexcept
GetThroughHole_Inner - Get the ThroughHole container.
unsigned int m_stats_converted_roundsegment2d_to_roundsegment
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
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
CPLATEDCOPPERNORMAL m_platedcopper_normal_perturbator
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
int m_raytrace_recursivelevel_reflections
SFVEC4F GetItemColor(int aItemId) const
GetItemColor - 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:195
A vertical cylinder.
Definition: ccylinder.h:38
BOARD_ADAPTER & m_boardAdapter
settings refrence in use for this render
const CBVHCONTAINER2D & GetThroughHole_Outer_Ring() const noexcept
GetThroughHole_Outer_Ring - Get the ThroughHole container that include the width of the annular ring.
const SFVEC3F & Min() const
Function Min return the minimun vertex pointer.
Definition: cbbox.h:204
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static void SetDefaultNrReflectionsSamples(unsigned int aNrReflections)
Definition: cmaterial.h:240
float GetTransparency() const
Definition: cmaterial.h:267
void ResetStats()
Definition: cobject.h:122
void Add(COBJECT2D *aObject)
Definition: ccontainer2d.h:52
Implements a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_T...
CSOLDERMASKNORMAL m_solder_mask_normal_perturbator
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
GetLayerColor - get the technical color of a layer.
const int scale
bool ShouldFPBeDisplayed(FOOTPRINT_ATTR_T aFPAttributes) const
ShouldFPBeDisplayed - Test if footprint should be displayed in relation to attributes and the flags.
Meta control for all vias opacity/visibility.
const SFVEC3F & GetBoardCenter3DU() const noexcept
GetBoardCenter - the board center position in 3d units.
SFVEC2F GetExtent() const
Function GetExtent.
Definition: cbbox2d.cpp:126
struct C3D_RENDER_RAYTRACING::@3 m_materials
bool m_reloadRequested
!TODO: this must be reviewed in order to flag change types
wxPoint GetPosition() const override
Definition: pad.h:167
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:154
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:186
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
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
SFVEC4F m_CopperColor
in realistic mode: copper 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:139
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
void SetCastShadows(bool aCastShadow)
Definition: clight.h:57
static void SetDefaultReflectionsLevel(unsigned int aReflectionLevel)
Definition: cmaterial.h:243
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
SphericalToCartesian.
Definition: 3d_math.h:43
void ResetStats()
Definition: cobject2d.h:135
VIATYPE GetViaType() const
Definition: track.h:384
float GetModulesZcoord3DIU(bool aIsFlipped) const
GetModulesZcoord3DIU - Get the position of the footprint in 3d integer units considering if it is fli...
Defines math related functions.
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
CCONTAINER2D * m_outlineBoard2dObjects
static float TransparencyControl(float aGrayColorValue, float aTransparency)
TransparencyAlphaControl Perform an interpolation step to easy control the transparency based on the ...
const SFVEC2F & GetCentroid() const
Definition: cobject2d.h:123
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
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 BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
Definition: pad.h:59
int m_raytrace_recursivelevel_refractions
const LIST_OBJECT2D & GetList() const
Definition: ccontainer2d.h:69
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:39
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:88
TRACKS & Tracks()
Definition: board.h:280
Definition: track.h:83
SFVEC3F m_Specular
Definition: c3dmodel.h:42
void insert3DPadHole(const PAD *aPad)
int m_raytrace_nrsamples_reflections