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