61 const float aaa = aTransparency * aTransparency * aTransparency;
64 float ca = 1.0f - aTransparency;
65 ca = 1.00f - 1.05f * ca * ca * ca;
67 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
73#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
84 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_refractions );
86 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_reflections );
104 const SFVEC3F copperSpecularLinear =
110 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
117 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
129 0.10f * 128.0f, 0.0f, 0.0f );
135 SFVEC3F( 0.0f ),
SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
141 const float solderMask_gray =
152 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
153 solderMask_transparency, 0.16f );
156 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
177 (
SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
178 0.10f * 128.0f, 1.0f, 0.50f );
180 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
185 float aZMin,
float aZMax,
const MATERIAL* aMaterial,
200 aDstContainer.
Add( objPtr );
207 aDstContainer.
Add( objPtr );
219 aDstContainer.
Add( objPtr );
228 aDstContainer.
Add( objPtr );
239 float aLayerZOffset )
241 if( aContainer2d ==
nullptr )
248 if( listObject2d.size() == 0 )
251 for(
const OBJECT_2D* object2d_A : listObject2d )
259 object2d_B =
new std::vector<const OBJECT_2D*>();
269 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
277 for(
const OBJECT_2D* hole2d : intersecting )
278 object2d_B->push_back( hole2d );
288 if( !throughHoleOuter.
GetList().empty() )
294 for(
const OBJECT_2D* hole2d : intersecting )
295 object2d_B->push_back( hole2d );
300 auto clipCutouts = [
this, &object2d_A, &object2d_B](
const BVH_CONTAINER_2D& cutouts )
302 if( !cutouts.GetList().empty() )
305 cutouts.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
307 for(
const OBJECT_2D* cutout : intersecting )
308 object2d_B->push_back( cutout );
312 if( aLayer_id ==
F_Cu )
318 else if( aLayer_id ==
B_Cu )
333 for(
const OBJECT_2D* obj : intersecting )
334 object2d_B->push_back( obj );
340 && ( ( aLayer_id ==
B_SilkS && mapLayers.find(
B_Mask ) != mapLayers.end() )
341 || ( aLayer_id ==
F_SilkS && mapLayers.find(
F_Mask ) != mapLayers.end() ) ) )
349 if( containerMaskLayer2d )
352 for(
const OBJECT_2D* obj2d : intersecting )
353 object2d_B->push_back( obj2d );
356 if( object2d_B->empty() )
394 bool aOnlyLoadCopperAndShapes )
405 if( !aOnlyLoadCopperAndShapes )
410 m_camera.SetBoardLookAtPos( camera_pos );
418 if( aStatusReporter )
419 aStatusReporter->
Report(
_(
"Load Raytracing: board" ) );
428 std::bitset<LAYER_3D_END> layerFlags =
m_boardAdapter.GetVisibleLayers();
430 if( !aOnlyLoadCopperAndShapes )
432 const int outlineCount =
m_boardAdapter.GetBoardPoly().OutlineCount();
434 if( outlineCount > 0 )
436 float divFactor = 0.0f;
453 for(
int ii = 0; ii < antiboardPoly.
OutlineCount(); ii++ )
464 for(
int ii = 0; ii < boardPolyCopy.
OutlineCount(); ii++ )
475 for(
const OBJECT_2D* object2d_A : listObjects )
477 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
487 for(
const OBJECT_2D* hole : intersecting )
489 if( object2d_A->Intersects( hole->GetBBox() ) )
490 object2d_B->push_back( hole );
495 auto addCutoutsFromContainer =
498 if( !aContainer.GetList().empty() )
501 aContainer.GetIntersectingObjects( object2d_A->GetBBox(),
504 for(
const OBJECT_2D* cutout : intersecting )
506 if( object2d_A->Intersects( cutout->GetBBox() ) )
507 object2d_B->push_back( cutout );
512 addCutoutsFromContainer(
m_boardAdapter.GetFrontCounterboreCutouts() );
513 addCutoutsFromContainer(
m_boardAdapter.GetBackCounterboreCutouts() );
514 addCutoutsFromContainer(
m_boardAdapter.GetFrontCountersinkCutouts() );
515 addCutoutsFromContainer(
m_boardAdapter.GetBackCountersinkCutouts() );
520 if( layerHolesMap.find(
F_Cu ) != layerHolesMap.end() )
527 for(
const OBJECT_2D* hole2d : intersecting )
529 if( object2d_A->Intersects( hole2d->GetBBox() ) )
530 object2d_B->push_back( hole2d );
534 if( layerHolesMap.find(
B_Cu ) != layerHolesMap.end() )
541 for(
const OBJECT_2D* hole2d : intersecting )
543 if( object2d_A->Intersects( hole2d->GetBBox() ) )
544 object2d_B->push_back( hole2d );
555 for(
const OBJECT_2D* obj : intersecting )
556 object2d_B->push_back( obj );
559 if( object2d_B->empty() )
604 for(
const OBJECT_2D* hole2d : holeList )
614 if( !intersecting.empty() )
618 switch( hole2d->GetObjectType() )
622 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
649 if( aStatusReporter )
650 aStatusReporter->
Report(
_(
"Load Raytracing: layers" ) );
653 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
728 else if(
m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
730 layerColor =
SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
758 if( !aOnlyLoadCopperAndShapes )
770 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
798 const float zLayerMin =
m_boardAdapter.GetLayerBottomZPos( layer_id );
799 const float zLayerMax =
m_boardAdapter.GetLayerTopZPos( layer_id );
804 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
814 for(
const OBJECT_2D* hole : intersecting )
816 if( object2d_A->Intersects( hole->GetBBox() ) )
817 object2d_B->push_back( hole );
823 if( !container2d->
GetList().empty() )
829 for(
const OBJECT_2D* obj : intersecting )
830 object2d_B->push_back( obj );
833 if( object2d_B->empty() )
843 materialLayer, layerColor );
857 object2d_A->GetBoardItem() );
874#ifdef PRINT_STATISTICS_3D_VIEWER
876 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
879 if( aStatusReporter )
880 aStatusReporter->
Report(
_(
"Loading 3D models..." ) );
884#ifdef PRINT_STATISTICS_3D_VIEWER
888 if( !aOnlyLoadCopperAndShapes )
897 boardBBox.
Scale( 3.0f );
903 containerBBox.
Scale( 1.3f );
908 const float minZ = glm::min( containerBBox.
Min().z, boardBBox.
Min().z );
912 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
916 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
932 newTriangle1->
SetColor( floorColor );
933 newTriangle2->
SetColor( floorColor );
936 const float maxZ = glm::max( containerBBox.
Max().z, boardBBox.
Max().z );
952 newTriangle3->
SetColor( floorColor );
953 newTriangle4->
SetColor( floorColor );
967 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
968 && ( aSource.b < ( 1.0f / 255.0f ) ) );
981 if( !IsColorZero( cameraLightColor ) )
986 if( !IsColorZero( topLightColor ) )
993 if( !IsColorZero( bottomLightColor ) )
997 bottomLightColor ) );
1000 for(
size_t i = 0; i <
m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
1005 if( !IsColorZero( lightColor ) )
1026 / -
m_camera.GetCameraInitPos().z );
1028 if( min_zoom > max_zoom )
1029 std::swap( min_zoom, max_zoom );
1031 float zoom_ratio = max_zoom / min_zoom;
1035 steps -=
static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
1036 steps = std::max( steps, 0 );
1039 float increased_zoom = pow( 1.26f, steps / 2 );
1040 max_zoom *= increased_zoom;
1041 min_zoom /= increased_zoom;
1046 min_zoom = std::min( min_zoom, 1.0f );
1056 if( aStatusReporter )
1059 double calculation_time = (double) (
GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
1061 aStatusReporter->
Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1068 float aInnerRadius,
float aDepth,
1069 float aSurfaceZ,
bool aIsFront )
1071 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1074 if( platingThickness <= 0.0f || aInnerRadius <= 0.0f || aDepth <= 0.0f )
1077 const float outerRadius = aInnerRadius + platingThickness;
1078 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1079 const float zMin = std::min( aSurfaceZ, zOther );
1080 const float zMax = std::max( aSurfaceZ, zOther );
1082 RING_2D* ring =
new RING_2D( aCenter, aInnerRadius, outerRadius, aSource );
1094 float aTopInnerRadius,
1095 float aBottomInnerRadius,
1096 float aSurfaceZ,
float aDepth,
1099 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1102 if( platingThickness <= 0.0f || aTopInnerRadius <= 0.0f || aBottomInnerRadius <= 0.0f
1108 const float topOuterRadius = aTopInnerRadius + platingThickness;
1109 const float bottomOuterRadius = aBottomInnerRadius + platingThickness;
1111 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1112 const float zTop = std::max( aSurfaceZ, zOther );
1113 const float zBot = std::min( aSurfaceZ, zOther );
1115 if( topOuterRadius <= 0.0f || bottomOuterRadius <= 0.0f )
1118 const float largestDiameter = 2.0f * std::max( aTopInnerRadius, aBottomInnerRadius );
1119 unsigned int segments = std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( largestDiameter ) );
1138 auto makePoint = [&](
float radius,
float angle,
float z )
1141 aCenter.y + sinf( angle ) *
radius,
1145 const float step = 2.0f * glm::pi<float>() / (float) segments;
1147 SFVEC3F innerTopPrev = makePoint( aTopInnerRadius, 0.0f, zTop );
1148 SFVEC3F innerBotPrev = makePoint( aBottomInnerRadius, 0.0f, zBot );
1149 SFVEC3F outerTopPrev = makePoint( topOuterRadius, 0.0f, zTop );
1150 SFVEC3F outerBotPrev = makePoint( bottomOuterRadius, 0.0f, zBot );
1152 const SFVEC3F innerTopFirst = innerTopPrev;
1153 const SFVEC3F innerBotFirst = innerBotPrev;
1154 const SFVEC3F outerTopFirst = outerTopPrev;
1155 const SFVEC3F outerBotFirst = outerBotPrev;
1157 for(
unsigned int i = 1; i <= segments; ++i )
1159 const float angle = ( i == segments ) ? 0.0f : step * i;
1161 const SFVEC3F innerTopCurr = ( i == segments ) ? innerTopFirst
1162 : makePoint( aTopInnerRadius, angle, zTop );
1163 const SFVEC3F innerBotCurr = ( i == segments ) ? innerBotFirst
1164 : makePoint( aBottomInnerRadius, angle, zBot );
1165 const SFVEC3F outerTopCurr = ( i == segments ) ? outerTopFirst
1166 : makePoint( topOuterRadius, angle, zTop );
1167 const SFVEC3F outerBotCurr = ( i == segments ) ? outerBotFirst
1168 : makePoint( bottomOuterRadius, angle, zBot );
1171 addQuad( innerTopPrev, innerTopCurr, innerBotCurr, innerBotPrev );
1174 addQuad( outerTopPrev, outerBotPrev, outerBotCurr, outerTopCurr );
1177 addQuad( outerTopPrev, outerTopCurr, innerTopCurr, innerTopPrev );
1180 addQuad( outerBotPrev, innerBotPrev, innerBotCurr, outerBotCurr );
1182 innerTopPrev = innerTopCurr;
1183 innerBotPrev = innerBotCurr;
1184 outerTopPrev = outerTopCurr;
1185 outerBotPrev = outerBotCurr;
1196 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1197 const float platingThickness3d = platingThickness * unitScale;
1211 const float holeDiameter =
via->GetDrillValue() * unitScale;
1212 const float holeInnerRadius = holeDiameter / 2.0f;
1213 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1217 via->LayerPair( &topLayer, &bottomLayer );
1219 const float viaZTop =
m_boardAdapter.GetLayerBottomZPos( topLayer );
1220 const float viaZBot =
m_boardAdapter.GetLayerBottomZPos( bottomLayer );
1223 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
1225 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
1227 const float backdrillRadius = secondaryDrillSize.value() * 0.5f * unitScale;
1229 if( backdrillRadius > holeOuterRadius )
1235 const float secEndZ =
m_boardAdapter.GetLayerBottomZPos( secEnd );
1237 float plugZTop, plugZBot;
1239 if( secStart ==
F_Cu )
1252 if( plugZTop > plugZBot )
1267 const auto frontMode =
via->GetFrontPostMachining();
1269 if( frontMode.has_value()
1273 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
1274 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
1276 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1279 const float pmBottomZ = viaZTop - frontDepth;
1280 const float plugZBot = viaZBot;
1282 if( pmBottomZ > plugZBot )
1289 if( angleRad < 0.01f )
1292 float radialDiff = frontRadius - holeOuterRadius;
1293 float innerHeight = radialDiff / tanf( angleRad );
1294 float totalHeight = pmBottomZ - plugZBot;
1296 if( innerHeight > totalHeight )
1297 innerHeight = totalHeight;
1299 float zInnerTop = plugZBot + innerHeight;
1303 holeOuterRadius, frontRadius );
1309 if( zInnerTop > plugZBot )
1335 const auto backMode =
via->GetBackPostMachining();
1337 if( backMode.has_value()
1341 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
1342 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
1344 if( backRadius > holeOuterRadius && backDepth > 0 )
1347 const float plugZTop = viaZTop;
1348 const float pmTopZ = viaZBot + backDepth;
1350 if( plugZTop > pmTopZ )
1357 if( angleRad < 0.01f )
1360 float radialDiff = backRadius - holeOuterRadius;
1361 float innerHeight = radialDiff / tanf( angleRad );
1362 float totalHeight = plugZTop - pmTopZ;
1364 if( innerHeight > totalHeight )
1365 innerHeight = totalHeight;
1367 float zInnerBot = plugZTop - innerHeight;
1371 backRadius, holeOuterRadius );
1377 if( zInnerBot < plugZTop )
1406 for(
const PAD*
pad : footprint->Pads() )
1411 if( !
pad->HasHole() )
1417 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
1418 -
pad->GetPosition().y * unitScale );
1419 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
1420 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1422 const float padZTop = boardZTop;
1423 const float padZBot = boardZBot;
1426 const auto frontMode =
pad->GetFrontPostMachining();
1428 if( frontMode.has_value()
1432 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
1433 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
1435 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1437 const float pmBottomZ = padZTop - frontDepth;
1438 const float plugZBot = padZBot;
1440 if( pmBottomZ > plugZBot )
1447 if( angleRad < 0.01f )
1450 float radialDiff = frontRadius - holeOuterRadius;
1451 float innerHeight = radialDiff / tanf( angleRad );
1452 float totalHeight = pmBottomZ - plugZBot;
1454 if( innerHeight > totalHeight )
1455 innerHeight = totalHeight;
1457 float zInnerTop = plugZBot + innerHeight;
1461 holeOuterRadius, frontRadius );
1467 if( zInnerTop > plugZBot )
1493 const auto backMode =
pad->GetBackPostMachining();
1495 if( backMode.has_value()
1499 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
1500 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
1502 if( backRadius > holeOuterRadius && backDepth > 0 )
1504 const float plugZTop = padZTop;
1505 const float pmTopZ = padZBot + backDepth;
1507 if( plugZTop > pmTopZ )
1514 if( angleRad < 0.01f )
1517 float radialDiff = backRadius - holeOuterRadius;
1518 float innerHeight = radialDiff / tanf( angleRad );
1519 float totalHeight = plugZTop - pmTopZ;
1521 if( innerHeight > totalHeight )
1522 innerHeight = totalHeight;
1524 float zInnerBot = plugZTop - innerHeight;
1528 backRadius, holeOuterRadius );
1534 if( zInnerBot < plugZTop )
1568 aVia->
LayerPair( &top_layer, &bottom_layer );
1570 float frontDepth = 0.0f;
1571 float backDepth = 0.0f;
1589 ( radiusBUI +
m_boardAdapter.GetHolePlatingThickness() ) * unitScale, *aVia );
1600 const float holeInnerRadius = radiusBUI * unitScale;
1601 const float frontSurface = topZ + frontDepth;
1602 const float backSurface = botZ - backDepth;
1608 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1625 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1646 const bool hasHole = drillsize.
x && drillsize.
y;
1648 const bool isRoundHole = drillsize.
x == drillsize.
y;
1650 float holeInnerRadius = 0.0f;
1657 float frontDepth = 0.0f;
1658 float backDepth = 0.0f;
1677 int innerRadius = drillsize.
x / 2;
1678 int outerRadius = innerRadius +
m_boardAdapter.GetHolePlatingThickness();
1679 holeInnerRadius = innerRadius * unitScale;
1681 RING_2D* ring =
new RING_2D( holeCenter, innerRadius * unitScale,
1682 outerRadius * unitScale, *aPad );
1693 antiOutlineIntersectionList );
1696 if( !antiOutlineIntersectionList.empty() )
1699 holeCenter, innerRadius * unitScale, *aPad );
1702 holeCenter, outerRadius * unitScale, *aPad );
1703 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1704 object2d_B->push_back( innerCircle );
1713 object2d_A = itemCSG2d;
1721 if( drillsize.
x > drillsize.
y )
1723 ends_offset.
x = ( drillsize.
x - drillsize.
y ) / 2;
1724 width = drillsize.
y;
1728 ends_offset.
y = ( drillsize.
y - drillsize.
x ) / 2;
1729 width = drillsize.
x;
1739 -start.
y * unitScale ),
1741 -
end.y * unitScale ),
1742 width * unitScale, *aPad );
1746 -start.
y * unitScale ),
1748 -
end.y * unitScale ),
1750 * unitScale, *aPad );
1753 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1754 object2d_B->push_back( innerSeg );
1762 object2d_A = itemCSG2d;
1767 antiOutlineIntersectionList );
1773 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1783 for(
const OBJECT_2D* hole2d : intersecting )
1785 if( object2d_A->
Intersects( hole2d->GetBBox() ) )
1786 object2d_B->push_back( hole2d );
1790 for(
const OBJECT_2D* obj : antiOutlineIntersectionList )
1791 object2d_B->push_back( obj );
1793 if( object2d_B->empty() )
1823 if( object2d_A && isRoundHole )
1825 const float frontSurface = topZ + frontDepth;
1826 const float backSurface = botZ - backDepth;
1832 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1850 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1887 for(
PAD*
pad : footprint->Pads() )
1897 bool aSkipMaterialInformation )
1913 if( !fp->Models().empty()
1916 double zpos =
m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1920 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1922 fpMatrix = glm::translate( fpMatrix,
1927 if( !fp->GetOrientation().IsZero() )
1929 fpMatrix = glm::rotate( fpMatrix, (
float) fp->GetOrientation().AsRadians(),
1930 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1933 if( fp->IsFlipped() )
1935 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1937 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1940 const double modelunit_to_3d_units_factor =
1943 fpMatrix = glm::scale(
1944 fpMatrix,
SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1945 modelunit_to_3d_units_factor ) );
1950 wxString libraryName = fp->GetFPID().GetLibNickname();
1952 wxString footprintBasePath = wxEmptyString;
1959 std::optional<LIBRARY_TABLE_ROW*> fpRow =
1974 if( !
model.m_Show ||
model.m_Filename.empty() )
1978 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
1979 embeddedFilesStack.push_back( fp->GetEmbeddedFiles() );
1980 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
1983 std::move( embeddedFilesStack ) );
1988 glm::mat4 modelMatrix = fpMatrix;
1990 modelMatrix = glm::translate( modelMatrix,
1993 modelMatrix = glm::rotate( modelMatrix,
1994 (
float) -(
model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
1995 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1997 modelMatrix = glm::rotate( modelMatrix,
1998 (
float) -(
model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
1999 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
2001 modelMatrix = glm::rotate( modelMatrix,
2002 (
float) -(
model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
2003 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
2005 modelMatrix = glm::scale( modelMatrix,
2008 addModels( aDstContainer, modelPtr, modelMatrix, (
float)
model.m_Opacity,
2009 aSkipMaterialInformation, fp );
2037 for(
unsigned int imat = 0; imat < a3DModel->
m_MaterialsSize; ++imat )
2045 float reflectionFactor = 0.0f;
2047 if( ( material.
m_Shininess - 0.35f ) > FLT_EPSILON )
2049 reflectionFactor = glm::clamp(
2050 glm::sqrt( ( material.
m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
2061 if(
m_boardAdapter.m_Cfg->m_Render.raytrace_procedural_textures )
2116 return materialVector;
2121 const glm::mat4& aModelMatrix,
float aFPOpacity,
2122 bool aSkipMaterialInformation,
BOARD_ITEM* aBoardItem )
2125 wxASSERT( a3DModel !=
nullptr );
2127 if( a3DModel ==
nullptr )
2131 wxASSERT( a3DModel->
m_Meshes !=
nullptr );
2135 if( aFPOpacity > 1.0f )
2138 if( aFPOpacity < 0.0f )
2146 if( !aSkipMaterialInformation )
2151 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
2153 for(
unsigned int mesh_i = 0; mesh_i < a3DModel->
m_MeshesSize; ++mesh_i )
2170 float fpTransparency;
2173 if( !aSkipMaterialInformation )
2182 for(
unsigned int faceIdx = 0; faceIdx < mesh.
m_FaceIdxSize; faceIdx += 3 )
2184 const unsigned int idx0 = mesh.
m_FaceIdx[faceIdx + 0];
2185 const unsigned int idx1 = mesh.
m_FaceIdx[faceIdx + 1];
2186 const unsigned int idx2 = mesh.
m_FaceIdx[faceIdx + 2];
2204 const SFVEC3F vt0 =
SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
2208 const SFVEC3F nt0 = glm::normalize(
SFVEC3F( normalMatrix * n0 ) );
2209 const SFVEC3F nt1 = glm::normalize(
SFVEC3F( normalMatrix * n1 ) );
2210 const SFVEC3F nt2 = glm::normalize(
SFVEC3F( normalMatrix * n2 ) );
2216 aDstContainer.
Add( newTriangle );
2218 if( !aSkipMaterialInformation )
@ 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)
float NextFloatUp(float v)
Defines math related functions.
float RGBtoGray(const SFVEC3F &aColor)
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
constexpr EDA_IU_SCALE pcbIUScale
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.
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
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.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
static const float DEFAULT_MAX_ZOOM
const LIST_OBJECT2D & GetList() const
void Add(OBJECT_3D *aObject)
Procedural generation of the copper normals.
void SetColor(SFVEC3F aObjColor)
A light source based only on a directional vector.
Make solid geometry for objects on layers.
void SetColor(SFVEC3F aObjColor)
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, 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.
Base material class that can be used to derive other material implementations.
static void SetDefaultReflectionRayCount(unsigned int aCount)
static void SetDefaultRefractionRayCount(unsigned int aCount)
static void SetDefaultRefractionRecursionCount(unsigned int aCount)
void SetGenerator(const MATERIAL_GENERATOR *aGenerator)
float GetTransparency() const
static void SetDefaultReflectionRecursionCount(unsigned int aCount)
static OBJECT_2D_STATS & Instance()
virtual bool Intersects(const BBOX_2D &aBBox) const =0
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
const BBOX_2D & GetBBox() const
const BOARD_ITEM & GetBoardItem() const
OBJECT_2D_TYPE GetObjectType() const
static OBJECT_3D_STATS & Instance()
void SetMaterial(const MATERIAL *aMaterial)
void SetModelTransparency(float aModelTransparency)
void SetBoardItem(BOARD_ITEM *aBoardItem)
POST_MACHINING_PROPS & FrontPostMachining()
POST_MACHINING_PROPS & BackPostMachining()
int GetBackPostMachiningSize() const
const VECTOR2I & GetDrillSize() const
VECTOR2I GetPosition() const override
int GetFrontPostMachiningSize() const
int GetFrontPostMachiningDepth() const
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetFrontPostMachining() const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetBackPostMachining() const
int GetBackPostMachiningDepth() const
const VECTOR2I & GetStart() const
int GetFrontPostMachiningSize() const
const PADSTACK & Padstack() const
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetFrontPostMachining() const
int GetBackPostMachiningSize() const
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetBackPostMachining() const
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)
Procedural generation of the plastic normals.
Procedural generation of the shiny plastic normals.
Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20....
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
SILK_SCREEN_NORMAL m_silkScreenMaterial
struct RENDER_3D_RAYTRACE_BASE::@013206213056006125230376122042346155134272177300 m_materials
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
void addCountersinkPlating(const SFVEC2F &aCenter, float aTopInnerRadius, float aBottomInnerRadius, float aSurfaceZ, float aDepth, bool aIsFront)
BOARD_NORMAL m_boardMaterial
CONTAINER_3D m_objectContainer
COPPER_NORMAL m_copperMaterial
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
PLASTIC_NORMAL m_plasticMaterial
ACCELERATOR_3D * m_accelerator
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
unsigned int m_convertedDummyBlockCount
void backfillPostMachine()
void addCounterborePlating(const BOARD_ITEM &aSource, const SFVEC2F &aCenter, float aInnerRadius, float aDepth, float aSurfaceZ, bool aIsFront)
CONTAINER_2D * m_outlineBoard2dObjects
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)
std::list< LIGHT * > m_lights
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.
unsigned int m_converted2dRoundSegmentCount
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
void SetColor(SFVEC3F aObjColor)
Cache for storing the 3D shapes.
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
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.
void SetColor(const SFVEC3F &aColor)
A vertical truncated cone with different radii at top and bottom.
void SetColor(SFVEC3F aObjColor)
A plane that is parallel to XY plane.
void SetColor(SFVEC3F aObjColor)
std::list< OBJECT_2D * > LIST_OBJECT2D
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
#define UNITS3D_TO_UNITSPCB
Implements a model viewer canvas.
Declaration of the eda_3d_viewer class.
A truncated cone for raytracing, used for countersink visualization.
int MapPCBLayerTo3DLayer(PCB_LAYER_ID aLayer)
@ LAYER_3D_SOLDERMASK_TOP
@ LAYER_3D_SOLDERMASK_BOTTOM
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
PAD_DRILL_POST_MACHINING_MODE
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
static wxColor copperColor(220, 180, 30)
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...
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
const SFVEC2F & Max() const
Manage a bounding box defined by two SFVEC3F min max points.
SFVEC3F GetCenter() const
Return the center point of the bounding box.
const SFVEC3F & Min() const
Return the minimum vertex pointer.
const SFVEC3F & Max() const
Return the maximum vertex pointer.
bool IsInitialized() const
Check if this bounding box is already initialized.
void Scale(float aScale)
Scales a bounding box by its center.
bool clip_silk_on_via_annuli
bool subtract_mask_from_silk
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
Store the a model based on meshes and materials.
SMATERIAL * m_Materials
The materials list of this model.
unsigned int m_MeshesSize
Number of meshes in the array.
SMESH * m_Meshes
The meshes list of this model.
unsigned int m_MaterialsSize
Number of materials in the material array.
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Per-vertex normal/color/texcoors structure.
unsigned int * m_FaceIdx
Triangle Face Indexes.
SFVEC3F * m_Normals
Vertex normals array.
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
unsigned int m_VertexSize
Number of vertex in the arrays.
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
SFVEC3F * m_Color
Vertex color array, can be NULL.
SFVEC3F * m_Positions
Vertex position array.
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.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I