KiCad PCB EDA Suite
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) 2015-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "render_3d_raytrace.h"
26#include "shapes3D/plane_3d.h"
32#include "shapes2D/ring_2d.h"
33#include "shapes2D/polygon_2d.h"
37#include "3d_fastmath.h"
38#include "3d_math.h"
39
40#include <board.h>
41#include <footprint.h>
42#include <fp_lib_table.h>
43#include <eda_3d_viewer_frame.h>
44
45#include <base_units.h>
46#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
47
56static float TransparencyControl( float aGrayColorValue, float aTransparency )
57{
58 const float aaa = aTransparency * aTransparency * aTransparency;
59
60 // 1.00-1.05*(1.0-x)^3
61 float ca = 1.0f - aTransparency;
62 ca = 1.00f - 1.05f * ca * ca * ca;
63
64 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
65}
66
70#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
71
72
74{
77
80
81 double mmTo3Dunits = pcbIUScale.IU_PER_MM * m_boardAdapter.BiuTo3dUnits();
82
84 {
85 m_boardMaterial = BOARD_NORMAL( 0.40f * mmTo3Dunits );
86 m_copperMaterial = COPPER_NORMAL( 4.0f * mmTo3Dunits, &m_boardMaterial );
87 m_platedCopperMaterial = PLATED_COPPER_NORMAL( 0.5f * mmTo3Dunits );
89 m_plasticMaterial = PLASTIC_NORMAL( 0.05f * mmTo3Dunits );
90 m_shinyPlasticMaterial = PLASTIC_SHINE_NORMAL( 0.1f * mmTo3Dunits );
91 m_brushedMetalMaterial = BRUSHED_METAL_NORMAL( 0.05f * mmTo3Dunits );
92 m_silkScreenMaterial = SILK_SCREEN_NORMAL( 0.25f * mmTo3Dunits );
93 }
94
95 // http://devernay.free.fr/cours/opengl/materials.html
96 // Copper
97 const SFVEC3F copperSpecularLinear =
98 ConvertSRGBToLinear( glm::clamp( (SFVEC3F) m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
99 SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) ) );
100
103 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
104
106 m_materials.m_Copper.SetGenerator( &m_platedCopperMaterial );
107
108 m_materials.m_NonPlatedCopper = BLINN_PHONG_MATERIAL(
109 ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ), SFVEC3F( 0.0f, 0.0f, 0.0f ),
110 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
111
113 m_materials.m_NonPlatedCopper.SetGenerator( &m_copperMaterial );
114
118 SFVEC3F( 0.0f, 0.0f, 0.0f ),
122 0.10f * 128.0f, 0.0f, 0.0f );
123
125 SFVEC3F( 0.0f, 0.0f, 0.0f ),
126 glm::clamp( ( ( SFVEC3F )( 1.0f ) - ConvertSRGBToLinear(
128 SFVEC3F( 0.0f ), SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
129
131 m_materials.m_SilkS.SetGenerator( &m_silkScreenMaterial );
132
133 // Assume that SolderMaskTop == SolderMaskBot
134 const float solderMask_gray =
137 / 3.0f;
138
139 const float solderMask_transparency = TransparencyControl( solderMask_gray,
141
142 m_materials.m_SolderMask = BLINN_PHONG_MATERIAL(
144 SFVEC3F( 0.0f, 0.0f, 0.0f ),
145 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
146 solderMask_transparency, 0.16f );
147
148 m_materials.m_SolderMask.SetCastShadows( true );
149 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
150
152 m_materials.m_SolderMask.SetGenerator( &m_solderMaskMaterial );
153
154 m_materials.m_EpoxyBoard =
155 BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f,
156 10.0f / 255.0f ) ),
157 SFVEC3F( 0.0f, 0.0f, 0.0f ),
158 ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f, 8.0f / 255.0f,
159 10.0f / 255.0f ) ),
160 0.1f * 128.0f, 1.0f - m_boardAdapter.m_BoardBodyColor.a, 0.0f );
161
162 m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
163
165 m_materials.m_EpoxyBoard.SetGenerator( &m_boardMaterial );
166
168
169 m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ),
170 ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
171 0.10f * 128.0f, 0.0f, 0.50f );
172 m_materials.m_Floor.SetCastShadows( false );
173 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
174}
175
176
177void RENDER_3D_RAYTRACE::createObject( CONTAINER_3D& aDstContainer, const OBJECT_2D* aObject2D,
178 float aZMin, float aZMax, const MATERIAL* aMaterial,
179 const SFVEC3F& aObjColor )
180{
181 switch( aObject2D->GetObjectType() )
182 {
184 {
186
187 XY_PLANE* objPtr;
188 objPtr = new XY_PLANE( BBOX_3D(
189 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
190 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
191 objPtr->SetMaterial( aMaterial );
192 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
193 aDstContainer.Add( objPtr );
194
195 objPtr = new XY_PLANE( BBOX_3D(
196 SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
197 SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
198 objPtr->SetMaterial( aMaterial );
199 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
200 aDstContainer.Add( objPtr );
201 break;
202 }
203
205 {
207
208 const ROUND_SEGMENT_2D* aRoundSeg2D = static_cast<const ROUND_SEGMENT_2D*>( aObject2D );
209 ROUND_SEGMENT* objPtr = new ROUND_SEGMENT( *aRoundSeg2D, aZMin, aZMax );
210 objPtr->SetMaterial( aMaterial );
211 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
212 aDstContainer.Add( objPtr );
213 break;
214 }
215
216 default:
217 {
218 LAYER_ITEM* objPtr = new LAYER_ITEM( aObject2D, aZMin, aZMax );
219 objPtr->SetMaterial( aMaterial );
220 objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
221 aDstContainer.Add( objPtr );
222 break;
223 }
224 }
225}
226
227
229 PCB_LAYER_ID aLayer_id,
230 const MATERIAL* aMaterialLayer,
231 const SFVEC3F& aLayerColor,
232 float aLayerZOffset )
233{
234 if( aContainer2d == nullptr )
235 return;
236
237 const LIST_OBJECT2D& listObject2d = aContainer2d->GetList();
238
239 if( listObject2d.size() == 0 )
240 return;
241
242 for( const OBJECT_2D* object2d_A : listObject2d )
243 {
244 // not yet used / implemented (can be used in future to clip the objects in the
245 // board borders
246 OBJECT_2D* object2d_C = CSGITEM_FULL;
247
248 std::vector<const OBJECT_2D*>* object2d_B = CSGITEM_EMPTY;
249
250 object2d_B = new std::vector<const OBJECT_2D*>();
251
252 // Subtract holes but not in SolderPaste
253 // (can be added as an option in future)
254 if( !( aLayer_id == B_Paste || aLayer_id == F_Paste ) )
255 {
256 // Check if there are any layerhole that intersects this object
257 // Eg: a segment is cut by a via hole or THT hole.
259
260 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
261 {
262 const BVH_CONTAINER_2D* holes2d = layerHolesMap.at( aLayer_id );
263
264 CONST_LIST_OBJECT2D intersecting;
265
266 holes2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
267
268 for( const OBJECT_2D* hole2d : intersecting )
269 object2d_B->push_back( hole2d );
270 }
271
272 // Check if there are any THT that intersects this object. If we're processing a silk
273 // layer and the flag is set, then clip the silk at the outer edge of the annular ring,
274 // rather than the at the outer edge of the copper plating.
275 const BVH_CONTAINER_2D& throughHoleOuter =
278 && ( aLayer_id == B_SilkS || aLayer_id == F_SilkS ) ?
281
282 if( !throughHoleOuter.GetList().empty() )
283 {
284 CONST_LIST_OBJECT2D intersecting;
285
286 throughHoleOuter.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
287
288 for( const OBJECT_2D* hole2d : intersecting )
289 object2d_B->push_back( hole2d );
290 }
291 }
292
293 if( !m_antioutlineBoard2dObjects->GetList().empty() )
294 {
295 CONST_LIST_OBJECT2D intersecting;
296
298 intersecting );
299
300 for( const OBJECT_2D* obj : intersecting )
301 object2d_B->push_back( obj );
302 }
303
305
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 layerMask_id = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
312
313 const BVH_CONTAINER_2D* containerMaskLayer2d = mapLayers.at( layerMask_id );
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::Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter,
362 bool aOnlyLoadCopperAndShapes )
363{
364 m_reloadRequested = false;
365
366 m_modelMaterialMap.clear();
367
370
371 unsigned 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 if( !aOnlyLoadCopperAndShapes )
397 {
398 const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
399
400 if( outlineCount > 0 )
401 {
402 float divFactor = 0.0f;
403
405 divFactor = m_boardAdapter.GetAverageViaHoleDiameter() * 18.0f;
406 else if( m_boardAdapter.GetHoleCount() )
407 divFactor = m_boardAdapter.GetAverageHoleDiameter() * 8.0f;
408
410
411 // Calculate an antiboard outline
412 SHAPE_POLY_SET antiboardPoly;
413
415
416 antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
417 antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
418
419 for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
420 {
423 *m_boardAdapter.GetBoard(), ii );
424 }
425
427
428 boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
429
430 for( int ii = 0; ii < outlineCount; ii++ )
431 {
433 m_boardAdapter.BiuTo3dUnits(), divFactor,
434 *m_boardAdapter.GetBoard(), ii );
435 }
436
438 {
439 const LIST_OBJECT2D& listObjects = m_outlineBoard2dObjects->GetList();
440
441 for( const OBJECT_2D* object2d_A : listObjects )
442 {
443 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
444
445 // Check if there are any THT that intersects this outline object part
446 if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
447 {
448 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
449 CONST_LIST_OBJECT2D intersecting;
450
451 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
452
453 for( const OBJECT_2D* hole : intersecting )
454 {
455 if( object2d_A->Intersects( hole->GetBBox() ) )
456 object2d_B->push_back( hole );
457 }
458 }
459
460 if( !m_antioutlineBoard2dObjects->GetList().empty() )
461 {
462 CONST_LIST_OBJECT2D intersecting;
463
465 intersecting );
466
467 for( const OBJECT_2D* obj : intersecting )
468 object2d_B->push_back( obj );
469 }
470
471 if( object2d_B->empty() )
472 {
473 delete object2d_B;
474 object2d_B = CSGITEM_EMPTY;
475 }
476
477 if( object2d_B == CSGITEM_EMPTY )
478 {
479 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
482
483 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
485 m_objectContainer.Add( objPtr );
486 }
487 else
488 {
489
490 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
493
495
496 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
499
500 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
502 m_objectContainer.Add( objPtr );
503 }
504 }
505
506 // Add cylinders of the board body to container
507 // Note: This is actually a workaround for the holes in the board.
508 // The issue is because if a hole is in a border of a divided polygon ( ex
509 // a polygon or dummy block) it will cut also the render of the hole.
510 // So this will add a full hole.
511 // In fact, that is not need if the hole have copper.
512 if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
513 {
515
516 for( const OBJECT_2D* hole2d : holeList )
517 {
518 if( !m_antioutlineBoard2dObjects->GetList().empty() )
519 {
520 CONST_LIST_OBJECT2D intersecting;
521
523 intersecting );
524
525 // Do not add cylinder if it intersects the edge of the board
526 if( !intersecting.empty() )
527 continue;
528 }
529
530 switch( hole2d->GetObjectType() )
531 {
533 {
534 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
535
536 CYLINDER* objPtr = new CYLINDER( hole2d->GetCentroid(),
539 radius );
540
541 objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
543
544 m_objectContainer.Add( objPtr );
545 }
546 break;
547
548 default:
549 break;
550 }
551 }
552 }
553 }
554 }
555 }
556
557 if( aStatusReporter )
558 aStatusReporter->Report( _( "Load Raytracing: layers" ) );
559
560 // Add layers maps (except B_Mask and F_Mask)
561 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry : m_boardAdapter.GetLayerMap() )
562 {
563 const PCB_LAYER_ID layer_id = entry.first;
564 const BVH_CONTAINER_2D* container2d = entry.second;
565
566 // Only process layers that exist
567 if( !container2d )
568 continue;
569
570 if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
571 continue;
572
573 // Mask layers are not processed here because they are a special case
574 if( layer_id == B_Mask || layer_id == F_Mask )
575 continue;
576
577 MATERIAL* materialLayer = &m_materials.m_SilkS;
578 SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
579
580 switch( layer_id )
581 {
582 case B_Adhes:
583 case F_Adhes:
584 break;
585
586 case B_Paste:
587 case F_Paste:
588 materialLayer = &m_materials.m_Paste;
589
592 else
593 layerColor = m_boardAdapter.GetLayerColor( layer_id );
594
595 break;
596
597 case B_SilkS:
598 materialLayer = &m_materials.m_SilkS;
599
602 else
603 layerColor = m_boardAdapter.GetLayerColor( layer_id );
604
605 break;
606
607 case F_SilkS:
608 materialLayer = &m_materials.m_SilkS;
609
612 else
613 layerColor = m_boardAdapter.GetLayerColor( layer_id );
614
615 break;
616
617 case Dwgs_User:
618 case Cmts_User:
619 case Eco1_User:
620 case Eco2_User:
621 case Edge_Cuts:
622 case Margin:
623 break;
624
625 case B_CrtYd:
626 case F_CrtYd:
627 break;
628
629 case B_Fab:
630 case F_Fab:
631 break;
632
633 default:
635 {
637 {
638 layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
639 materialLayer = &m_materials.m_NonPlatedCopper;
640 }
641 else
642 {
643 layerColor = m_boardAdapter.m_CopperColor;
644 materialLayer = &m_materials.m_Copper;
645 }
646 }
647 else
648 {
649 layerColor = m_boardAdapter.GetLayerColor( layer_id );
650 }
651
652 break;
653 }
654
655 createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
656 } // for each layer on map
657
658 // Create plated copper
661 {
665
669 }
670
671 if( !aOnlyLoadCopperAndShapes )
672 {
673 // Add Mask layer
674 // Solder mask layers are "negative" layers so the elements that we have in the container
675 // should remove the board outline. We will check for all objects in the outline if it
676 // intersects any object in the layer container and also any hole.
678 && !m_outlineBoard2dObjects->GetList().empty() )
679 {
680 const MATERIAL* materialLayer = &m_materials.m_SolderMask;
681
682 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry : m_boardAdapter.GetLayerMap() )
683 {
684 const PCB_LAYER_ID layer_id = entry.first;
685 const BVH_CONTAINER_2D* container2d = entry.second;
686
687 // Only process layers that exist
688 if( !container2d )
689 continue;
690
691 // Only get the Solder mask layers (and only if the board has them)
692 if( !( layer_id == B_Mask || layer_id == F_Mask ) )
693 continue;
694
695 SFVEC3F layerColor;
696
698 {
699 if( layer_id == B_Mask )
701 else
703 }
704 else
705 {
706 layerColor = m_boardAdapter.GetLayerColor( layer_id );
707 }
708
709 const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
710 const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
711
712 // Get the outline board objects
713 for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
714 {
715 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
716
717 // Check if there are any THT that intersects this outline object part
718 if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
719 {
720 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
721 CONST_LIST_OBJECT2D intersecting;
722
723 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
724
725 for( const OBJECT_2D* hole : intersecting )
726 {
727 if( object2d_A->Intersects( hole->GetBBox() ) )
728 object2d_B->push_back( hole );
729 }
730 }
731
732 // Check if there are any objects in the layer to subtract with the current
733 // object
734 if( !container2d->GetList().empty() )
735 {
736 CONST_LIST_OBJECT2D intersecting;
737
738 container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
739
740 for( const OBJECT_2D* obj : intersecting )
741 object2d_B->push_back( obj );
742 }
743
744 if( object2d_B->empty() )
745 {
746 delete object2d_B;
747 object2d_B = CSGITEM_EMPTY;
748 }
749
750 if( object2d_B == CSGITEM_EMPTY )
751 {
752#if 0
753 createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
754 materialLayer, layerColor );
755#else
756 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
757
758 objPtr->SetMaterial( materialLayer );
759 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
760
761 m_objectContainer.Add( objPtr );
762#endif
763 }
764 else
765 {
766 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
768 object2d_A->GetBoardItem() );
769
771
772 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
773 objPtr->SetMaterial( materialLayer );
774 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
775
776 m_objectContainer.Add( objPtr );
777 }
778 }
779 }
780 }
781
783 }
784
785#ifdef PRINT_STATISTICS_3D_VIEWER
786 unsigned stats_endConvertTime = GetRunningMicroSecs();
787 unsigned stats_startLoad3DmodelsTime = stats_endConvertTime;
788#endif
789
790 if( aStatusReporter )
791 aStatusReporter->Report( _( "Loading 3D models..." ) );
792
793 load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
794
795#ifdef PRINT_STATISTICS_3D_VIEWER
796 unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs();
797#endif
798
799 if( !aOnlyLoadCopperAndShapes )
800 {
801 // Add floor
803 {
804 BBOX_3D boardBBox = m_boardAdapter.GetBBox();
805
806 if( boardBBox.IsInitialized() )
807 {
808 boardBBox.Scale( 3.0f );
809
810 if( m_objectContainer.GetList().size() > 0 )
811 {
812 BBOX_3D containerBBox = m_objectContainer.GetBBox();
813
814 containerBBox.Scale( 1.3f );
815
816 const SFVEC3F centerBBox = containerBBox.GetCenter();
817
818 // Floor triangles
819 const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
820
821 const SFVEC3F v1 =
822 SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
823 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
824
825 const SFVEC3F v3 =
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 v2 = SFVEC3F( v1.x, v3.y, v1.z );
830 const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
831
833
834 TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
835 TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
836
837 m_objectContainer.Add( newTriangle1 );
838 m_objectContainer.Add( newTriangle2 );
839
840 newTriangle1->SetMaterial( &m_materials.m_Floor );
841 newTriangle2->SetMaterial( &m_materials.m_Floor );
842
843 newTriangle1->SetColor( backgroundColor );
844 newTriangle2->SetColor( backgroundColor );
845
846 // Ceiling triangles
847 const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
848
849 const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
850 const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
851 const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
852 const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
853
854 TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
855 TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
856
857 m_objectContainer.Add( newTriangle3 );
858 m_objectContainer.Add( newTriangle4 );
859
860 newTriangle3->SetMaterial( &m_materials.m_Floor );
861 newTriangle4->SetMaterial( &m_materials.m_Floor );
862
863 newTriangle3->SetColor( backgroundColor );
864 newTriangle4->SetColor( backgroundColor );
865 }
866 }
867 }
868
869 // Init initial lights
870 for( LIGHT* light : m_lights )
871 delete light;
872
873 m_lights.clear();
874
875 auto IsColorZero =
876 []( const SFVEC3F& aSource )
877 {
878 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
879 && ( aSource.b < ( 1.0f / 255.0f ) ) );
880 };
881
882 SFVEC3F cameraLightColor =
884 SFVEC3F topLightColor =
886 SFVEC3F bottomLightColor =
888
889 m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), cameraLightColor );
891
892 if( !IsColorZero( cameraLightColor ) )
893 m_lights.push_back( m_cameraLight );
894
895 const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
896
897 if( !IsColorZero( topLightColor ) )
898 {
899 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
900 +RANGE_SCALE_3D * 2.0f ),
901 topLightColor ) );
902 }
903
904 if( !IsColorZero( bottomLightColor ) )
905 {
906 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
907 -RANGE_SCALE_3D * 2.0f ),
908 bottomLightColor ) );
909 }
910
911 for( size_t i = 0; i < m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
912 {
913 SFVEC3F lightColor =
915
916 if( !IsColorZero( lightColor ) )
917 {
919
920 m_lights.push_back( new DIRECTIONAL_LIGHT(
921 SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
922 lightColor ) );
923 }
924 }
925 }
926
927 // Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
928 // class would require reimplementing bounding box calculation (feel free to do this if you
929 // have time and patience).
930 if( m_objectContainer.GetList().size() > 0 )
931 {
932 float ratio =
935
937 / -m_camera.GetCameraInitPos().z ) );
938 }
939
940 // Create an accelerator
941 delete m_accelerator;
943
944 if( aStatusReporter )
945 {
946 // Calculation time in seconds
947 double calculation_time = (double) GetRunningMicroSecs() - stats_startReloadTime / 1e6;
948
949 aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
950 }
951}
952
953
955{
956 PCB_LAYER_ID top_layer, bottom_layer;
957 int radiusBUI = ( aVia->GetDrillValue() / 2 );
958
959 aVia->LayerPair( &top_layer, &bottom_layer );
960
961 float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
963
964 float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
966
967 const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
968 -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
969
970 RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
972 * m_boardAdapter.BiuTo3dUnits(), *aVia );
973
975
976 LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
977
978 objPtr->SetMaterial( &m_materials.m_Copper );
979
982 else if( aVia->GetViaType() == VIATYPE::MICROVIA )
984 else if( aVia->GetViaType() == VIATYPE::BLIND_BURIED )
986 else
988
989 m_objectContainer.Add( objPtr );
990}
991
992
994{
995 const OBJECT_2D* object2d_A = nullptr;
996
997 SFVEC3F objColor;
998
1000 objColor = m_boardAdapter.m_CopperColor;
1001 else
1003
1004 const VECTOR2I drillsize = aPad->GetDrillSize();
1005 const bool hasHole = drillsize.x && drillsize.y;
1006
1007 if( !hasHole )
1008 return;
1009
1010 CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1011
1012 const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
1014
1015 const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
1017
1018 if( drillsize.x == drillsize.y ) // usual round hole
1019 {
1022
1023 int innerRadius = drillsize.x / 2;
1024 int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1025
1026 RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1027 outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1028
1030
1031 object2d_A = ring;
1032
1033 // If the object (ring) is intersected by an antioutline board,
1034 // it will use instead a CSG of two circles.
1035 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1036 {
1038 antiOutlineIntersectionList );
1039 }
1040
1041 if( !antiOutlineIntersectionList.empty() )
1042 {
1043 FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1044 center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1045
1046 FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1047 center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1048 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1049 object2d_B->push_back( innerCircle );
1050
1051 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1052 *aPad );
1053
1055 m_containerWithObjectsToDelete.Add( innerCircle );
1056 m_containerWithObjectsToDelete.Add( outterCircle );
1057
1058 object2d_A = itemCSG2d;
1059 }
1060 }
1061 else // Oblong hole
1062 {
1063 VECTOR2I ends_offset;
1064 int width;
1065
1066 if( drillsize.x > drillsize.y ) // Horizontal oval
1067 {
1068 ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1069 width = drillsize.y;
1070 }
1071 else // Vertical oval
1072 {
1073 ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1074 width = drillsize.x;
1075 }
1076
1077 RotatePoint( ends_offset, aPad->GetOrientation() );
1078
1079 VECTOR2I start = VECTOR2I( aPad->GetPosition() ) + ends_offset;
1080 VECTOR2I end = VECTOR2I( aPad->GetPosition() ) - ends_offset;
1081
1082 ROUND_SEGMENT_2D* innerSeg =
1084 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1086 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1087 width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1088
1089 ROUND_SEGMENT_2D* outerSeg =
1091 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1093 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1094 ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1095 * m_boardAdapter.BiuTo3dUnits(), *aPad );
1096
1097 // NOTE: the round segment width is the "diameter", so we double the thickness
1098 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1099 object2d_B->push_back( innerSeg );
1100
1101 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1102
1106
1107 object2d_A = itemCSG2d;
1108
1109 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1110 {
1112 antiOutlineIntersectionList );
1113 }
1114 }
1115
1116 if( object2d_A )
1117 {
1118 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1119
1120 // Check if there are any other THT that intersects this hole
1121 // It will use the non inflated holes
1122 if( !m_boardAdapter.GetThroughHoleIds().GetList().empty() )
1123 {
1124 CONST_LIST_OBJECT2D intersecting;
1125
1127 intersecting );
1128
1129 for( const OBJECT_2D* hole2d : intersecting )
1130 {
1131 if( object2d_A->Intersects( hole2d->GetBBox() ) )
1132 object2d_B->push_back( hole2d );
1133 }
1134 }
1135
1136 for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1137 object2d_B->push_back( obj );
1138
1139 if( object2d_B->empty() )
1140 {
1141 delete object2d_B;
1142 object2d_B = CSGITEM_EMPTY;
1143 }
1144
1145 if( object2d_B == CSGITEM_EMPTY )
1146 {
1147 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1148
1149 objPtr->SetMaterial( &m_materials.m_Copper );
1150 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1151 m_objectContainer.Add( objPtr );
1152 }
1153 else
1154 {
1155 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1156 *aPad );
1157
1159
1160 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1161
1162 objPtr->SetMaterial( &m_materials.m_Copper );
1163 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1164
1165 m_objectContainer.Add( objPtr );
1166 }
1167 }
1168}
1169
1170
1172{
1173 if( !m_boardAdapter.GetBoard() )
1174 return;
1175
1176 // Insert plated vertical holes inside the board
1177
1178 // Insert vias holes (vertical cylinders)
1179 for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1180 {
1181 if( track->Type() == PCB_VIA_T )
1182 {
1183 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1184 insertHole( via );
1185 }
1186 }
1187
1188 // Insert pads holes (vertical cylinders)
1189 for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1190 {
1191 for( PAD* pad : footprint->Pads() )
1192 {
1193 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1194 insertHole( pad );
1195 }
1196 }
1197}
1198
1199
1200void RENDER_3D_RAYTRACE::load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMaterialInformation )
1201{
1202 if( !m_boardAdapter.GetBoard() )
1203 return;
1204
1208 {
1209 return;
1210 }
1211
1212 // Go for all footprints
1214 {
1215 if( !fp->Models().empty()
1216 && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1217 {
1218 double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1219
1220 VECTOR2I pos = fp->GetPosition();
1221
1222 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1223
1224 fpMatrix = glm::translate( fpMatrix,
1226 -pos.y * m_boardAdapter.BiuTo3dUnits(),
1227 zpos ) );
1228
1229 if( !fp->GetOrientation().IsZero() )
1230 {
1231 fpMatrix = glm::rotate( fpMatrix, (float) fp->GetOrientation().AsRadians(),
1232 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1233 }
1234
1235 if( fp->IsFlipped() )
1236 {
1237 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1238
1239 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1240 }
1241
1242 const double modelunit_to_3d_units_factor =
1244
1245 fpMatrix = glm::scale(
1246 fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1247 modelunit_to_3d_units_factor ) );
1248
1249 BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( fp );
1250
1251 // Get the list of model files for this model
1253 auto sM = fp->Models().begin();
1254 auto eM = fp->Models().end();
1255
1256 wxString libraryName = fp->GetFPID().GetLibNickname();
1257
1258 wxString footprintBasePath = wxEmptyString;
1260 {
1261 try
1262 {
1263 // FindRow() can throw an exception
1264 const FP_LIB_TABLE_ROW* fpRow =
1266 libraryName, false );
1267
1268 if( fpRow )
1269 footprintBasePath = fpRow->GetFullURI( true );
1270 }
1271 catch( ... )
1272 {
1273 // Do nothing if the libraryName is not found in lib table
1274 }
1275 }
1276
1277 while( sM != eM )
1278 {
1279 if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
1280 && ( sM->m_Show && !sM->m_Filename.empty() ) )
1281 {
1282 // get it from cache
1283 const S3DMODEL* modelPtr =
1284 cacheMgr->GetModel( sM->m_Filename, footprintBasePath );
1285
1286 // only add it if the return is not NULL.
1287 if( modelPtr )
1288 {
1289 glm::mat4 modelMatrix = fpMatrix;
1290
1291 modelMatrix = glm::translate( modelMatrix,
1292 SFVEC3F( sM->m_Offset.x, sM->m_Offset.y, sM->m_Offset.z ) );
1293
1294 modelMatrix = glm::rotate( modelMatrix,
1295 (float) -( sM->m_Rotation.z / 180.0f ) * glm::pi<float>(),
1296 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1297
1298 modelMatrix = glm::rotate( modelMatrix,
1299 (float) -( sM->m_Rotation.y / 180.0f ) * glm::pi<float>(),
1300 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1301
1302 modelMatrix = glm::rotate( modelMatrix,
1303 (float) -( sM->m_Rotation.x / 180.0f ) * glm::pi<float>(),
1304 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1305
1306 modelMatrix = glm::scale( modelMatrix,
1307 SFVEC3F( sM->m_Scale.x, sM->m_Scale.y, sM->m_Scale.z ) );
1308
1309 addModels( aDstContainer, modelPtr, modelMatrix, (float) sM->m_Opacity,
1310 aSkipMaterialInformation, boardItem );
1311 }
1312 }
1313
1314 ++sM;
1315 }
1316 }
1317 }
1318}
1319
1320
1322{
1323 MODEL_MATERIALS* materialVector;
1324
1325 // Try find if the materials already exists in the map list
1326 if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1327 {
1328 // Found it, so get the pointer
1329 materialVector = &m_modelMaterialMap[a3DModel];
1330 }
1331 else
1332 {
1333 // Materials was not found in the map, so it will create a new for
1334 // this model.
1335
1336 m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1337 materialVector = &m_modelMaterialMap[a3DModel];
1338
1339 materialVector->resize( a3DModel->m_MaterialsSize );
1340
1341 for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1342 {
1344 {
1345 const SMATERIAL& material = a3DModel->m_Materials[imat];
1346
1347 // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1348
1349 float reflectionFactor = 0.0f;
1350
1351 if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1352 {
1353 reflectionFactor = glm::clamp(
1354 glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1355 0.5f );
1356 }
1357
1358 BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1359
1360 blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1361 ConvertSRGBToLinear( material.m_Emissive ),
1362 ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1363 material.m_Transparency, reflectionFactor );
1364
1366 {
1367 // Guess material type and apply a normal perturbator
1368 if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1369 && ( material.m_Shininess < 0.36f )
1370 && ( material.m_Transparency == 0.0f )
1371 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1372 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1373 < 0.15f )
1374 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1375 < 0.15f ) ) )
1376 {
1377 // This may be a black plastic..
1378 blinnMaterial.SetGenerator( &m_plasticMaterial );
1379 }
1380 else
1381 {
1382 if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1383 && ( material.m_Shininess < 0.30f )
1384 && ( material.m_Transparency == 0.0f )
1385 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1386 || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1387 || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1388 > 0.25f ) ) )
1389 {
1390 // This may be a color plastic ...
1391 blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1392 }
1393 else
1394 {
1395 if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1396 && ( material.m_Shininess > 0.35f )
1397 && ( material.m_Transparency == 0.0f )
1398 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1399 < 0.40f )
1400 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1401 < 0.40f )
1402 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1403 < 0.40f ) ) )
1404 {
1405 // This may be a brushed metal
1406 blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1407 }
1408 }
1409 }
1410 }
1411 }
1412 else
1413 {
1414 ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1415 SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1416 }
1417 }
1418 }
1419
1420 return materialVector;
1421}
1422
1423
1424void RENDER_3D_RAYTRACE::addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
1425 const glm::mat4& aModelMatrix, float aFPOpacity,
1426 bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem )
1427{
1428 // Validate a3DModel pointers
1429 wxASSERT( a3DModel != nullptr );
1430
1431 if( a3DModel == nullptr )
1432 return;
1433
1434 wxASSERT( a3DModel->m_Materials != nullptr );
1435 wxASSERT( a3DModel->m_Meshes != nullptr );
1436 wxASSERT( a3DModel->m_MaterialsSize > 0 );
1437 wxASSERT( a3DModel->m_MeshesSize > 0 );
1438 wxASSERT( aFPOpacity > 0.0f );
1439 wxASSERT( aFPOpacity <= 1.0f );
1440
1441 if( aFPOpacity > 1.0f )
1442 {
1443 aFPOpacity = 1.0f;
1444 }
1445
1446 if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1447 && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1448 {
1449 MODEL_MATERIALS* materialVector = nullptr;
1450
1451 if( !aSkipMaterialInformation )
1452 {
1453 materialVector = getModelMaterial( a3DModel );
1454 }
1455
1456 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1457
1458 for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1459 {
1460 const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1461
1462 // Validate the mesh pointers
1463 wxASSERT( mesh.m_Positions != nullptr );
1464 wxASSERT( mesh.m_FaceIdx != nullptr );
1465 wxASSERT( mesh.m_Normals != nullptr );
1466 wxASSERT( mesh.m_FaceIdxSize > 0 );
1467 wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1468
1469
1470 if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1471 && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1472 && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1473 && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1474 {
1475 float fpTransparency;
1476 const BLINN_PHONG_MATERIAL* blinn_material;
1477
1478 if( !aSkipMaterialInformation )
1479 {
1480 blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1481
1482 fpTransparency =
1483 1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1484 }
1485
1486 // Add all face triangles
1487 for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1488 {
1489 const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1490 const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1491 const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1492
1493 wxASSERT( idx0 < mesh.m_VertexSize );
1494 wxASSERT( idx1 < mesh.m_VertexSize );
1495 wxASSERT( idx2 < mesh.m_VertexSize );
1496
1497 if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1498 && ( idx2 < mesh.m_VertexSize ) )
1499 {
1500 const SFVEC3F& v0 = mesh.m_Positions[idx0];
1501 const SFVEC3F& v1 = mesh.m_Positions[idx1];
1502 const SFVEC3F& v2 = mesh.m_Positions[idx2];
1503
1504 const SFVEC3F& n0 = mesh.m_Normals[idx0];
1505 const SFVEC3F& n1 = mesh.m_Normals[idx1];
1506 const SFVEC3F& n2 = mesh.m_Normals[idx2];
1507
1508 // Transform vertex with the model matrix
1509 const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1510 const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1511 const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1512
1513 const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1514 const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1515 const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1516
1517 TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1518
1519 newTriangle->SetBoardItem( aBoardItem );
1520
1521 aDstContainer.Add( newTriangle );
1522
1523 if( !aSkipMaterialInformation )
1524 {
1525 newTriangle->SetMaterial( blinn_material );
1526 newTriangle->SetModelTransparency( fpTransparency );
1527
1528 if( mesh.m_Color == nullptr )
1529 {
1530 const SFVEC3F diffuseColor =
1531 a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1532
1534 newTriangle->SetColor( ConvertSRGBToLinear(
1535 MaterialDiffuseToColorCAD( diffuseColor ) ) );
1536 else
1537 newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1538 }
1539 else
1540 {
1542 {
1543 newTriangle->SetColor(
1545 mesh.m_Color[idx0] ) ),
1547 mesh.m_Color[idx1] ) ),
1549 mesh.m_Color[idx2] ) ) );
1550 }
1551 else
1552 {
1553 newTriangle->SetColor(
1554 ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1555 ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1556 ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1557 }
1558 }
1559 }
1560 }
1561 }
1562 }
1563 }
1564 }
1565}
@ NORMAL
Use all material properties from model file.
@ CAD_MODE
Use a gray shading based on diffuse material.
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:109
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:54
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:62
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
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.
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
const BVH_CONTAINER_2D & GetThroughHoleIds() const noexcept
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.
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
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 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 )
SFVEC4F GetItemColor(int aItemId) const
Get the technical color of a layer.
const BVH_CONTAINER_2D * GetPlatedPadsFront() const noexcept
const BVH_CONTAINER_2D & GetThroughHoleAnnularRings() 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
const BVH_CONTAINER_2D & GetThroughHoleOds() const noexcept
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
Get the technical color of a layer.
S3D_CACHE * Get3dCacheManager() const noexcept
Definition: board_adapter.h:81
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
FOOTPRINTS & Footprints()
Definition: board.h:307
TRACKS & Tracks()
Definition: board.h:304
PROJECT * GetProject() const
Definition: board.h:440
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:195
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: camera.cpp:124
float GetMaxZoom()
Definition: camera.h:201
void SetMaxZoom(float maxZoom)
Definition: camera.h:202
const SFVEC3F & GetCameraInitPos() const
Definition: camera.h:141
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 th...
Definition: fp_lib_table.h:41
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
const void SetBoardItem(BOARD_ITEM *aBoardItem)
Definition: object_3d.h:55
void SetModelTransparency(float aModelTransparency)
Definition: object_3d.h:66
Definition: pad.h:59
const VECTOR2I & GetDrillSize() const
Definition: pad.h:262
VECTOR2I GetPosition() const override
Definition: pad.h:197
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:365
const VECTOR2I & GetStart() const
Definition: pcb_track.h:112
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:192
VIATYPE GetViaType() const
Definition: pcb_track.h:390
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: pcb_track.cpp:542
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
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:319
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
bool m_reloadRequested
The window size that this camera is working.
BOARD_ADAPTER & m_boardAdapter
DIRECTIONAL_LIGHT * m_cameraLight
PLATED_COPPER_NORMAL m_platedCopperMaterial
SOLDER_MASK_NORMAL m_solderMaskMaterial
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation)
unsigned int m_converted2dRoundSegmentCount
void createItemsFromContainer(const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
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.
MODEL_MATERIALS * getModelMaterial(const S3DMODEL *a3DModel)
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
CONTAINER_2D * m_outlineBoard2dObjects
struct RENDER_3D_RAYTRACE::@5 m_materials
ACCELERATOR_3D * m_accelerator
unsigned int m_convertedDummyBlockCount
void addModels(CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
PLASTIC_NORMAL m_plasticMaterial
SILK_SCREEN_NORMAL m_silkScreenMaterial
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.
BOARD_NORMAL m_boardMaterial
CONTAINER_2D m_containerWithObjectsToDelete
std::list< LIGHT * > m_lights
static constexpr float MIN_DISTANCE_IU
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
void insertHole(const PCB_VIA *aVia)
COPPER_NORMAL m_copperMaterial
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:645
Represent a set of closed polygons.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
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:62
T x
Definition: vector3.h:61
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)
FOOTPRINT_ATTR_T
The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes() and FOOTPRINT::Get...
Definition: footprint.h:67
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:825
@ LAYER_PADS_TH
multilayer pads, usually with holes
Definition: layer_ids.h:213
@ LAYER_VIA_MICROVIA
to draw micro vias
Definition: layer_ids.h:194
@ LAYER_VIAS
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:193
@ LAYER_VIA_BBLIND
to draw blind/buried vias
Definition: layer_ids.h:195
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ 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
@ Margin
Definition: layer_ids.h:114
@ 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
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
@ NPTH
like PAD_PTH, but not plated
@ BLIND_BURIED
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
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
#define UNITS3D_TO_UNITSPCB
Scale conversion from 3d model units to pcb units.
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 int scale
const SFVEC2F & Min() const
Definition: bbox_2d.h:167
const SFVEC2F & Max() const
Definition: bbox_2d.h:172
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:183
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:190
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:77
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
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
v1
VECTOR3I v3(1, 1, 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)
Definition: trigo.cpp:183
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44