KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <mrluzeiro@ua.pt>
5 * Copyright (C) 2023 CERN
6 * Copyright The 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{
81
86
87 double mmTo3Dunits = pcbIUScale.IU_PER_MM * m_boardAdapter.BiuTo3dUnits();
88
90 {
91 m_boardMaterial = BOARD_NORMAL( 0.40f * mmTo3Dunits );
92 m_copperMaterial = COPPER_NORMAL( 4.0f * mmTo3Dunits, &m_boardMaterial );
93 m_platedCopperMaterial = PLATED_COPPER_NORMAL( 0.5f * mmTo3Dunits );
95 m_plasticMaterial = PLASTIC_NORMAL( 0.05f * mmTo3Dunits );
96 m_shinyPlasticMaterial = PLASTIC_SHINE_NORMAL( 0.1f * mmTo3Dunits );
97 m_brushedMetalMaterial = BRUSHED_METAL_NORMAL( 0.05f * mmTo3Dunits );
98 m_silkScreenMaterial = SILK_SCREEN_NORMAL( 0.25f * mmTo3Dunits );
99 }
100
101 // http://devernay.free.fr/cours/opengl/materials.html
102 // Copper
103 const SFVEC3F copperSpecularLinear =
104 ConvertSRGBToLinear( glm::clamp( (SFVEC3F) m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
105 SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) ) );
106
109 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
110
112 m_materials.m_Copper.SetGenerator( &m_platedCopperMaterial );
113
114 m_materials.m_NonPlatedCopper = BLINN_PHONG_MATERIAL(
115 ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ), SFVEC3F( 0.0f, 0.0f, 0.0f ),
116 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
117
119 m_materials.m_NonPlatedCopper.SetGenerator( &m_copperMaterial );
120
124 SFVEC3F( 0.0f, 0.0f, 0.0f ),
128 0.10f * 128.0f, 0.0f, 0.0f );
129
131 SFVEC3F( 0.0f, 0.0f, 0.0f ),
132 glm::clamp( ( ( SFVEC3F )( 1.0f ) - ConvertSRGBToLinear(
134 SFVEC3F( 0.0f ), SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
135
137 m_materials.m_SilkS.SetGenerator( &m_silkScreenMaterial );
138
139 // Assume that SolderMaskTop == SolderMaskBot
140 const float solderMask_gray =
143 / 3.0f;
144
145 const float solderMask_transparency = TransparencyControl( solderMask_gray,
147
148 m_materials.m_SolderMask = BLINN_PHONG_MATERIAL(
150 SFVEC3F( 0.0f, 0.0f, 0.0f ),
151 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
152 solderMask_transparency, 0.16f );
153
154 m_materials.m_SolderMask.SetCastShadows( true );
155 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
156
158 m_materials.m_SolderMask.SetGenerator( &m_solderMaskMaterial );
159
160 m_materials.m_EpoxyBoard =
161 BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f,
162 10.0f / 255.0f ) ),
163 SFVEC3F( 0.0f, 0.0f, 0.0f ),
164 ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f, 8.0f / 255.0f,
165 10.0f / 255.0f ) ),
166 0.1f * 128.0f, 1.0f - m_boardAdapter.m_BoardBodyColor.a, 0.0f );
167
168 m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
169
171 m_materials.m_EpoxyBoard.SetGenerator( &m_boardMaterial );
172
174
175 m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ),
176 ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
177 0.10f * 128.0f, 1.0f, 0.50f );
178 m_materials.m_Floor.SetCastShadows( false );
179 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
180}
181
182
183void RENDER_3D_RAYTRACE_BASE::createObject( CONTAINER_3D& aDstContainer, const OBJECT_2D* aObject2D,
184 float aZMin, float aZMax, const MATERIAL* aMaterial,
185 const SFVEC3F& aObjColor )
186{
187 switch( aObject2D->GetObjectType() )
188 {
189 case OBJECT_2D_TYPE::DUMMYBLOCK:
190 {
192
193 XY_PLANE* objPtr;
194 objPtr = new XY_PLANE( BBOX_3D(
195 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
196 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
197 objPtr->SetMaterial( aMaterial );
198 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
199 aDstContainer.Add( objPtr );
200
201 objPtr = new XY_PLANE( BBOX_3D(
202 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
203 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
204 objPtr->SetMaterial( aMaterial );
205 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
206 aDstContainer.Add( objPtr );
207 break;
208 }
209
210 case OBJECT_2D_TYPE::ROUNDSEG:
211 {
213
214 const ROUND_SEGMENT_2D* aRoundSeg2D = static_cast<const ROUND_SEGMENT_2D*>( aObject2D );
215 ROUND_SEGMENT* objPtr = new ROUND_SEGMENT( *aRoundSeg2D, aZMin, aZMax );
216 objPtr->SetMaterial( aMaterial );
217 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
218 aDstContainer.Add( objPtr );
219 break;
220 }
221
222 default:
223 {
224 LAYER_ITEM* objPtr = new LAYER_ITEM( aObject2D, aZMin, aZMax );
225 objPtr->SetMaterial( aMaterial );
226 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
227 aDstContainer.Add( objPtr );
228 break;
229 }
230 }
231}
232
233
235 PCB_LAYER_ID aLayer_id,
236 const MATERIAL* aMaterialLayer,
237 const SFVEC3F& aLayerColor,
238 float aLayerZOffset )
239{
240 if( aContainer2d == nullptr )
241 return;
242
244 bool isSilk = aLayer_id == B_SilkS || aLayer_id == F_SilkS;
245 const LIST_OBJECT2D& listObject2d = aContainer2d->GetList();
246
247 if( listObject2d.size() == 0 )
248 return;
249
250 for( const OBJECT_2D* object2d_A : listObject2d )
251 {
252 // not yet used / implemented (can be used in future to clip the objects in the
253 // board borders
254 OBJECT_2D* object2d_C = CSGITEM_FULL;
255
256 std::vector<const OBJECT_2D*>* object2d_B = CSGITEM_EMPTY;
257
258 object2d_B = new std::vector<const OBJECT_2D*>();
259
260 // Subtract holes but not in SolderPaste
261 // (can be added as an option in future)
262 if( !( aLayer_id == B_Paste || aLayer_id == F_Paste ) )
263 {
264 // Check if there are any layerhole that intersects this object
265 // Eg: a segment is cut by a via hole or THT hole.
267
268 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
269 {
270 const BVH_CONTAINER_2D* holes2d = layerHolesMap.at( aLayer_id );
271
272 CONST_LIST_OBJECT2D intersecting;
273
274 holes2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
275
276 for( const OBJECT_2D* hole2d : intersecting )
277 object2d_B->push_back( hole2d );
278 }
279
280 // Check if there are any THT that intersects this object. If we're processing a silk
281 // layer and the flag is set, then clip the silk at the outer edge of the annular ring,
282 // rather than the at the outer edge of the copper plating.
283 const BVH_CONTAINER_2D& throughHoleOuter =
286
287 if( !throughHoleOuter.GetList().empty() )
288 {
289 CONST_LIST_OBJECT2D intersecting;
290
291 throughHoleOuter.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
292
293 for( const OBJECT_2D* hole2d : intersecting )
294 object2d_B->push_back( hole2d );
295 }
296 }
297
298 if( !m_antioutlineBoard2dObjects->GetList().empty() )
299 {
300 CONST_LIST_OBJECT2D intersecting;
301
303 intersecting );
304
305 for( const OBJECT_2D* obj : intersecting )
306 object2d_B->push_back( obj );
307 }
308
310
312 && ( ( aLayer_id == B_SilkS && mapLayers.find( B_Mask ) != mapLayers.end() )
313 || ( aLayer_id == F_SilkS && mapLayers.find( F_Mask ) != mapLayers.end() ) ) )
314 {
315 const PCB_LAYER_ID maskLayer = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
316
317 const BVH_CONTAINER_2D* containerMaskLayer2d = mapLayers.at( maskLayer );
318
319 CONST_LIST_OBJECT2D intersecting;
320
321 if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
322 containerMaskLayer2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
323
324 for( const OBJECT_2D* obj2d : intersecting )
325 object2d_B->push_back( obj2d );
326 }
327
328 if( object2d_B->empty() )
329 {
330 delete object2d_B;
331 object2d_B = CSGITEM_EMPTY;
332 }
333
334 if( ( object2d_B == CSGITEM_EMPTY ) && ( object2d_C == CSGITEM_FULL ) )
335 {
336 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
337 m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
338 m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
339 objPtr->SetMaterial( aMaterialLayer );
340 objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
341 m_objectContainer.Add( objPtr );
342 }
343 else
344 {
345 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, object2d_C,
346 object2d_A->GetBoardItem() );
348
349 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
350 m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
351 m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
352
353 objPtr->SetMaterial( aMaterialLayer );
354 objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
355
356 m_objectContainer.Add( objPtr );
357 }
358 }
359}
360
361
362extern void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline );
363
364
365void RENDER_3D_RAYTRACE_BASE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter,
366 bool aOnlyLoadCopperAndShapes )
367{
368 m_reloadRequested = false;
369
370 m_modelMaterialMap.clear();
371
374
375 int64_t stats_startReloadTime = GetRunningMicroSecs();
376
377 if( !aOnlyLoadCopperAndShapes )
378 {
379 m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
380
382 m_camera.SetBoardLookAtPos( camera_pos );
383 }
384
387
389
390 if( aStatusReporter )
391 aStatusReporter->Report( _( "Load Raytracing: board" ) );
392
393 // Create and add the outline board
396
399
400 std::bitset<LAYER_3D_END> layerFlags = m_boardAdapter.GetVisibleLayers();
401
402 if( !aOnlyLoadCopperAndShapes )
403 {
404 const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
405
406 if( outlineCount > 0 )
407 {
408 float divFactor = 0.0f;
409
411 divFactor = m_boardAdapter.GetAverageViaHoleDiameter() * 18.0f;
412 else if( m_boardAdapter.GetHoleCount() )
413 divFactor = m_boardAdapter.GetAverageHoleDiameter() * 8.0f;
414
416
417 // Calculate an antiboard outline
418 SHAPE_POLY_SET antiboardPoly;
419
421
422 antiboardPoly.BooleanSubtract( boardPolyCopy );
423 antiboardPoly.Fracture();
424
425 for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
426 {
429 *m_boardAdapter.GetBoard(), ii );
430 }
431
433
434 boardPolyCopy.Fracture();
435
436 for( int ii = 0; ii < boardPolyCopy.OutlineCount(); ii++ )
437 {
439 m_boardAdapter.BiuTo3dUnits(), divFactor,
440 *m_boardAdapter.GetBoard(), ii );
441 }
442
443 if( layerFlags.test( LAYER_3D_BOARD ) )
444 {
445 const LIST_OBJECT2D& listObjects = m_outlineBoard2dObjects->GetList();
446
447 for( const OBJECT_2D* object2d_A : listObjects )
448 {
449 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
450
451 // Check if there are any THT that intersects this outline object part
452 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
453 {
454 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetTH_ODs();
455 CONST_LIST_OBJECT2D intersecting;
456
457 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
458
459 for( const OBJECT_2D* hole : intersecting )
460 {
461 if( object2d_A->Intersects( hole->GetBBox() ) )
462 object2d_B->push_back( hole );
463 }
464 }
465
466 if( !m_antioutlineBoard2dObjects->GetList().empty() )
467 {
468 CONST_LIST_OBJECT2D intersecting;
469
471 intersecting );
472
473 for( const OBJECT_2D* obj : intersecting )
474 object2d_B->push_back( obj );
475 }
476
477 if( object2d_B->empty() )
478 {
479 delete object2d_B;
480 object2d_B = CSGITEM_EMPTY;
481 }
482
483 if( object2d_B == CSGITEM_EMPTY )
484 {
485 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
488
489 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
491 m_objectContainer.Add( objPtr );
492 }
493 else
494 {
495
496 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
499
501
502 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
505
506 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
508 m_objectContainer.Add( objPtr );
509 }
510 }
511
512 // Add cylinders of the board body to container
513 // Note: This is actually a workaround for the holes in the board.
514 // The issue is because if a hole is in a border of a divided polygon ( ex
515 // a polygon or dummy block) it will cut also the render of the hole.
516 // So this will add a full hole.
517 // In fact, that is not need if the hole have copper.
518 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
519 {
520 const LIST_OBJECT2D& holeList = m_boardAdapter.GetTH_ODs().GetList();
521
522 for( const OBJECT_2D* hole2d : holeList )
523 {
524 if( !m_antioutlineBoard2dObjects->GetList().empty() )
525 {
526 CONST_LIST_OBJECT2D intersecting;
527
529 intersecting );
530
531 // Do not add cylinder if it intersects the edge of the board
532 if( !intersecting.empty() )
533 continue;
534 }
535
536 switch( hole2d->GetObjectType() )
537 {
538 case OBJECT_2D_TYPE::FILLED_CIRCLE:
539 {
540 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
541
542 CYLINDER* objPtr = new CYLINDER( hole2d->GetCentroid(),
545 radius );
546
547 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
548 objPtr->SetColor(
550
551 m_objectContainer.Add( objPtr );
552 }
553 break;
554
555 default:
556 break;
557 }
558 }
559 }
560 }
561 }
562 }
563
564 if( aStatusReporter )
565 aStatusReporter->Report( _( "Load Raytracing: layers" ) );
566
567 // Add layers maps (except B_Mask and F_Mask)
568 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
570 {
571 const PCB_LAYER_ID layer_id = entry.first;
572 const BVH_CONTAINER_2D* container2d = entry.second;
573
574 // Only process layers that exist
575 if( !container2d )
576 continue;
577
578 if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
579 continue;
580
581 // Mask layers are not processed here because they are a special case
582 if( layer_id == B_Mask || layer_id == F_Mask )
583 continue;
584
585 MATERIAL* materialLayer = &m_materials.m_SilkS;
586 SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
587
588 switch( layer_id )
589 {
590 case B_Adhes:
591 case F_Adhes:
592 break;
593
594 case B_Paste:
595 case F_Paste:
596 materialLayer = &m_materials.m_Paste;
598 break;
599
600 case B_SilkS:
601 materialLayer = &m_materials.m_SilkS;
603 break;
604
605 case F_SilkS:
606 materialLayer = &m_materials.m_SilkS;
608 break;
609
610 case Dwgs_User:
612 break;
613
614 case Cmts_User:
616 break;
617
618 case Eco1_User:
619 layerColor = m_boardAdapter.m_ECO1Color;
620 break;
621
622 case Eco2_User:
623 layerColor = m_boardAdapter.m_ECO2Color;
624 break;
625
626 case B_CrtYd:
627 case F_CrtYd:
628 break;
629
630 case B_Fab:
631 case F_Fab:
632 break;
633
634 default:
635 {
636 int layer3D = MapPCBLayerTo3DLayer( layer_id );
637
638 // Note: MUST do this in LAYER_3D space; User_1..User_45 are NOT contiguous
639 if( layer3D >= LAYER_3D_USER_1 && layer3D <= LAYER_3D_USER_45 )
640 {
642 }
644 {
645 layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
646 materialLayer = &m_materials.m_NonPlatedCopper;
647 }
648 else
649 {
650 layerColor = m_boardAdapter.m_CopperColor;
651 materialLayer = &m_materials.m_Copper;
652 }
653
654 break;
655 }
656 }
657
658 createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
659 } // for each layer on map
660
661 // Create plated copper
663 {
667
671 }
672
673 if( !aOnlyLoadCopperAndShapes )
674 {
675 // Add Mask layer
676 // Solder mask layers are "negative" layers so the elements that we have in the container
677 // should remove the board outline. We will check for all objects in the outline if it
678 // intersects any object in the layer container and also any hole.
679 if( ( layerFlags.test( LAYER_3D_SOLDERMASK_TOP )
680 || layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
681 && !m_outlineBoard2dObjects->GetList().empty() )
682 {
683 const MATERIAL* materialLayer = &m_materials.m_SolderMask;
684
685 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
687 {
688 const PCB_LAYER_ID layer_id = entry.first;
689 const BVH_CONTAINER_2D* container2d = entry.second;
690
691 // Only process layers that exist
692 if( !container2d )
693 continue;
694
695 // Only get the Solder mask layers (and only if the board has them)
696 if( layer_id == F_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_TOP ) )
697 continue;
698
699 if( layer_id == B_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
700 continue;
701
702 // Only Mask layers are processed here because they are negative layers
703 if( layer_id != F_Mask && layer_id != B_Mask )
704 continue;
705
706 SFVEC3F layerColor;
707
708 if( layer_id == B_Mask )
710 else
712
713 const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
714 const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
715
716 // Get the outline board objects
717 for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
718 {
719 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
720
721 // Check if there are any THT that intersects this outline object part
722 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
723 {
724 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetTH_ODs();
725 CONST_LIST_OBJECT2D intersecting;
726
727 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
728
729 for( const OBJECT_2D* hole : intersecting )
730 {
731 if( object2d_A->Intersects( hole->GetBBox() ) )
732 object2d_B->push_back( hole );
733 }
734 }
735
736 // Check if there are any objects in the layer to subtract with the current
737 // object
738 if( !container2d->GetList().empty() )
739 {
740 CONST_LIST_OBJECT2D intersecting;
741
742 container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
743
744 for( const OBJECT_2D* obj : intersecting )
745 object2d_B->push_back( obj );
746 }
747
748 if( object2d_B->empty() )
749 {
750 delete object2d_B;
751 object2d_B = CSGITEM_EMPTY;
752 }
753
754 if( object2d_B == CSGITEM_EMPTY )
755 {
756#if 0
757 createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
758 materialLayer, layerColor );
759#else
760 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
761
762 objPtr->SetMaterial( materialLayer );
763 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
764
765 m_objectContainer.Add( objPtr );
766#endif
767 }
768 else
769 {
770 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
772 object2d_A->GetBoardItem() );
773
775
776 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
777 objPtr->SetMaterial( materialLayer );
778 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
779
780 m_objectContainer.Add( objPtr );
781 }
782 }
783 }
784 }
785
787 }
788
789#ifdef PRINT_STATISTICS_3D_VIEWER
790 int64_t stats_endConvertTime = GetRunningMicroSecs();
791 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
792#endif
793
794 if( aStatusReporter )
795 aStatusReporter->Report( _( "Loading 3D models..." ) );
796
797 load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
798
799#ifdef PRINT_STATISTICS_3D_VIEWER
800 int64_t stats_endLoad3DmodelsTime = GetRunningMicroSecs();
801#endif
802
803 if( !aOnlyLoadCopperAndShapes )
804 {
805 // Add floor
807 {
808 BBOX_3D boardBBox = m_boardAdapter.GetBBox();
809
810 if( boardBBox.IsInitialized() )
811 {
812 boardBBox.Scale( 3.0f );
813
814 if( m_objectContainer.GetList().size() > 0 )
815 {
816 BBOX_3D containerBBox = m_objectContainer.GetBBox();
817
818 containerBBox.Scale( 1.3f );
819
820 const SFVEC3F centerBBox = containerBBox.GetCenter();
821
822 // Floor triangles
823 const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
824
825 const SFVEC3F v1 =
826 SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
827 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
828
829 const SFVEC3F v3 =
830 SFVEC3F( +RANGE_SCALE_3D * 4.0f, +RANGE_SCALE_3D * 4.0f, minZ )
831 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
832
833 const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
834 const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
835
837
838 TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
839 TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
840
841 m_objectContainer.Add( newTriangle1 );
842 m_objectContainer.Add( newTriangle2 );
843
844 newTriangle1->SetMaterial( &m_materials.m_Floor );
845 newTriangle2->SetMaterial( &m_materials.m_Floor );
846
847 newTriangle1->SetColor( floorColor );
848 newTriangle2->SetColor( floorColor );
849
850 // Ceiling triangles
851 const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
852
853 const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
854 const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
855 const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
856 const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
857
858 TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
859 TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
860
861 m_objectContainer.Add( newTriangle3 );
862 m_objectContainer.Add( newTriangle4 );
863
864 newTriangle3->SetMaterial( &m_materials.m_Floor );
865 newTriangle4->SetMaterial( &m_materials.m_Floor );
866
867 newTriangle3->SetColor( floorColor );
868 newTriangle4->SetColor( floorColor );
869 }
870 }
871 }
872
873 // Init initial lights
874 for( LIGHT* light : m_lights )
875 delete light;
876
877 m_lights.clear();
878
879 auto IsColorZero =
880 []( const SFVEC3F& aSource )
881 {
882 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
883 && ( aSource.b < ( 1.0f / 255.0f ) ) );
884 };
885
886 SFVEC3F cameraLightColor =
888 SFVEC3F topLightColor =
890 SFVEC3F bottomLightColor =
892
893 m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), cameraLightColor );
895
896 if( !IsColorZero( cameraLightColor ) )
897 m_lights.push_back( m_cameraLight );
898
899 const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
900
901 if( !IsColorZero( topLightColor ) )
902 {
903 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
904 +RANGE_SCALE_3D * 2.0f ),
905 topLightColor ) );
906 }
907
908 if( !IsColorZero( bottomLightColor ) )
909 {
910 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
911 -RANGE_SCALE_3D * 2.0f ),
912 bottomLightColor ) );
913 }
914
915 for( size_t i = 0; i < m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
916 {
917 SFVEC3F lightColor =
919
920 if( !IsColorZero( lightColor ) )
921 {
923
924 m_lights.push_back( new DIRECTIONAL_LIGHT(
925 SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
926 lightColor ) );
927 }
928 }
929 }
930
931 // Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
932 // class would require reimplementing bounding box calculation (feel free to do this if you
933 // have time and patience).
934 if( m_objectContainer.GetList().size() > 0 )
935 {
936 float ratio =
938
939 float max_zoom = CAMERA::DEFAULT_MAX_ZOOM * ratio;
940 float min_zoom = static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
941 / -m_camera.GetCameraInitPos().z );
942
943 if( min_zoom > max_zoom )
944 std::swap( min_zoom, max_zoom );
945
946 float zoom_ratio = max_zoom / min_zoom;
947
948 // Set the minimum number of zoom 'steps' between max and min.
949 int steps = 3 * 3;
950 steps -= static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
951 steps = std::max( steps, 0 );
952
953 // Resize max and min zoom to accomplish the number of steps.
954 float increased_zoom = pow( 1.26f, steps / 2 );
955 max_zoom *= increased_zoom;
956 min_zoom /= increased_zoom;
957
958 if( steps & 1 )
959 min_zoom /= 1.26f;
960
961 min_zoom = std::min( min_zoom, 1.0f );
962
963 m_camera.SetMaxZoom( max_zoom );
964 m_camera.SetMinZoom( min_zoom );
965 }
966
967 // Create an accelerator
968 delete m_accelerator;
969 m_accelerator = new BVH_PBRT( m_objectContainer, 8, SPLITMETHOD::MIDDLE );
970
971 if( aStatusReporter )
972 {
973 // Calculation time in seconds
974 double calculation_time = (double) ( GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
975
976 aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
977 }
978}
979
980
982{
983 PCB_LAYER_ID top_layer, bottom_layer;
984 int radiusBUI = ( aVia->GetDrillValue() / 2 );
985
986 aVia->LayerPair( &top_layer, &bottom_layer );
987
988 float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
990
991 float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
993
995 -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
996
997 RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
999 * m_boardAdapter.BiuTo3dUnits(), *aVia );
1000
1002
1003 LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
1004
1005 objPtr->SetMaterial( &m_materials.m_Copper );
1007
1008 m_objectContainer.Add( objPtr );
1009}
1010
1011
1013{
1014 const OBJECT_2D* object2d_A = nullptr;
1015
1017 const VECTOR2I drillsize = aPad->GetDrillSize();
1018 const bool hasHole = drillsize.x && drillsize.y;
1019
1020 if( !hasHole )
1021 return;
1022
1023 CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1024
1025 const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
1027
1028 const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
1030
1031 if( drillsize.x == drillsize.y ) // usual round hole
1032 {
1035
1036 int innerRadius = drillsize.x / 2;
1037 int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1038
1039 RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1040 outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1041
1043
1044 object2d_A = ring;
1045
1046 // If the object (ring) is intersected by an antioutline board,
1047 // it will use instead a CSG of two circles.
1048 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1049 {
1051 antiOutlineIntersectionList );
1052 }
1053
1054 if( !antiOutlineIntersectionList.empty() )
1055 {
1056 FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1057 center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1058
1059 FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1060 center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1061 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1062 object2d_B->push_back( innerCircle );
1063
1064 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1065 *aPad );
1066
1068 m_containerWithObjectsToDelete.Add( innerCircle );
1069 m_containerWithObjectsToDelete.Add( outterCircle );
1070
1071 object2d_A = itemCSG2d;
1072 }
1073 }
1074 else // Oblong hole
1075 {
1076 VECTOR2I ends_offset;
1077 int width;
1078
1079 if( drillsize.x > drillsize.y ) // Horizontal oval
1080 {
1081 ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1082 width = drillsize.y;
1083 }
1084 else // Vertical oval
1085 {
1086 ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1087 width = drillsize.x;
1088 }
1089
1090 RotatePoint( ends_offset, aPad->GetOrientation() );
1091
1092 VECTOR2I start = VECTOR2I( aPad->GetPosition() ) + ends_offset;
1093 VECTOR2I end = VECTOR2I( aPad->GetPosition() ) - ends_offset;
1094
1095 ROUND_SEGMENT_2D* innerSeg =
1097 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1100 width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1101
1102 ROUND_SEGMENT_2D* outerSeg =
1104 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1107 ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1108 * m_boardAdapter.BiuTo3dUnits(), *aPad );
1109
1110 // NOTE: the round segment width is the "diameter", so we double the thickness
1111 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1112 object2d_B->push_back( innerSeg );
1113
1114 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1115
1119
1120 object2d_A = itemCSG2d;
1121
1122 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1123 {
1125 antiOutlineIntersectionList );
1126 }
1127 }
1128
1129 if( object2d_A )
1130 {
1131 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1132
1133 // Check if there are any other THT that intersects this hole
1134 // It will use the non inflated holes
1135 if( !m_boardAdapter.GetTH_IDs().GetList().empty() )
1136 {
1137 CONST_LIST_OBJECT2D intersecting;
1138
1139 m_boardAdapter.GetTH_IDs().GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
1140
1141 for( const OBJECT_2D* hole2d : intersecting )
1142 {
1143 if( object2d_A->Intersects( hole2d->GetBBox() ) )
1144 object2d_B->push_back( hole2d );
1145 }
1146 }
1147
1148 for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1149 object2d_B->push_back( obj );
1150
1151 if( object2d_B->empty() )
1152 {
1153 delete object2d_B;
1154 object2d_B = CSGITEM_EMPTY;
1155 }
1156
1157 if( object2d_B == CSGITEM_EMPTY )
1158 {
1159 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1160
1161 objPtr->SetMaterial( &m_materials.m_Copper );
1162 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1163 m_objectContainer.Add( objPtr );
1164 }
1165 else
1166 {
1167 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1168 *aPad );
1169
1171
1172 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1173
1174 objPtr->SetMaterial( &m_materials.m_Copper );
1175 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1176
1177 m_objectContainer.Add( objPtr );
1178 }
1179 }
1180}
1181
1182
1184{
1185 if( !m_boardAdapter.GetBoard() )
1186 return;
1187
1188 // Insert plated vertical holes inside the board
1189
1190 // Insert vias holes (vertical cylinders)
1191 for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1192 {
1193 if( track->Type() == PCB_VIA_T )
1194 {
1195 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1196 insertHole( via );
1197 }
1198 }
1199
1200 // Insert pads holes (vertical cylinders)
1201 for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1202 {
1203 for( PAD* pad : footprint->Pads() )
1204 {
1205 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1206 insertHole( pad );
1207 }
1208 }
1209}
1210
1211
1213 bool aSkipMaterialInformation )
1214{
1215 if( !m_boardAdapter.GetBoard() )
1216 return;
1217
1222 {
1223 return;
1224 }
1225
1226 // Go for all footprints
1228 {
1229 if( !fp->Models().empty()
1230 && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1231 {
1232 double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1233
1234 VECTOR2I pos = fp->GetPosition();
1235
1236 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1237
1238 fpMatrix = glm::translate( fpMatrix,
1240 -pos.y * m_boardAdapter.BiuTo3dUnits(),
1241 zpos ) );
1242
1243 if( !fp->GetOrientation().IsZero() )
1244 {
1245 fpMatrix = glm::rotate( fpMatrix, (float) fp->GetOrientation().AsRadians(),
1246 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1247 }
1248
1249 if( fp->IsFlipped() )
1250 {
1251 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1252
1253 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1254 }
1255
1256 const double modelunit_to_3d_units_factor =
1258
1259 fpMatrix = glm::scale(
1260 fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1261 modelunit_to_3d_units_factor ) );
1262
1263 // Get the list of model files for this model
1265
1266 wxString libraryName = fp->GetFPID().GetLibNickname();
1267
1268 wxString footprintBasePath = wxEmptyString;
1269
1271 {
1272 try
1273 {
1274 // FindRow() can throw an exception
1275 const FP_LIB_TABLE_ROW* fpRow =
1277 ->FindRow( libraryName, false );
1278
1279 if( fpRow )
1280 footprintBasePath = fpRow->GetFullURI( true );
1281 }
1282 catch( ... )
1283 {
1284 // Do nothing if the libraryName is not found in lib table
1285 }
1286 }
1287
1288 for( FP_3DMODEL& model : fp->Models() )
1289 {
1290 if( !model.m_Show || model.m_Filename.empty() )
1291 continue;
1292
1293 // get it from cache
1294 const S3DMODEL* modelPtr =
1295 cacheMgr->GetModel( model.m_Filename, footprintBasePath, fp );
1296
1297 // only add it if the return is not NULL.
1298 if( modelPtr )
1299 {
1300 glm::mat4 modelMatrix = fpMatrix;
1301
1302 modelMatrix = glm::translate( modelMatrix,
1303 SFVEC3F( model.m_Offset.x, model.m_Offset.y, model.m_Offset.z ) );
1304
1305 modelMatrix = glm::rotate( modelMatrix,
1306 (float) -( model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
1307 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1308
1309 modelMatrix = glm::rotate( modelMatrix,
1310 (float) -( model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
1311 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1312
1313 modelMatrix = glm::rotate( modelMatrix,
1314 (float) -( model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
1315 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1316
1317 modelMatrix = glm::scale( modelMatrix,
1318 SFVEC3F( model.m_Scale.x, model.m_Scale.y, model.m_Scale.z ) );
1319
1320 addModels( aDstContainer, modelPtr, modelMatrix, (float) model.m_Opacity,
1321 aSkipMaterialInformation, fp );
1322 }
1323 }
1324 }
1325 }
1326}
1327
1328
1330{
1331 MODEL_MATERIALS* materialVector;
1332
1333 // Try find if the materials already exists in the map list
1334 if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1335 {
1336 // Found it, so get the pointer
1337 materialVector = &m_modelMaterialMap[a3DModel];
1338 }
1339 else
1340 {
1341 // Materials was not found in the map, so it will create a new for
1342 // this model.
1343
1344 m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1345 materialVector = &m_modelMaterialMap[a3DModel];
1346
1347 materialVector->resize( a3DModel->m_MaterialsSize );
1348
1349 for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1350 {
1351 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::NORMAL )
1352 {
1353 const SMATERIAL& material = a3DModel->m_Materials[imat];
1354
1355 // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1356
1357 float reflectionFactor = 0.0f;
1358
1359 if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1360 {
1361 reflectionFactor = glm::clamp(
1362 glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1363 0.5f );
1364 }
1365
1366 BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1367
1368 blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1369 ConvertSRGBToLinear( material.m_Emissive ),
1370 ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1371 material.m_Transparency, reflectionFactor );
1372
1374 {
1375 // Guess material type and apply a normal perturbator
1376 if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1377 && ( material.m_Shininess < 0.36f )
1378 && ( material.m_Transparency == 0.0f )
1379 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1380 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1381 < 0.15f )
1382 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1383 < 0.15f ) ) )
1384 {
1385 // This may be a black plastic..
1386 blinnMaterial.SetGenerator( &m_plasticMaterial );
1387 }
1388 else
1389 {
1390 if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1391 && ( material.m_Shininess < 0.30f )
1392 && ( material.m_Transparency == 0.0f )
1393 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1394 || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1395 || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1396 > 0.25f ) ) )
1397 {
1398 // This may be a color plastic ...
1399 blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1400 }
1401 else
1402 {
1403 if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1404 && ( material.m_Shininess > 0.35f )
1405 && ( material.m_Transparency == 0.0f )
1406 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1407 < 0.40f )
1408 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1409 < 0.40f )
1410 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1411 < 0.40f ) ) )
1412 {
1413 // This may be a brushed metal
1414 blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1415 }
1416 }
1417 }
1418 }
1419 }
1420 else
1421 {
1422 ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1423 SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1424 }
1425 }
1426 }
1427
1428 return materialVector;
1429}
1430
1431
1432void RENDER_3D_RAYTRACE_BASE::addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
1433 const glm::mat4& aModelMatrix, float aFPOpacity,
1434 bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem )
1435{
1436 // Validate a3DModel pointers
1437 wxASSERT( a3DModel != nullptr );
1438
1439 if( a3DModel == nullptr )
1440 return;
1441
1442 wxASSERT( a3DModel->m_Materials != nullptr );
1443 wxASSERT( a3DModel->m_Meshes != nullptr );
1444 wxASSERT( a3DModel->m_MaterialsSize > 0 );
1445 wxASSERT( a3DModel->m_MeshesSize > 0 );
1446
1447 if( aFPOpacity > 1.0f )
1448 aFPOpacity = 1.0f;
1449
1450 if( aFPOpacity < 0.0f )
1451 aFPOpacity = 0.0f;
1452
1453 if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1454 && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1455 {
1456 MODEL_MATERIALS* materialVector = nullptr;
1457
1458 if( !aSkipMaterialInformation )
1459 {
1460 materialVector = getModelMaterial( a3DModel );
1461 }
1462
1463 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1464
1465 for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1466 {
1467 const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1468
1469 // Validate the mesh pointers
1470 wxASSERT( mesh.m_Positions != nullptr );
1471 wxASSERT( mesh.m_FaceIdx != nullptr );
1472 wxASSERT( mesh.m_Normals != nullptr );
1473 wxASSERT( mesh.m_FaceIdxSize > 0 );
1474 wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1475
1476
1477 if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1478 && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1479 && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1480 && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1481 {
1482 float fpTransparency;
1483 const BLINN_PHONG_MATERIAL* blinn_material;
1484
1485 if( !aSkipMaterialInformation )
1486 {
1487 blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1488
1489 fpTransparency =
1490 1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1491 }
1492
1493 // Add all face triangles
1494 for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1495 {
1496 const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1497 const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1498 const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1499
1500 wxASSERT( idx0 < mesh.m_VertexSize );
1501 wxASSERT( idx1 < mesh.m_VertexSize );
1502 wxASSERT( idx2 < mesh.m_VertexSize );
1503
1504 if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1505 && ( idx2 < mesh.m_VertexSize ) )
1506 {
1507 const SFVEC3F& v0 = mesh.m_Positions[idx0];
1508 const SFVEC3F& v1 = mesh.m_Positions[idx1];
1509 const SFVEC3F& v2 = mesh.m_Positions[idx2];
1510
1511 const SFVEC3F& n0 = mesh.m_Normals[idx0];
1512 const SFVEC3F& n1 = mesh.m_Normals[idx1];
1513 const SFVEC3F& n2 = mesh.m_Normals[idx2];
1514
1515 // Transform vertex with the model matrix
1516 const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1517 const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1518 const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1519
1520 const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1521 const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1522 const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1523
1524 TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1525
1526 newTriangle->SetBoardItem( aBoardItem );
1527
1528 aDstContainer.Add( newTriangle );
1529
1530 if( !aSkipMaterialInformation )
1531 {
1532 newTriangle->SetMaterial( blinn_material );
1533 newTriangle->SetModelTransparency( fpTransparency );
1534
1535 if( mesh.m_Color == nullptr )
1536 {
1537 const SFVEC3F diffuseColor =
1538 a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1539
1540 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1541 newTriangle->SetColor( ConvertSRGBToLinear(
1542 MaterialDiffuseToColorCAD( diffuseColor ) ) );
1543 else
1544 newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1545 }
1546 else
1547 {
1548 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1549 {
1550 newTriangle->SetColor(
1552 mesh.m_Color[idx0] ) ),
1554 mesh.m_Color[idx1] ) ),
1556 mesh.m_Color[idx2] ) ) );
1557 }
1558 else
1559 {
1560 newTriangle->SetColor(
1561 ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1562 ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1563 ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1564 }
1565 }
1566 }
1567 }
1568 }
1569 }
1570 }
1571 }
1572}
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
SFVEC4F m_UserDefinedLayerColor[45]
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 outline 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:78
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
const FOOTPRINTS & Footprints() const
Definition: board.h:338
const TRACKS & Tracks() const
Definition: board.h:336
PROJECT * GetProject() const
Definition: board.h:511
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:54
const VECTOR2I & GetDrillSize() const
Definition: pad.h:305
VECTOR2I GetPosition() const override
Definition: pad.h:208
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:408
const VECTOR2I & GetStart() const
Definition: pcb_track.h:152
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:634
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:1321
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
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
SILK_SCREEN_NORMAL m_silkScreenMaterial
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
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
CONTAINER_2D m_containerWithObjectsToDelete
Store the list of created objects special for RT that will be clear in the end.
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:73
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:55
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, const EMBEDDED_FILES *aEmbeddedFiles)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:550
Represent a set of closed polygons.
void Fracture()
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.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
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:64
T z
Definition: vector3.h:65
T x
Definition: vector3.h:63
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:79
int MapPCBLayerTo3DLayer(PCB_LAYER_ID aLayer)
Definition: layer_id.cpp:331
@ LAYER_3D_USER_1
Definition: layer_ids.h:554
@ LAYER_3D_SOLDERMASK_TOP
Definition: layer_ids.h:547
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:546
@ LAYER_3D_BOARD
Definition: layer_ids.h:541
@ LAYER_3D_USER_45
Definition: layer_ids.h:598
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:663
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ F_CrtYd
Definition: layer_ids.h:116
@ B_Adhes
Definition: layer_ids.h:103
@ Dwgs_User
Definition: layer_ids.h:107
@ F_Paste
Definition: layer_ids.h:104
@ Cmts_User
Definition: layer_ids.h:108
@ F_Adhes
Definition: layer_ids.h:102
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ Eco1_User
Definition: layer_ids.h:109
@ F_Mask
Definition: layer_ids.h:97
@ B_Paste
Definition: layer_ids.h:105
@ F_Fab
Definition: layer_ids.h:119
@ F_SilkS
Definition: layer_ids.h:100
@ B_CrtYd
Definition: layer_ids.h:115
@ Eco2_User
Definition: layer_ids.h:110
@ B_SilkS
Definition: layer_ids.h:101
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:118
#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:43
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:192
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:199
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:95
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:100
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:96
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:97
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:99
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:81
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:88
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:84
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:89
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:82
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:87
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:86
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:83
VECTOR3I v1(5, 5, 5)
VECTOR2I center
int radius
VECTOR2I end
VECTOR2I v2(1, 0)
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:229
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44