KiCad PCB EDA Suite
Loading...
Searching...
No Matches
raytracing/create_scene.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2022 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright (C) 2015-2024 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27#include "shapes3D/plane_3d.h"
33#include "shapes2D/ring_2d.h"
34#include "shapes2D/polygon_2d.h"
38#include "3d_fastmath.h"
39#include "3d_math.h"
40
41#include <board.h>
42#include <footprint.h>
43#include <fp_lib_table.h>
44#include <eda_3d_viewer_frame.h>
45#include <project_pcb.h>
46
47#include <base_units.h>
48#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
49
58static float TransparencyControl( float aGrayColorValue, float aTransparency )
59{
60 const float aaa = aTransparency * aTransparency * aTransparency;
61
62 // 1.00-1.05*(1.0-x)^3
63 float ca = 1.0f - aTransparency;
64 ca = 1.00f - 1.05f * ca * ca * ca;
65
66 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
67}
68
72#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
73
74
76{
79
82
83 double mmTo3Dunits = pcbIUScale.IU_PER_MM * m_boardAdapter.BiuTo3dUnits();
84
86 {
87 m_boardMaterial = BOARD_NORMAL( 0.40f * mmTo3Dunits );
88 m_copperMaterial = COPPER_NORMAL( 4.0f * mmTo3Dunits, &m_boardMaterial );
89 m_platedCopperMaterial = PLATED_COPPER_NORMAL( 0.5f * mmTo3Dunits );
91 m_plasticMaterial = PLASTIC_NORMAL( 0.05f * mmTo3Dunits );
92 m_shinyPlasticMaterial = PLASTIC_SHINE_NORMAL( 0.1f * mmTo3Dunits );
93 m_brushedMetalMaterial = BRUSHED_METAL_NORMAL( 0.05f * mmTo3Dunits );
94 m_silkScreenMaterial = SILK_SCREEN_NORMAL( 0.25f * mmTo3Dunits );
95 }
96
97 // http://devernay.free.fr/cours/opengl/materials.html
98 // Copper
99 const SFVEC3F copperSpecularLinear =
100 ConvertSRGBToLinear( glm::clamp( (SFVEC3F) m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
101 SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) ) );
102
105 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
106
108 m_materials.m_Copper.SetGenerator( &m_platedCopperMaterial );
109
110 m_materials.m_NonPlatedCopper = BLINN_PHONG_MATERIAL(
111 ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ), SFVEC3F( 0.0f, 0.0f, 0.0f ),
112 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
113
115 m_materials.m_NonPlatedCopper.SetGenerator( &m_copperMaterial );
116
120 SFVEC3F( 0.0f, 0.0f, 0.0f ),
124 0.10f * 128.0f, 0.0f, 0.0f );
125
127 SFVEC3F( 0.0f, 0.0f, 0.0f ),
128 glm::clamp( ( ( SFVEC3F )( 1.0f ) - ConvertSRGBToLinear(
130 SFVEC3F( 0.0f ), SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
131
133 m_materials.m_SilkS.SetGenerator( &m_silkScreenMaterial );
134
135 // Assume that SolderMaskTop == SolderMaskBot
136 const float solderMask_gray =
139 / 3.0f;
140
141 const float solderMask_transparency = TransparencyControl( solderMask_gray,
143
144 m_materials.m_SolderMask = BLINN_PHONG_MATERIAL(
146 SFVEC3F( 0.0f, 0.0f, 0.0f ),
147 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
148 solderMask_transparency, 0.16f );
149
150 m_materials.m_SolderMask.SetCastShadows( true );
151 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
152
154 m_materials.m_SolderMask.SetGenerator( &m_solderMaskMaterial );
155
156 m_materials.m_EpoxyBoard =
157 BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f,
158 10.0f / 255.0f ) ),
159 SFVEC3F( 0.0f, 0.0f, 0.0f ),
160 ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f, 8.0f / 255.0f,
161 10.0f / 255.0f ) ),
162 0.1f * 128.0f, 1.0f - m_boardAdapter.m_BoardBodyColor.a, 0.0f );
163
164 m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
165
167 m_materials.m_EpoxyBoard.SetGenerator( &m_boardMaterial );
168
170
171 m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ),
172 ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
173 0.10f * 128.0f, 1.0f, 0.50f );
174 m_materials.m_Floor.SetCastShadows( false );
175 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
176}
177
178
179void RENDER_3D_RAYTRACE_BASE::createObject( CONTAINER_3D& aDstContainer, const OBJECT_2D* aObject2D,
180 float aZMin, float aZMax, const MATERIAL* aMaterial,
181 const SFVEC3F& aObjColor )
182{
183 switch( aObject2D->GetObjectType() )
184 {
185 case OBJECT_2D_TYPE::DUMMYBLOCK:
186 {
188
189 XY_PLANE* objPtr;
190 objPtr = new XY_PLANE( BBOX_3D(
191 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
192 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
193 objPtr->SetMaterial( aMaterial );
194 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
195 aDstContainer.Add( objPtr );
196
197 objPtr = new XY_PLANE( BBOX_3D(
198 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
199 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
200 objPtr->SetMaterial( aMaterial );
201 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
202 aDstContainer.Add( objPtr );
203 break;
204 }
205
206 case OBJECT_2D_TYPE::ROUNDSEG:
207 {
209
210 const ROUND_SEGMENT_2D* aRoundSeg2D = static_cast<const ROUND_SEGMENT_2D*>( aObject2D );
211 ROUND_SEGMENT* objPtr = new ROUND_SEGMENT( *aRoundSeg2D, aZMin, aZMax );
212 objPtr->SetMaterial( aMaterial );
213 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
214 aDstContainer.Add( objPtr );
215 break;
216 }
217
218 default:
219 {
220 LAYER_ITEM* objPtr = new LAYER_ITEM( aObject2D, aZMin, aZMax );
221 objPtr->SetMaterial( aMaterial );
222 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
223 aDstContainer.Add( objPtr );
224 break;
225 }
226 }
227}
228
229
231 PCB_LAYER_ID aLayer_id,
232 const MATERIAL* aMaterialLayer,
233 const SFVEC3F& aLayerColor,
234 float aLayerZOffset )
235{
236 if( aContainer2d == nullptr )
237 return;
238
240 bool isSilk = aLayer_id == B_SilkS || aLayer_id == F_SilkS;
241 const LIST_OBJECT2D& listObject2d = aContainer2d->GetList();
242
243 if( listObject2d.size() == 0 )
244 return;
245
246 for( const OBJECT_2D* object2d_A : listObject2d )
247 {
248 // not yet used / implemented (can be used in future to clip the objects in the
249 // board borders
250 OBJECT_2D* object2d_C = CSGITEM_FULL;
251
252 std::vector<const OBJECT_2D*>* object2d_B = CSGITEM_EMPTY;
253
254 object2d_B = new std::vector<const OBJECT_2D*>();
255
256 // Subtract holes but not in SolderPaste
257 // (can be added as an option in future)
258 if( !( aLayer_id == B_Paste || aLayer_id == F_Paste ) )
259 {
260 // Check if there are any layerhole that intersects this object
261 // Eg: a segment is cut by a via hole or THT hole.
263
264 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
265 {
266 const BVH_CONTAINER_2D* holes2d = layerHolesMap.at( aLayer_id );
267
268 CONST_LIST_OBJECT2D intersecting;
269
270 holes2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
271
272 for( const OBJECT_2D* hole2d : intersecting )
273 object2d_B->push_back( hole2d );
274 }
275
276 // Check if there are any THT that intersects this object. If we're processing a silk
277 // layer and the flag is set, then clip the silk at the outer edge of the annular ring,
278 // rather than the at the outer edge of the copper plating.
279 const BVH_CONTAINER_2D& throughHoleOuter =
282
283 if( !throughHoleOuter.GetList().empty() )
284 {
285 CONST_LIST_OBJECT2D intersecting;
286
287 throughHoleOuter.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
288
289 for( const OBJECT_2D* hole2d : intersecting )
290 object2d_B->push_back( hole2d );
291 }
292 }
293
294 if( !m_antioutlineBoard2dObjects->GetList().empty() )
295 {
296 CONST_LIST_OBJECT2D intersecting;
297
299 intersecting );
300
301 for( const OBJECT_2D* obj : intersecting )
302 object2d_B->push_back( obj );
303 }
304
306
308 && ( ( aLayer_id == B_SilkS && mapLayers.find( B_Mask ) != mapLayers.end() )
309 || ( aLayer_id == F_SilkS && mapLayers.find( F_Mask ) != mapLayers.end() ) ) )
310 {
311 const PCB_LAYER_ID maskLayer = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
312
313 const BVH_CONTAINER_2D* containerMaskLayer2d = mapLayers.at( maskLayer );
314
315 CONST_LIST_OBJECT2D intersecting;
316
317 if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
318 containerMaskLayer2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
319
320 for( const OBJECT_2D* obj2d : intersecting )
321 object2d_B->push_back( obj2d );
322 }
323
324 if( object2d_B->empty() )
325 {
326 delete object2d_B;
327 object2d_B = CSGITEM_EMPTY;
328 }
329
330 if( ( object2d_B == CSGITEM_EMPTY ) && ( object2d_C == CSGITEM_FULL ) )
331 {
332 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
333 m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
334 m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
335 objPtr->SetMaterial( aMaterialLayer );
336 objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
337 m_objectContainer.Add( objPtr );
338 }
339 else
340 {
341 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, object2d_C,
342 object2d_A->GetBoardItem() );
344
345 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
346 m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
347 m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
348
349 objPtr->SetMaterial( aMaterialLayer );
350 objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
351
352 m_objectContainer.Add( objPtr );
353 }
354 }
355}
356
357
358extern void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline );
359
360
361void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter,
362 bool aOnlyLoadCopperAndShapes )
363{
364 m_reloadRequested = false;
365
366 m_modelMaterialMap.clear();
367
370
371 int64_t stats_startReloadTime = GetRunningMicroSecs();
372
373 if( !aOnlyLoadCopperAndShapes )
374 {
375 m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
376
378 m_camera.SetBoardLookAtPos( camera_pos );
379 }
380
383
385
386 if( aStatusReporter )
387 aStatusReporter->Report( _( "Load Raytracing: board" ) );
388
389 // Create and add the outline board
392
395
396 std::bitset<LAYER_3D_END> layerFlags = m_boardAdapter.GetVisibleLayers();
397
398 if( !aOnlyLoadCopperAndShapes )
399 {
400 const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
401
402 if( outlineCount > 0 )
403 {
404 float divFactor = 0.0f;
405
407 divFactor = m_boardAdapter.GetAverageViaHoleDiameter() * 18.0f;
408 else if( m_boardAdapter.GetHoleCount() )
409 divFactor = m_boardAdapter.GetAverageHoleDiameter() * 8.0f;
410
412
413 // Calculate an antiboard outline
414 SHAPE_POLY_SET antiboardPoly;
415
417
418 antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
419 antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
420
421 for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
422 {
425 *m_boardAdapter.GetBoard(), ii );
426 }
427
429
430 boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
431
432 for( int ii = 0; ii < outlineCount; ii++ )
433 {
435 m_boardAdapter.BiuTo3dUnits(), divFactor,
436 *m_boardAdapter.GetBoard(), ii );
437 }
438
439 if( layerFlags.test( LAYER_3D_BOARD ) )
440 {
441 const LIST_OBJECT2D& listObjects = m_outlineBoard2dObjects->GetList();
442
443 for( const OBJECT_2D* object2d_A : listObjects )
444 {
445 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
446
447 // Check if there are any THT that intersects this outline object part
448 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
449 {
450 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetTH_ODs();
451 CONST_LIST_OBJECT2D intersecting;
452
453 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
454
455 for( const OBJECT_2D* hole : intersecting )
456 {
457 if( object2d_A->Intersects( hole->GetBBox() ) )
458 object2d_B->push_back( hole );
459 }
460 }
461
462 if( !m_antioutlineBoard2dObjects->GetList().empty() )
463 {
464 CONST_LIST_OBJECT2D intersecting;
465
467 intersecting );
468
469 for( const OBJECT_2D* obj : intersecting )
470 object2d_B->push_back( obj );
471 }
472
473 if( object2d_B->empty() )
474 {
475 delete object2d_B;
476 object2d_B = CSGITEM_EMPTY;
477 }
478
479 if( object2d_B == CSGITEM_EMPTY )
480 {
481 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
484
485 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
487 m_objectContainer.Add( objPtr );
488 }
489 else
490 {
491
492 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
495
497
498 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
501
502 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
504 m_objectContainer.Add( objPtr );
505 }
506 }
507
508 // Add cylinders of the board body to container
509 // Note: This is actually a workaround for the holes in the board.
510 // The issue is because if a hole is in a border of a divided polygon ( ex
511 // a polygon or dummy block) it will cut also the render of the hole.
512 // So this will add a full hole.
513 // In fact, that is not need if the hole have copper.
514 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
515 {
516 const LIST_OBJECT2D& holeList = m_boardAdapter.GetTH_ODs().GetList();
517
518 for( const OBJECT_2D* hole2d : holeList )
519 {
520 if( !m_antioutlineBoard2dObjects->GetList().empty() )
521 {
522 CONST_LIST_OBJECT2D intersecting;
523
525 intersecting );
526
527 // Do not add cylinder if it intersects the edge of the board
528 if( !intersecting.empty() )
529 continue;
530 }
531
532 switch( hole2d->GetObjectType() )
533 {
534 case OBJECT_2D_TYPE::FILLED_CIRCLE:
535 {
536 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
537
538 CYLINDER* objPtr = new CYLINDER( hole2d->GetCentroid(),
541 radius );
542
543 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
545
546 m_objectContainer.Add( objPtr );
547 }
548 break;
549
550 default:
551 break;
552 }
553 }
554 }
555 }
556 }
557 }
558
559 if( aStatusReporter )
560 aStatusReporter->Report( _( "Load Raytracing: layers" ) );
561
562 // Add layers maps (except B_Mask and F_Mask)
563 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry : m_boardAdapter.GetLayerMap() )
564 {
565 const PCB_LAYER_ID layer_id = entry.first;
566 const BVH_CONTAINER_2D* container2d = entry.second;
567
568 // Only process layers that exist
569 if( !container2d )
570 continue;
571
572 if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
573 continue;
574
575 // Mask layers are not processed here because they are a special case
576 if( layer_id == B_Mask || layer_id == F_Mask )
577 continue;
578
579 MATERIAL* materialLayer = &m_materials.m_SilkS;
580 SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
581
582 switch( layer_id )
583 {
584 case B_Adhes:
585 case F_Adhes:
586 break;
587
588 case B_Paste:
589 case F_Paste:
590 materialLayer = &m_materials.m_Paste;
592 break;
593
594 case B_SilkS:
595 materialLayer = &m_materials.m_SilkS;
597 break;
598
599 case F_SilkS:
600 materialLayer = &m_materials.m_SilkS;
602 break;
603
604 case Dwgs_User:
606 break;
607
608 case Cmts_User:
610 break;
611
612 case Eco1_User:
613 layerColor = m_boardAdapter.m_ECO1Color;
614 break;
615
616 case Eco2_User:
617 layerColor = m_boardAdapter.m_ECO2Color;
618 break;
619
620 case B_CrtYd:
621 case F_CrtYd:
622 break;
623
624 case B_Fab:
625 case F_Fab:
626 break;
627
628 default:
630 {
631 layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
632 materialLayer = &m_materials.m_NonPlatedCopper;
633 }
634 else
635 {
636 layerColor = m_boardAdapter.m_CopperColor;
637 materialLayer = &m_materials.m_Copper;
638 }
639
640 break;
641 }
642
643 createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
644 } // for each layer on map
645
646 // Create plated copper
648 {
652
656 }
657
658 if( !aOnlyLoadCopperAndShapes )
659 {
660 // Add Mask layer
661 // Solder mask layers are "negative" layers so the elements that we have in the container
662 // should remove the board outline. We will check for all objects in the outline if it
663 // intersects any object in the layer container and also any hole.
664 if( ( layerFlags.test( LAYER_3D_SOLDERMASK_TOP )
665 || layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
666 && !m_outlineBoard2dObjects->GetList().empty() )
667 {
668 const MATERIAL* materialLayer = &m_materials.m_SolderMask;
669
670 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry : m_boardAdapter.GetLayerMap() )
671 {
672 const PCB_LAYER_ID layer_id = entry.first;
673 const BVH_CONTAINER_2D* container2d = entry.second;
674
675 // Only process layers that exist
676 if( !container2d )
677 continue;
678
679 // Only get the Solder mask layers (and only if the board has them)
680 if( layer_id == F_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_TOP ) )
681 continue;
682
683 if( layer_id == B_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
684 continue;
685
686 // Only Mask layers are processed here because they are negative layers
687 if( layer_id != F_Mask && layer_id != B_Mask )
688 continue;
689
690 SFVEC3F layerColor;
691
692 if( layer_id == B_Mask )
694 else
696
697 const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
698 const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
699
700 // Get the outline board objects
701 for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
702 {
703 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
704
705 // Check if there are any THT that intersects this outline object part
706 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
707 {
708 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetTH_ODs();
709 CONST_LIST_OBJECT2D intersecting;
710
711 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
712
713 for( const OBJECT_2D* hole : intersecting )
714 {
715 if( object2d_A->Intersects( hole->GetBBox() ) )
716 object2d_B->push_back( hole );
717 }
718 }
719
720 // Check if there are any objects in the layer to subtract with the current
721 // object
722 if( !container2d->GetList().empty() )
723 {
724 CONST_LIST_OBJECT2D intersecting;
725
726 container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
727
728 for( const OBJECT_2D* obj : intersecting )
729 object2d_B->push_back( obj );
730 }
731
732 if( object2d_B->empty() )
733 {
734 delete object2d_B;
735 object2d_B = CSGITEM_EMPTY;
736 }
737
738 if( object2d_B == CSGITEM_EMPTY )
739 {
740#if 0
741 createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
742 materialLayer, layerColor );
743#else
744 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
745
746 objPtr->SetMaterial( materialLayer );
747 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
748
749 m_objectContainer.Add( objPtr );
750#endif
751 }
752 else
753 {
754 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
756 object2d_A->GetBoardItem() );
757
759
760 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
761 objPtr->SetMaterial( materialLayer );
762 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
763
764 m_objectContainer.Add( objPtr );
765 }
766 }
767 }
768 }
769
771 }
772
773#ifdef PRINT_STATISTICS_3D_VIEWER
774 int64_t stats_endConvertTime = GetRunningMicroSecs();
775 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
776#endif
777
778 if( aStatusReporter )
779 aStatusReporter->Report( _( "Loading 3D models..." ) );
780
781 load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
782
783#ifdef PRINT_STATISTICS_3D_VIEWER
784 int64_t stats_endLoad3DmodelsTime = GetRunningMicroSecs();
785#endif
786
787 if( !aOnlyLoadCopperAndShapes )
788 {
789 // Add floor
791 {
792 BBOX_3D boardBBox = m_boardAdapter.GetBBox();
793
794 if( boardBBox.IsInitialized() )
795 {
796 boardBBox.Scale( 3.0f );
797
798 if( m_objectContainer.GetList().size() > 0 )
799 {
800 BBOX_3D containerBBox = m_objectContainer.GetBBox();
801
802 containerBBox.Scale( 1.3f );
803
804 const SFVEC3F centerBBox = containerBBox.GetCenter();
805
806 // Floor triangles
807 const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
808
809 const SFVEC3F v1 =
810 SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
811 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
812
813 const SFVEC3F v3 =
814 SFVEC3F( +RANGE_SCALE_3D * 4.0f, +RANGE_SCALE_3D * 4.0f, minZ )
815 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
816
817 const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
818 const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
819
821
822 TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
823 TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
824
825 m_objectContainer.Add( newTriangle1 );
826 m_objectContainer.Add( newTriangle2 );
827
828 newTriangle1->SetMaterial( &m_materials.m_Floor );
829 newTriangle2->SetMaterial( &m_materials.m_Floor );
830
831 newTriangle1->SetColor( floorColor );
832 newTriangle2->SetColor( floorColor );
833
834 // Ceiling triangles
835 const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
836
837 const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
838 const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
839 const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
840 const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
841
842 TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
843 TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
844
845 m_objectContainer.Add( newTriangle3 );
846 m_objectContainer.Add( newTriangle4 );
847
848 newTriangle3->SetMaterial( &m_materials.m_Floor );
849 newTriangle4->SetMaterial( &m_materials.m_Floor );
850
851 newTriangle3->SetColor( floorColor );
852 newTriangle4->SetColor( floorColor );
853 }
854 }
855 }
856
857 // Init initial lights
858 for( LIGHT* light : m_lights )
859 delete light;
860
861 m_lights.clear();
862
863 auto IsColorZero =
864 []( const SFVEC3F& aSource )
865 {
866 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
867 && ( aSource.b < ( 1.0f / 255.0f ) ) );
868 };
869
870 SFVEC3F cameraLightColor =
872 SFVEC3F topLightColor =
874 SFVEC3F bottomLightColor =
876
877 m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), cameraLightColor );
879
880 if( !IsColorZero( cameraLightColor ) )
881 m_lights.push_back( m_cameraLight );
882
883 const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
884
885 if( !IsColorZero( topLightColor ) )
886 {
887 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
888 +RANGE_SCALE_3D * 2.0f ),
889 topLightColor ) );
890 }
891
892 if( !IsColorZero( bottomLightColor ) )
893 {
894 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
895 -RANGE_SCALE_3D * 2.0f ),
896 bottomLightColor ) );
897 }
898
899 for( size_t i = 0; i < m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
900 {
901 SFVEC3F lightColor =
903
904 if( !IsColorZero( lightColor ) )
905 {
907
908 m_lights.push_back( new DIRECTIONAL_LIGHT(
909 SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
910 lightColor ) );
911 }
912 }
913 }
914
915 // Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
916 // class would require reimplementing bounding box calculation (feel free to do this if you
917 // have time and patience).
918 if( m_objectContainer.GetList().size() > 0 )
919 {
920 float ratio =
922
923 float max_zoom = CAMERA::DEFAULT_MAX_ZOOM * ratio;
924 float min_zoom = static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
925 / -m_camera.GetCameraInitPos().z );
926
927 if( min_zoom > max_zoom )
928 std::swap( min_zoom, max_zoom );
929
930 float zoom_ratio = max_zoom / min_zoom;
931
932 // Set the minimum number of zoom 'steps' between max and min.
933 int steps = 3 * 3;
934 steps -= static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
935 steps = std::max( steps, 0 );
936
937 // Resize max and min zoom to accomplish the number of steps.
938 float increased_zoom = pow( 1.26f, steps / 2 );
939 max_zoom *= increased_zoom;
940 min_zoom /= increased_zoom;
941
942 if( steps & 1 )
943 min_zoom /= 1.26f;
944
945 min_zoom = std::min( min_zoom, 1.0f );
946
947 m_camera.SetMaxZoom( max_zoom );
948 m_camera.SetMinZoom( min_zoom );
949 }
950
951 // Create an accelerator
952 delete m_accelerator;
953 m_accelerator = new BVH_PBRT( m_objectContainer, 8, SPLITMETHOD::MIDDLE );
954
955 if( aStatusReporter )
956 {
957 // Calculation time in seconds
958 double calculation_time = (double) ( GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
959
960 aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
961 }
962}
963
964
966{
967 PCB_LAYER_ID top_layer, bottom_layer;
968 int radiusBUI = ( aVia->GetDrillValue() / 2 );
969
970 aVia->LayerPair( &top_layer, &bottom_layer );
971
972 float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
974
975 float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
977
978 const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
979 -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
980
981 RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
983 * m_boardAdapter.BiuTo3dUnits(), *aVia );
984
986
987 LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
988
989 objPtr->SetMaterial( &m_materials.m_Copper );
991
992 m_objectContainer.Add( objPtr );
993}
994
995
997{
998 const OBJECT_2D* object2d_A = nullptr;
999
1001 const VECTOR2I drillsize = aPad->GetDrillSize();
1002 const bool hasHole = drillsize.x && drillsize.y;
1003
1004 if( !hasHole )
1005 return;
1006
1007 CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1008
1009 const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
1011
1012 const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
1014
1015 if( drillsize.x == drillsize.y ) // usual round hole
1016 {
1019
1020 int innerRadius = drillsize.x / 2;
1021 int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1022
1023 RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1024 outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1025
1027
1028 object2d_A = ring;
1029
1030 // If the object (ring) is intersected by an antioutline board,
1031 // it will use instead a CSG of two circles.
1032 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1033 {
1035 antiOutlineIntersectionList );
1036 }
1037
1038 if( !antiOutlineIntersectionList.empty() )
1039 {
1040 FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1041 center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1042
1043 FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1044 center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1045 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1046 object2d_B->push_back( innerCircle );
1047
1048 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1049 *aPad );
1050
1052 m_containerWithObjectsToDelete.Add( innerCircle );
1053 m_containerWithObjectsToDelete.Add( outterCircle );
1054
1055 object2d_A = itemCSG2d;
1056 }
1057 }
1058 else // Oblong hole
1059 {
1060 VECTOR2I ends_offset;
1061 int width;
1062
1063 if( drillsize.x > drillsize.y ) // Horizontal oval
1064 {
1065 ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1066 width = drillsize.y;
1067 }
1068 else // Vertical oval
1069 {
1070 ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1071 width = drillsize.x;
1072 }
1073
1074 RotatePoint( ends_offset, aPad->GetOrientation() );
1075
1076 VECTOR2I start = VECTOR2I( aPad->GetPosition() ) + ends_offset;
1077 VECTOR2I end = VECTOR2I( aPad->GetPosition() ) - ends_offset;
1078
1079 ROUND_SEGMENT_2D* innerSeg =
1081 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1083 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1084 width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1085
1086 ROUND_SEGMENT_2D* outerSeg =
1088 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1090 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1091 ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1092 * m_boardAdapter.BiuTo3dUnits(), *aPad );
1093
1094 // NOTE: the round segment width is the "diameter", so we double the thickness
1095 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1096 object2d_B->push_back( innerSeg );
1097
1098 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1099
1103
1104 object2d_A = itemCSG2d;
1105
1106 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1107 {
1109 antiOutlineIntersectionList );
1110 }
1111 }
1112
1113 if( object2d_A )
1114 {
1115 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1116
1117 // Check if there are any other THT that intersects this hole
1118 // It will use the non inflated holes
1119 if( !m_boardAdapter.GetTH_IDs().GetList().empty() )
1120 {
1121 CONST_LIST_OBJECT2D intersecting;
1122
1123 m_boardAdapter.GetTH_IDs().GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
1124
1125 for( const OBJECT_2D* hole2d : intersecting )
1126 {
1127 if( object2d_A->Intersects( hole2d->GetBBox() ) )
1128 object2d_B->push_back( hole2d );
1129 }
1130 }
1131
1132 for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1133 object2d_B->push_back( obj );
1134
1135 if( object2d_B->empty() )
1136 {
1137 delete object2d_B;
1138 object2d_B = CSGITEM_EMPTY;
1139 }
1140
1141 if( object2d_B == CSGITEM_EMPTY )
1142 {
1143 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1144
1145 objPtr->SetMaterial( &m_materials.m_Copper );
1146 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1147 m_objectContainer.Add( objPtr );
1148 }
1149 else
1150 {
1151 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1152 *aPad );
1153
1155
1156 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1157
1158 objPtr->SetMaterial( &m_materials.m_Copper );
1159 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1160
1161 m_objectContainer.Add( objPtr );
1162 }
1163 }
1164}
1165
1166
1168{
1169 if( !m_boardAdapter.GetBoard() )
1170 return;
1171
1172 // Insert plated vertical holes inside the board
1173
1174 // Insert vias holes (vertical cylinders)
1175 for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1176 {
1177 if( track->Type() == PCB_VIA_T )
1178 {
1179 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1180 insertHole( via );
1181 }
1182 }
1183
1184 // Insert pads holes (vertical cylinders)
1185 for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1186 {
1187 for( PAD* pad : footprint->Pads() )
1188 {
1189 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1190 insertHole( pad );
1191 }
1192 }
1193}
1194
1195
1196void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMaterialInformation )
1197{
1198 if( !m_boardAdapter.GetBoard() )
1199 return;
1200
1205 {
1206 return;
1207 }
1208
1209 // Go for all footprints
1211 {
1212 if( !fp->Models().empty()
1213 && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1214 {
1215 double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1216
1217 VECTOR2I pos = fp->GetPosition();
1218
1219 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1220
1221 fpMatrix = glm::translate( fpMatrix,
1223 -pos.y * m_boardAdapter.BiuTo3dUnits(),
1224 zpos ) );
1225
1226 if( !fp->GetOrientation().IsZero() )
1227 {
1228 fpMatrix = glm::rotate( fpMatrix, (float) fp->GetOrientation().AsRadians(),
1229 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1230 }
1231
1232 if( fp->IsFlipped() )
1233 {
1234 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1235
1236 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1237 }
1238
1239 const double modelunit_to_3d_units_factor =
1241
1242 fpMatrix = glm::scale(
1243 fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1244 modelunit_to_3d_units_factor ) );
1245
1246 BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( fp );
1247
1248 // Get the list of model files for this model
1250 auto sM = fp->Models().begin();
1251 auto eM = fp->Models().end();
1252
1253 wxString libraryName = fp->GetFPID().GetLibNickname();
1254
1255 wxString footprintBasePath = wxEmptyString;
1257 {
1258 try
1259 {
1260 // FindRow() can throw an exception
1261 const FP_LIB_TABLE_ROW* fpRow =
1263 ->FindRow( libraryName, false );
1264
1265 if( fpRow )
1266 footprintBasePath = fpRow->GetFullURI( true );
1267 }
1268 catch( ... )
1269 {
1270 // Do nothing if the libraryName is not found in lib table
1271 }
1272 }
1273
1274 while( sM != eM )
1275 {
1276 if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
1277 && ( sM->m_Show && !sM->m_Filename.empty() ) )
1278 {
1279 // get it from cache
1280 const S3DMODEL* modelPtr =
1281 cacheMgr->GetModel( sM->m_Filename, footprintBasePath );
1282
1283 // only add it if the return is not NULL.
1284 if( modelPtr )
1285 {
1286 glm::mat4 modelMatrix = fpMatrix;
1287
1288 modelMatrix = glm::translate( modelMatrix,
1289 SFVEC3F( sM->m_Offset.x, sM->m_Offset.y, sM->m_Offset.z ) );
1290
1291 modelMatrix = glm::rotate( modelMatrix,
1292 (float) -( sM->m_Rotation.z / 180.0f ) * glm::pi<float>(),
1293 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1294
1295 modelMatrix = glm::rotate( modelMatrix,
1296 (float) -( sM->m_Rotation.y / 180.0f ) * glm::pi<float>(),
1297 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1298
1299 modelMatrix = glm::rotate( modelMatrix,
1300 (float) -( sM->m_Rotation.x / 180.0f ) * glm::pi<float>(),
1301 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1302
1303 modelMatrix = glm::scale( modelMatrix,
1304 SFVEC3F( sM->m_Scale.x, sM->m_Scale.y, sM->m_Scale.z ) );
1305
1306 addModels( aDstContainer, modelPtr, modelMatrix, (float) sM->m_Opacity,
1307 aSkipMaterialInformation, boardItem );
1308 }
1309 }
1310
1311 ++sM;
1312 }
1313 }
1314 }
1315}
1316
1317
1319{
1320 MODEL_MATERIALS* materialVector;
1321
1322 // Try find if the materials already exists in the map list
1323 if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1324 {
1325 // Found it, so get the pointer
1326 materialVector = &m_modelMaterialMap[a3DModel];
1327 }
1328 else
1329 {
1330 // Materials was not found in the map, so it will create a new for
1331 // this model.
1332
1333 m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1334 materialVector = &m_modelMaterialMap[a3DModel];
1335
1336 materialVector->resize( a3DModel->m_MaterialsSize );
1337
1338 for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1339 {
1340 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::NORMAL )
1341 {
1342 const SMATERIAL& material = a3DModel->m_Materials[imat];
1343
1344 // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1345
1346 float reflectionFactor = 0.0f;
1347
1348 if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1349 {
1350 reflectionFactor = glm::clamp(
1351 glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1352 0.5f );
1353 }
1354
1355 BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1356
1357 blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1358 ConvertSRGBToLinear( material.m_Emissive ),
1359 ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1360 material.m_Transparency, reflectionFactor );
1361
1363 {
1364 // Guess material type and apply a normal perturbator
1365 if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1366 && ( material.m_Shininess < 0.36f )
1367 && ( material.m_Transparency == 0.0f )
1368 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1369 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1370 < 0.15f )
1371 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1372 < 0.15f ) ) )
1373 {
1374 // This may be a black plastic..
1375 blinnMaterial.SetGenerator( &m_plasticMaterial );
1376 }
1377 else
1378 {
1379 if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1380 && ( material.m_Shininess < 0.30f )
1381 && ( material.m_Transparency == 0.0f )
1382 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1383 || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1384 || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1385 > 0.25f ) ) )
1386 {
1387 // This may be a color plastic ...
1388 blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1389 }
1390 else
1391 {
1392 if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1393 && ( material.m_Shininess > 0.35f )
1394 && ( material.m_Transparency == 0.0f )
1395 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1396 < 0.40f )
1397 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1398 < 0.40f )
1399 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1400 < 0.40f ) ) )
1401 {
1402 // This may be a brushed metal
1403 blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1404 }
1405 }
1406 }
1407 }
1408 }
1409 else
1410 {
1411 ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1412 SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1413 }
1414 }
1415 }
1416
1417 return materialVector;
1418}
1419
1420
1421void RENDER_3D_RAYTRACE_BASE::addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
1422 const glm::mat4& aModelMatrix, float aFPOpacity,
1423 bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem )
1424{
1425 // Validate a3DModel pointers
1426 wxASSERT( a3DModel != nullptr );
1427
1428 if( a3DModel == nullptr )
1429 return;
1430
1431 wxASSERT( a3DModel->m_Materials != nullptr );
1432 wxASSERT( a3DModel->m_Meshes != nullptr );
1433 wxASSERT( a3DModel->m_MaterialsSize > 0 );
1434 wxASSERT( a3DModel->m_MeshesSize > 0 );
1435 wxASSERT( aFPOpacity > 0.0f );
1436 wxASSERT( aFPOpacity <= 1.0f );
1437
1438 if( aFPOpacity > 1.0f )
1439 {
1440 aFPOpacity = 1.0f;
1441 }
1442
1443 if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1444 && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1445 {
1446 MODEL_MATERIALS* materialVector = nullptr;
1447
1448 if( !aSkipMaterialInformation )
1449 {
1450 materialVector = getModelMaterial( a3DModel );
1451 }
1452
1453 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1454
1455 for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1456 {
1457 const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1458
1459 // Validate the mesh pointers
1460 wxASSERT( mesh.m_Positions != nullptr );
1461 wxASSERT( mesh.m_FaceIdx != nullptr );
1462 wxASSERT( mesh.m_Normals != nullptr );
1463 wxASSERT( mesh.m_FaceIdxSize > 0 );
1464 wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1465
1466
1467 if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1468 && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1469 && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1470 && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1471 {
1472 float fpTransparency;
1473 const BLINN_PHONG_MATERIAL* blinn_material;
1474
1475 if( !aSkipMaterialInformation )
1476 {
1477 blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1478
1479 fpTransparency =
1480 1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1481 }
1482
1483 // Add all face triangles
1484 for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1485 {
1486 const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1487 const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1488 const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1489
1490 wxASSERT( idx0 < mesh.m_VertexSize );
1491 wxASSERT( idx1 < mesh.m_VertexSize );
1492 wxASSERT( idx2 < mesh.m_VertexSize );
1493
1494 if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1495 && ( idx2 < mesh.m_VertexSize ) )
1496 {
1497 const SFVEC3F& v0 = mesh.m_Positions[idx0];
1498 const SFVEC3F& v1 = mesh.m_Positions[idx1];
1499 const SFVEC3F& v2 = mesh.m_Positions[idx2];
1500
1501 const SFVEC3F& n0 = mesh.m_Normals[idx0];
1502 const SFVEC3F& n1 = mesh.m_Normals[idx1];
1503 const SFVEC3F& n2 = mesh.m_Normals[idx2];
1504
1505 // Transform vertex with the model matrix
1506 const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1507 const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1508 const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1509
1510 const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1511 const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1512 const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1513
1514 TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1515
1516 newTriangle->SetBoardItem( aBoardItem );
1517
1518 aDstContainer.Add( newTriangle );
1519
1520 if( !aSkipMaterialInformation )
1521 {
1522 newTriangle->SetMaterial( blinn_material );
1523 newTriangle->SetModelTransparency( fpTransparency );
1524
1525 if( mesh.m_Color == nullptr )
1526 {
1527 const SFVEC3F diffuseColor =
1528 a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1529
1530 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1531 newTriangle->SetColor( ConvertSRGBToLinear(
1532 MaterialDiffuseToColorCAD( diffuseColor ) ) );
1533 else
1534 newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1535 }
1536 else
1537 {
1538 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1539 {
1540 newTriangle->SetColor(
1542 mesh.m_Color[idx0] ) ),
1544 mesh.m_Color[idx1] ) ),
1546 mesh.m_Color[idx2] ) ) );
1547 }
1548 else
1549 {
1550 newTriangle->SetColor(
1551 ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1552 ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1553 ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1554 }
1555 }
1556 }
1557 }
1558 }
1559 }
1560 }
1561 }
1562}
Defines math related functions.
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
Defines math related functions.
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:140
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:147
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
Definition: 3d_math.h:43
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:58
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:66
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:379
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
SFVEC4F m_BgColorTop
background top color
SFVEC4F m_ECO2Color
const MAP_CONTAINER_2D_BASE & GetLayerHoleMap() const noexcept
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
Get the current polygon of the epoxy board.
bool IsFootprintShown(FOOTPRINT_ATTR_T aFPAttributes) const
Test if footprint should be displayed in relation to attributes and the flags.
const BBOX_3D & GetBBox() const noexcept
Get the board outling bounding box.
std::bitset< LAYER_3D_END > GetVisibleLayers() const
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
bool m_IsPreviewer
true if we're in a 3D preview panel, false for the standard 3D viewer
int GetHolePlatingThickness() const noexcept
Get the hole plating thickness (NB: in BOARD UNITS!).
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
const BVH_CONTAINER_2D & GetViaAnnuli() const noexcept
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
const BVH_CONTAINER_2D & GetTH_IDs() const noexcept
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
SFVEC4F GetColor(const COLOR4D &aColor) const
const BVH_CONTAINER_2D * GetPlatedPadsBack() const noexcept
float GetBackCopperThickness() const noexcept
SFVEC4F m_CopperColor
in realistic mode: copper color
float GetAverageViaHoleDiameter() const noexcept
SFVEC2F GetSphericalCoord(int i) const
unsigned int GetViaCount() const noexcept
const BOARD * GetBoard() const noexcept
const SFVEC3F & GetBoardCenter() const noexcept
The board center position in 3D units.
float GetFootprintZPos(bool aIsFlipped) const
Get the position of the footprint in 3d integer units considering if it is flipped or not.
float GetLayerTopZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the top z position.
const BVH_CONTAINER_2D & GetTH_ODs() const noexcept
const MAP_CONTAINER_2D_BASE & GetLayerMap() const noexcept
Get the map of containers that have the objects per layer.
EDA_3D_VIEWER_SETTINGS * m_Cfg
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
unsigned int GetHoleCount() const noexcept
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
const BVH_CONTAINER_2D * GetPlatedPadsFront() const noexcept
float GetFrontCopperThickness() const noexcept
Get the copper layer thicknesses (in 3D units).
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
float GetAverageHoleDiameter() const noexcept
SFVEC4F m_UserCommentsColor
SFVEC4F m_ECO1Color
SFVEC4F m_UserDrawingsColor
S3D_CACHE * Get3dCacheManager() const noexcept
Definition: board_adapter.h:85
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:281
const FOOTPRINTS & Footprints() const
Definition: board.h:322
const TRACKS & Tracks() const
Definition: board.h:320
PROJECT * GetProject() const
Definition: board.h:475
Procedural generation of the shiny brushed metal.
Definition: material.h:195
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
void SetMinZoom(float minZoom)
Definition: camera.h:224
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: camera.cpp:182
static const float DEFAULT_MAX_ZOOM
Definition: camera.h:106
void SetMaxZoom(float maxZoom)
Definition: camera.h:231
const SFVEC3F & GetCameraInitPos() const
Definition: camera.h:170
virtual void Clear()
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
const BBOX_3D & GetBBox() const
Definition: container_3d.h:63
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
const LIST_OBJECT & GetList() const
Definition: container_3d.h:59
Procedural generation of the copper normals.
Definition: material.h:76
A vertical cylinder.
Definition: cylinder_3d.h:38
void SetColor(SFVEC3F aObjColor)
Definition: cylinder_3d.h:48
A light source based only on a directional vector.
Definition: light.h:116
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
Make solid geometry for objects on layers.
Definition: layer_item_2d.h:80
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A base light class to derive to implement other light classes.
Definition: light.h:41
void SetCastShadows(bool aCastShadow)
Definition: light.h:59
Base material class that can be used to derive other material implementations.
Definition: material.h:240
static void SetDefaultReflectionRayCount(unsigned int aCount)
Definition: material.h:247
static void SetDefaultRefractionRayCount(unsigned int aCount)
Definition: material.h:242
static void SetDefaultRefractionRecursionCount(unsigned int aCount)
Definition: material.h:252
void SetGenerator(const MATERIAL_GENERATOR *aGenerator)
Definition: material.h:328
float GetTransparency() const
Definition: material.h:273
static void SetDefaultReflectionRecursionCount(unsigned int aCount)
Definition: material.h:257
static OBJECT_2D_STATS & Instance()
Definition: object_2d.h:137
void ResetStats()
Definition: object_2d.h:122
virtual bool Intersects(const BBOX_2D &aBBox) const =0
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
const BBOX_2D & GetBBox() const
Definition: object_2d.h:103
const BOARD_ITEM & GetBoardItem() const
Definition: object_2d.h:66
OBJECT_2D_TYPE GetObjectType() const
Definition: object_2d.h:107
static OBJECT_3D_STATS & Instance()
Definition: object_3d.h:132
void ResetStats()
Definition: object_3d.h:115
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
void SetModelTransparency(float aModelTransparency)
Definition: object_3d.h:66
void SetBoardItem(BOARD_ITEM *aBoardItem)
Definition: object_3d.h:55
Definition: pad.h:59
const VECTOR2I & GetDrillSize() const
Definition: pad.h:257
VECTOR2I GetPosition() const override
Definition: pad.h:201
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:345
const VECTOR2I & GetStart() const
Definition: pcb_track.h:113
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:600
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Return the 2 layers used by the via (the via actually uses all layers between these 2 layers)
Definition: pcb_track.cpp:951
Procedural generation of the plastic normals.
Definition: material.h:146
Procedural generation of the shiny plastic normals.
Definition: material.h:170
Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20....
Definition: light.h:71
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
CAMERA & m_camera
Flag if the canvas specific for this render was already initialized.
bool m_reloadRequested
The window size that this camera is working.
BOARD_ADAPTER & m_boardAdapter
SILK_SCREEN_NORMAL m_silkScreenMaterial
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation)
void insertHole(const PCB_VIA *aVia)
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
static constexpr float MIN_DISTANCE_IU
PLATED_COPPER_NORMAL m_platedCopperMaterial
void createItemsFromContainer(const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
DIRECTIONAL_LIGHT * m_cameraLight
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
struct RENDER_3D_RAYTRACE_BASE::@5 m_materials
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
MODEL_MATERIALS * getModelMaterial(const S3DMODEL *a3DModel)
SOLDER_MASK_NORMAL m_solderMaskMaterial
void addModels(CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
void createObject(CONTAINER_3D &aDstContainer, const OBJECT_2D *aObject2D, float aZMin, float aZMax, const MATERIAL *aMaterial, const SFVEC3F &aObjColor)
Create one or more 3D objects form a 2D object and Z positions.
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
void SetColor(SFVEC3F aObjColor)
Cache for storing the 3D shapes.
Definition: 3d_cache.h:53
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:634
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int OutlineCount() const
Return the number of outlines in the set.
Procedural generation of the solder mask.
Definition: material.h:126
A triangle object.
Definition: triangle_3d.h:43
void SetColor(const SFVEC3F &aColor)
T y
Definition: vector3.h:63
T z
Definition: vector3.h:64
T x
Definition: vector3.h:62
A plane that is parallel to XY plane.
Definition: plane_3d.h:38
void SetColor(SFVEC3F aObjColor)
Definition: plane_3d.h:49
std::list< OBJECT_2D * > LIST_OBJECT2D
Definition: container_2d.h:38
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
Definition: container_2d.h:39
#define _(s)
#define UNITS3D_TO_UNITSPCB
Implements a model viewer canvas.
Declaration of the eda_3d_viewer class.
FOOTPRINT_ATTR_T
The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes() and FOOTPRINT::Get...
Definition: footprint.h:71
@ LAYER_3D_SOLDERMASK_TOP
Definition: layer_ids.h:458
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:457
@ LAYER_3D_BOARD
Definition: layer_ids.h:452
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:880
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Dwgs_User
Definition: layer_ids.h:109
@ F_Paste
Definition: layer_ids.h:101
@ Cmts_User
Definition: layer_ids.h:110
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ Eco1_User
Definition: layer_ids.h:111
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_Fab
Definition: layer_ids.h:120
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ Eco2_User
Definition: layer_ids.h:112
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:119
#define CSGITEM_EMPTY
Definition: layer_item_2d.h:38
#define CSGITEM_FULL
Definition: layer_item_2d.h:39
void ConvertPolygonToBlocks(const SHAPE_POLY_SET &aMainPath, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (PO...
Definition: polygon_2d.cpp:378
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
static float TransparencyControl(float aGrayColorValue, float aTransparency)
Perform an interpolation step to easy control the transparency based on the gray color value and tran...
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
const SFVEC2F & Min() const
Definition: bbox_2d.h:175
const SFVEC2F & Max() const
Definition: bbox_2d.h:180
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:42
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition: bbox_3d.cpp:132
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:191
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:198
float GetMaxDimension() const
Definition: bbox_3d.cpp:167
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition: bbox_3d.cpp:88
void Scale(float aScale)
Scales a bounding box by its center.
Definition: bbox_3d.cpp:182
std::vector< KIGFX::COLOR4D > raytrace_lightColor
const double IU_PER_MM
Definition: base_units.h:76
Store the a model based on meshes and materials.
Definition: c3dmodel.h:91
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
float m_Shininess
Definition: c3dmodel.h:43
SFVEC3F m_Specular
Definition: c3dmodel.h:42
SFVEC3F m_Ambient
Definition: c3dmodel.h:39
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
SFVEC3F m_Emissive
Definition: c3dmodel.h:41
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:77
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
VECTOR3I v1(5, 5, 5)
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
VECTOR2I v4(1, 1)
VECTOR2I v5(-70, -70)
VECTOR2I v3(-2, 1)
Implement a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_To...
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:228
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44