KiCad PCB EDA Suite
Loading...
Searching...
No Matches
raytracing/create_scene.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2022 Mario Luzeiro <[email protected]>
5 * Copyright (C) 2023 CERN
6 * Copyright 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:
636 {
637 layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
638 materialLayer = &m_materials.m_NonPlatedCopper;
639 }
640 else
641 {
642 layerColor = m_boardAdapter.m_CopperColor;
643 materialLayer = &m_materials.m_Copper;
644 }
645
646 break;
647 }
648
649 createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
650 } // for each layer on map
651
652 // Create plated copper
654 {
658
662 }
663
664 if( !aOnlyLoadCopperAndShapes )
665 {
666 // Add Mask layer
667 // Solder mask layers are "negative" layers so the elements that we have in the container
668 // should remove the board outline. We will check for all objects in the outline if it
669 // intersects any object in the layer container and also any hole.
670 if( ( layerFlags.test( LAYER_3D_SOLDERMASK_TOP )
671 || layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
672 && !m_outlineBoard2dObjects->GetList().empty() )
673 {
674 const MATERIAL* materialLayer = &m_materials.m_SolderMask;
675
676 for( const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
678 {
679 const PCB_LAYER_ID layer_id = entry.first;
680 const BVH_CONTAINER_2D* container2d = entry.second;
681
682 // Only process layers that exist
683 if( !container2d )
684 continue;
685
686 // Only get the Solder mask layers (and only if the board has them)
687 if( layer_id == F_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_TOP ) )
688 continue;
689
690 if( layer_id == B_Mask && !layerFlags.test( LAYER_3D_SOLDERMASK_BOTTOM ) )
691 continue;
692
693 // Only Mask layers are processed here because they are negative layers
694 if( layer_id != F_Mask && layer_id != B_Mask )
695 continue;
696
697 SFVEC3F layerColor;
698
699 if( layer_id == B_Mask )
701 else
703
704 const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
705 const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
706
707 // Get the outline board objects
708 for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
709 {
710 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
711
712 // Check if there are any THT that intersects this outline object part
713 if( !m_boardAdapter.GetTH_ODs().GetList().empty() )
714 {
715 const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetTH_ODs();
716 CONST_LIST_OBJECT2D intersecting;
717
718 throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
719
720 for( const OBJECT_2D* hole : intersecting )
721 {
722 if( object2d_A->Intersects( hole->GetBBox() ) )
723 object2d_B->push_back( hole );
724 }
725 }
726
727 // Check if there are any objects in the layer to subtract with the current
728 // object
729 if( !container2d->GetList().empty() )
730 {
731 CONST_LIST_OBJECT2D intersecting;
732
733 container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
734
735 for( const OBJECT_2D* obj : intersecting )
736 object2d_B->push_back( obj );
737 }
738
739 if( object2d_B->empty() )
740 {
741 delete object2d_B;
742 object2d_B = CSGITEM_EMPTY;
743 }
744
745 if( object2d_B == CSGITEM_EMPTY )
746 {
747#if 0
748 createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
749 materialLayer, layerColor );
750#else
751 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
752
753 objPtr->SetMaterial( materialLayer );
754 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
755
756 m_objectContainer.Add( objPtr );
757#endif
758 }
759 else
760 {
761 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
763 object2d_A->GetBoardItem() );
764
766
767 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
768 objPtr->SetMaterial( materialLayer );
769 objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
770
771 m_objectContainer.Add( objPtr );
772 }
773 }
774 }
775 }
776
778 }
779
780#ifdef PRINT_STATISTICS_3D_VIEWER
781 int64_t stats_endConvertTime = GetRunningMicroSecs();
782 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
783#endif
784
785 if( aStatusReporter )
786 aStatusReporter->Report( _( "Loading 3D models..." ) );
787
788 load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
789
790#ifdef PRINT_STATISTICS_3D_VIEWER
791 int64_t stats_endLoad3DmodelsTime = GetRunningMicroSecs();
792#endif
793
794 if( !aOnlyLoadCopperAndShapes )
795 {
796 // Add floor
798 {
799 BBOX_3D boardBBox = m_boardAdapter.GetBBox();
800
801 if( boardBBox.IsInitialized() )
802 {
803 boardBBox.Scale( 3.0f );
804
805 if( m_objectContainer.GetList().size() > 0 )
806 {
807 BBOX_3D containerBBox = m_objectContainer.GetBBox();
808
809 containerBBox.Scale( 1.3f );
810
811 const SFVEC3F centerBBox = containerBBox.GetCenter();
812
813 // Floor triangles
814 const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
815
816 const SFVEC3F v1 =
817 SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
818 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
819
820 const SFVEC3F v3 =
821 SFVEC3F( +RANGE_SCALE_3D * 4.0f, +RANGE_SCALE_3D * 4.0f, minZ )
822 + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
823
824 const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
825 const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
826
828
829 TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
830 TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
831
832 m_objectContainer.Add( newTriangle1 );
833 m_objectContainer.Add( newTriangle2 );
834
835 newTriangle1->SetMaterial( &m_materials.m_Floor );
836 newTriangle2->SetMaterial( &m_materials.m_Floor );
837
838 newTriangle1->SetColor( floorColor );
839 newTriangle2->SetColor( floorColor );
840
841 // Ceiling triangles
842 const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
843
844 const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
845 const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
846 const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
847 const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
848
849 TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
850 TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
851
852 m_objectContainer.Add( newTriangle3 );
853 m_objectContainer.Add( newTriangle4 );
854
855 newTriangle3->SetMaterial( &m_materials.m_Floor );
856 newTriangle4->SetMaterial( &m_materials.m_Floor );
857
858 newTriangle3->SetColor( floorColor );
859 newTriangle4->SetColor( floorColor );
860 }
861 }
862 }
863
864 // Init initial lights
865 for( LIGHT* light : m_lights )
866 delete light;
867
868 m_lights.clear();
869
870 auto IsColorZero =
871 []( const SFVEC3F& aSource )
872 {
873 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
874 && ( aSource.b < ( 1.0f / 255.0f ) ) );
875 };
876
877 SFVEC3F cameraLightColor =
879 SFVEC3F topLightColor =
881 SFVEC3F bottomLightColor =
883
884 m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), cameraLightColor );
886
887 if( !IsColorZero( cameraLightColor ) )
888 m_lights.push_back( m_cameraLight );
889
890 const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
891
892 if( !IsColorZero( topLightColor ) )
893 {
894 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
895 +RANGE_SCALE_3D * 2.0f ),
896 topLightColor ) );
897 }
898
899 if( !IsColorZero( bottomLightColor ) )
900 {
901 m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
902 -RANGE_SCALE_3D * 2.0f ),
903 bottomLightColor ) );
904 }
905
906 for( size_t i = 0; i < m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
907 {
908 SFVEC3F lightColor =
910
911 if( !IsColorZero( lightColor ) )
912 {
914
915 m_lights.push_back( new DIRECTIONAL_LIGHT(
916 SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
917 lightColor ) );
918 }
919 }
920 }
921
922 // Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
923 // class would require reimplementing bounding box calculation (feel free to do this if you
924 // have time and patience).
925 if( m_objectContainer.GetList().size() > 0 )
926 {
927 float ratio =
929
930 float max_zoom = CAMERA::DEFAULT_MAX_ZOOM * ratio;
931 float min_zoom = static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
932 / -m_camera.GetCameraInitPos().z );
933
934 if( min_zoom > max_zoom )
935 std::swap( min_zoom, max_zoom );
936
937 float zoom_ratio = max_zoom / min_zoom;
938
939 // Set the minimum number of zoom 'steps' between max and min.
940 int steps = 3 * 3;
941 steps -= static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
942 steps = std::max( steps, 0 );
943
944 // Resize max and min zoom to accomplish the number of steps.
945 float increased_zoom = pow( 1.26f, steps / 2 );
946 max_zoom *= increased_zoom;
947 min_zoom /= increased_zoom;
948
949 if( steps & 1 )
950 min_zoom /= 1.26f;
951
952 min_zoom = std::min( min_zoom, 1.0f );
953
954 m_camera.SetMaxZoom( max_zoom );
955 m_camera.SetMinZoom( min_zoom );
956 }
957
958 // Create an accelerator
959 delete m_accelerator;
960 m_accelerator = new BVH_PBRT( m_objectContainer, 8, SPLITMETHOD::MIDDLE );
961
962 if( aStatusReporter )
963 {
964 // Calculation time in seconds
965 double calculation_time = (double) ( GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
966
967 aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
968 }
969}
970
971
973{
974 PCB_LAYER_ID top_layer, bottom_layer;
975 int radiusBUI = ( aVia->GetDrillValue() / 2 );
976
977 aVia->LayerPair( &top_layer, &bottom_layer );
978
979 float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
981
982 float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
984
985 const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
986 -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
987
988 RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
990 * m_boardAdapter.BiuTo3dUnits(), *aVia );
991
993
994 LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
995
996 objPtr->SetMaterial( &m_materials.m_Copper );
998
999 m_objectContainer.Add( objPtr );
1000}
1001
1002
1004{
1005 const OBJECT_2D* object2d_A = nullptr;
1006
1008 const VECTOR2I drillsize = aPad->GetDrillSize();
1009 const bool hasHole = drillsize.x && drillsize.y;
1010
1011 if( !hasHole )
1012 return;
1013
1014 CONST_LIST_OBJECT2D antiOutlineIntersectionList;
1015
1016 const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
1018
1019 const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
1021
1022 if( drillsize.x == drillsize.y ) // usual round hole
1023 {
1026
1027 int innerRadius = drillsize.x / 2;
1028 int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1029
1030 RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1031 outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1032
1034
1035 object2d_A = ring;
1036
1037 // If the object (ring) is intersected by an antioutline board,
1038 // it will use instead a CSG of two circles.
1039 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1040 {
1042 antiOutlineIntersectionList );
1043 }
1044
1045 if( !antiOutlineIntersectionList.empty() )
1046 {
1047 FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1048 center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1049
1050 FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1051 center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1052 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1053 object2d_B->push_back( innerCircle );
1054
1055 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1056 *aPad );
1057
1059 m_containerWithObjectsToDelete.Add( innerCircle );
1060 m_containerWithObjectsToDelete.Add( outterCircle );
1061
1062 object2d_A = itemCSG2d;
1063 }
1064 }
1065 else // Oblong hole
1066 {
1067 VECTOR2I ends_offset;
1068 int width;
1069
1070 if( drillsize.x > drillsize.y ) // Horizontal oval
1071 {
1072 ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1073 width = drillsize.y;
1074 }
1075 else // Vertical oval
1076 {
1077 ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1078 width = drillsize.x;
1079 }
1080
1081 RotatePoint( ends_offset, aPad->GetOrientation() );
1082
1083 VECTOR2I start = VECTOR2I( aPad->GetPosition() ) + ends_offset;
1084 VECTOR2I end = VECTOR2I( aPad->GetPosition() ) - ends_offset;
1085
1086 ROUND_SEGMENT_2D* innerSeg =
1088 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1090 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1091 width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1092
1093 ROUND_SEGMENT_2D* outerSeg =
1095 -start.y * m_boardAdapter.BiuTo3dUnits() ),
1097 -end.y * m_boardAdapter.BiuTo3dUnits() ),
1098 ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1099 * m_boardAdapter.BiuTo3dUnits(), *aPad );
1100
1101 // NOTE: the round segment width is the "diameter", so we double the thickness
1102 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1103 object2d_B->push_back( innerSeg );
1104
1105 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1106
1110
1111 object2d_A = itemCSG2d;
1112
1113 if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1114 {
1116 antiOutlineIntersectionList );
1117 }
1118 }
1119
1120 if( object2d_A )
1121 {
1122 std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1123
1124 // Check if there are any other THT that intersects this hole
1125 // It will use the non inflated holes
1126 if( !m_boardAdapter.GetTH_IDs().GetList().empty() )
1127 {
1128 CONST_LIST_OBJECT2D intersecting;
1129
1130 m_boardAdapter.GetTH_IDs().GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
1131
1132 for( const OBJECT_2D* hole2d : intersecting )
1133 {
1134 if( object2d_A->Intersects( hole2d->GetBBox() ) )
1135 object2d_B->push_back( hole2d );
1136 }
1137 }
1138
1139 for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1140 object2d_B->push_back( obj );
1141
1142 if( object2d_B->empty() )
1143 {
1144 delete object2d_B;
1145 object2d_B = CSGITEM_EMPTY;
1146 }
1147
1148 if( object2d_B == CSGITEM_EMPTY )
1149 {
1150 LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1151
1152 objPtr->SetMaterial( &m_materials.m_Copper );
1153 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1154 m_objectContainer.Add( objPtr );
1155 }
1156 else
1157 {
1158 LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1159 *aPad );
1160
1162
1163 LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1164
1165 objPtr->SetMaterial( &m_materials.m_Copper );
1166 objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1167
1168 m_objectContainer.Add( objPtr );
1169 }
1170 }
1171}
1172
1173
1175{
1176 if( !m_boardAdapter.GetBoard() )
1177 return;
1178
1179 // Insert plated vertical holes inside the board
1180
1181 // Insert vias holes (vertical cylinders)
1182 for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1183 {
1184 if( track->Type() == PCB_VIA_T )
1185 {
1186 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1187 insertHole( via );
1188 }
1189 }
1190
1191 // Insert pads holes (vertical cylinders)
1192 for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1193 {
1194 for( PAD* pad : footprint->Pads() )
1195 {
1196 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1197 insertHole( pad );
1198 }
1199 }
1200}
1201
1202
1204 bool aSkipMaterialInformation )
1205{
1206 if( !m_boardAdapter.GetBoard() )
1207 return;
1208
1213 {
1214 return;
1215 }
1216
1217 // Go for all footprints
1219 {
1220 if( !fp->Models().empty()
1221 && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1222 {
1223 double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1224
1225 VECTOR2I pos = fp->GetPosition();
1226
1227 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1228
1229 fpMatrix = glm::translate( fpMatrix,
1231 -pos.y * m_boardAdapter.BiuTo3dUnits(),
1232 zpos ) );
1233
1234 if( !fp->GetOrientation().IsZero() )
1235 {
1236 fpMatrix = glm::rotate( fpMatrix, (float) fp->GetOrientation().AsRadians(),
1237 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1238 }
1239
1240 if( fp->IsFlipped() )
1241 {
1242 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1243
1244 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1245 }
1246
1247 const double modelunit_to_3d_units_factor =
1249
1250 fpMatrix = glm::scale(
1251 fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1252 modelunit_to_3d_units_factor ) );
1253
1254 // Get the list of model files for this model
1256
1257 wxString libraryName = fp->GetFPID().GetLibNickname();
1258
1259 wxString footprintBasePath = wxEmptyString;
1260
1262 {
1263 try
1264 {
1265 // FindRow() can throw an exception
1266 const FP_LIB_TABLE_ROW* fpRow =
1268 ->FindRow( libraryName, false );
1269
1270 if( fpRow )
1271 footprintBasePath = fpRow->GetFullURI( true );
1272 }
1273 catch( ... )
1274 {
1275 // Do nothing if the libraryName is not found in lib table
1276 }
1277 }
1278
1279 for( FP_3DMODEL& model : fp->Models() )
1280 {
1281 // get it from cache
1282 const S3DMODEL* modelPtr =
1283 cacheMgr->GetModel( model.m_Filename, footprintBasePath, fp );
1284
1285 // only add it if the return is not NULL.
1286 if( modelPtr )
1287 {
1288 glm::mat4 modelMatrix = fpMatrix;
1289
1290 modelMatrix = glm::translate( modelMatrix,
1291 SFVEC3F( model.m_Offset.x, model.m_Offset.y, model.m_Offset.z ) );
1292
1293 modelMatrix = glm::rotate( modelMatrix,
1294 (float) -( model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
1295 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1296
1297 modelMatrix = glm::rotate( modelMatrix,
1298 (float) -( model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
1299 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1300
1301 modelMatrix = glm::rotate( modelMatrix,
1302 (float) -( model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
1303 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1304
1305 modelMatrix = glm::scale( modelMatrix,
1306 SFVEC3F( model.m_Scale.x, model.m_Scale.y, model.m_Scale.z ) );
1307
1308 addModels( aDstContainer, modelPtr, modelMatrix, (float) model.m_Opacity,
1309 aSkipMaterialInformation, fp );
1310 }
1311 }
1312 }
1313 }
1314}
1315
1316
1318{
1319 MODEL_MATERIALS* materialVector;
1320
1321 // Try find if the materials already exists in the map list
1322 if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1323 {
1324 // Found it, so get the pointer
1325 materialVector = &m_modelMaterialMap[a3DModel];
1326 }
1327 else
1328 {
1329 // Materials was not found in the map, so it will create a new for
1330 // this model.
1331
1332 m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1333 materialVector = &m_modelMaterialMap[a3DModel];
1334
1335 materialVector->resize( a3DModel->m_MaterialsSize );
1336
1337 for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1338 {
1339 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::NORMAL )
1340 {
1341 const SMATERIAL& material = a3DModel->m_Materials[imat];
1342
1343 // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1344
1345 float reflectionFactor = 0.0f;
1346
1347 if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1348 {
1349 reflectionFactor = glm::clamp(
1350 glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1351 0.5f );
1352 }
1353
1354 BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1355
1356 blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1357 ConvertSRGBToLinear( material.m_Emissive ),
1358 ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1359 material.m_Transparency, reflectionFactor );
1360
1362 {
1363 // Guess material type and apply a normal perturbator
1364 if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1365 && ( material.m_Shininess < 0.36f )
1366 && ( material.m_Transparency == 0.0f )
1367 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1368 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1369 < 0.15f )
1370 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1371 < 0.15f ) ) )
1372 {
1373 // This may be a black plastic..
1374 blinnMaterial.SetGenerator( &m_plasticMaterial );
1375 }
1376 else
1377 {
1378 if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1379 && ( material.m_Shininess < 0.30f )
1380 && ( material.m_Transparency == 0.0f )
1381 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1382 || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1383 || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1384 > 0.25f ) ) )
1385 {
1386 // This may be a color plastic ...
1387 blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1388 }
1389 else
1390 {
1391 if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1392 && ( material.m_Shininess > 0.35f )
1393 && ( material.m_Transparency == 0.0f )
1394 && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1395 < 0.40f )
1396 && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1397 < 0.40f )
1398 && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1399 < 0.40f ) ) )
1400 {
1401 // This may be a brushed metal
1402 blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1403 }
1404 }
1405 }
1406 }
1407 }
1408 else
1409 {
1410 ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1411 SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1412 }
1413 }
1414 }
1415
1416 return materialVector;
1417}
1418
1419
1420void RENDER_3D_RAYTRACE_BASE::addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
1421 const glm::mat4& aModelMatrix, float aFPOpacity,
1422 bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem )
1423{
1424 // Validate a3DModel pointers
1425 wxASSERT( a3DModel != nullptr );
1426
1427 if( a3DModel == nullptr )
1428 return;
1429
1430 wxASSERT( a3DModel->m_Materials != nullptr );
1431 wxASSERT( a3DModel->m_Meshes != nullptr );
1432 wxASSERT( a3DModel->m_MaterialsSize > 0 );
1433 wxASSERT( a3DModel->m_MeshesSize > 0 );
1434
1435 if( aFPOpacity > 1.0f )
1436 aFPOpacity = 1.0f;
1437
1438 if( aFPOpacity < 0.0f )
1439 aFPOpacity = 0.0f;
1440
1441 if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1442 && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1443 {
1444 MODEL_MATERIALS* materialVector = nullptr;
1445
1446 if( !aSkipMaterialInformation )
1447 {
1448 materialVector = getModelMaterial( a3DModel );
1449 }
1450
1451 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1452
1453 for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1454 {
1455 const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1456
1457 // Validate the mesh pointers
1458 wxASSERT( mesh.m_Positions != nullptr );
1459 wxASSERT( mesh.m_FaceIdx != nullptr );
1460 wxASSERT( mesh.m_Normals != nullptr );
1461 wxASSERT( mesh.m_FaceIdxSize > 0 );
1462 wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1463
1464
1465 if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1466 && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1467 && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1468 && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1469 {
1470 float fpTransparency;
1471 const BLINN_PHONG_MATERIAL* blinn_material;
1472
1473 if( !aSkipMaterialInformation )
1474 {
1475 blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1476
1477 fpTransparency =
1478 1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1479 }
1480
1481 // Add all face triangles
1482 for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1483 {
1484 const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1485 const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1486 const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1487
1488 wxASSERT( idx0 < mesh.m_VertexSize );
1489 wxASSERT( idx1 < mesh.m_VertexSize );
1490 wxASSERT( idx2 < mesh.m_VertexSize );
1491
1492 if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1493 && ( idx2 < mesh.m_VertexSize ) )
1494 {
1495 const SFVEC3F& v0 = mesh.m_Positions[idx0];
1496 const SFVEC3F& v1 = mesh.m_Positions[idx1];
1497 const SFVEC3F& v2 = mesh.m_Positions[idx2];
1498
1499 const SFVEC3F& n0 = mesh.m_Normals[idx0];
1500 const SFVEC3F& n1 = mesh.m_Normals[idx1];
1501 const SFVEC3F& n2 = mesh.m_Normals[idx2];
1502
1503 // Transform vertex with the model matrix
1504 const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1505 const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1506 const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1507
1508 const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1509 const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1510 const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1511
1512 TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1513
1514 newTriangle->SetBoardItem( aBoardItem );
1515
1516 aDstContainer.Add( newTriangle );
1517
1518 if( !aSkipMaterialInformation )
1519 {
1520 newTriangle->SetMaterial( blinn_material );
1521 newTriangle->SetModelTransparency( fpTransparency );
1522
1523 if( mesh.m_Color == nullptr )
1524 {
1525 const SFVEC3F diffuseColor =
1526 a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1527
1528 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1529 newTriangle->SetColor( ConvertSRGBToLinear(
1530 MaterialDiffuseToColorCAD( diffuseColor ) ) );
1531 else
1532 newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1533 }
1534 else
1535 {
1536 if( m_boardAdapter.m_Cfg->m_Render.material_mode == MATERIAL_MODE::CAD_MODE )
1537 {
1538 newTriangle->SetColor(
1540 mesh.m_Color[idx0] ) ),
1542 mesh.m_Color[idx1] ) ),
1544 mesh.m_Color[idx2] ) ) );
1545 }
1546 else
1547 {
1548 newTriangle->SetColor(
1549 ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1550 ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1551 ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1552 }
1553 }
1554 }
1555 }
1556 }
1557 }
1558 }
1559 }
1560}
Defines math related functions.
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
Defines math related functions.
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:140
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:147
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
Definition: 3d_math.h:43
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:58
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:66
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:379
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
SFVEC4F m_BgColorTop
background top color
SFVEC4F m_ECO2Color
const MAP_CONTAINER_2D_BASE & GetLayerHoleMap() const noexcept
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
Get the current polygon of the epoxy board.
bool IsFootprintShown(FOOTPRINT_ATTR_T aFPAttributes) const
Test if footprint should be displayed in relation to attributes and the flags.
const BBOX_3D & GetBBox() const noexcept
Get the board 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:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
const FOOTPRINTS & Footprints() const
Definition: board.h:336
const TRACKS & Tracks() const
Definition: board.h:334
PROJECT * GetProject() const
Definition: board.h:499
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:303
VECTOR2I GetPosition() const override
Definition: pad.h:206
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:406
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Definition: pcb_track.cpp:613
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:1161
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:72
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:78
@ LAYER_3D_SOLDERMASK_TOP
Definition: layer_ids.h:510
@ LAYER_3D_SOLDERMASK_BOTTOM
Definition: layer_ids.h:509
@ LAYER_3D_BOARD
Definition: layer_ids.h:504
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition: layer_ids.h:581
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 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