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