65 const float aaa = aTransparency * aTransparency * aTransparency;
68 float ca = 1.0f - aTransparency;
69 ca = 1.00f - 1.05f * ca * ca * ca;
71 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
77#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
88 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_refractions );
90 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_reflections );
108 const SFVEC3F copperSpecularLinear =
114 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
121 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
133 0.10f * 128.0f, 0.0f, 0.0f );
139 SFVEC3F( 0.0f ),
SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
145 const float solderMask_gray =
155 const float minSolderMaskShininess = 0.85f * 128.0f;
156 const float maxSolderMaskShininess = 512.0f;
157 const float solderMaskShininess = minSolderMaskShininess
158 + ( maxSolderMaskShininess - minSolderMaskShininess ) * ( 1.0f - solderMask_gray );
161 const float solderMaskReflection = glm::clamp( solderMask_gray * 0.3f, 0.02f, 0.16f );
166 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.30f, 1.0f ) ), solderMaskShininess,
167 solderMask_transparency, solderMaskReflection );
170 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
191 (
SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
192 0.10f * 128.0f, 1.0f, 0.50f );
194 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
199 float aZMin,
float aZMax,
const MATERIAL* aMaterial,
214 aDstContainer.
Add( objPtr );
221 aDstContainer.
Add( objPtr );
233 aDstContainer.
Add( objPtr );
242 aDstContainer.
Add( objPtr );
253 float aLayerZOffset )
255 if( aContainer2d ==
nullptr )
262 if( listObject2d.size() == 0 )
265 for(
const OBJECT_2D* object2d_A : listObject2d )
273 object2d_B =
new std::vector<const OBJECT_2D*>();
283 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
291 for(
const OBJECT_2D* hole2d : intersecting )
292 object2d_B->push_back( hole2d );
302 if( !throughHoleOuter.
GetList().empty() )
308 for(
const OBJECT_2D* hole2d : intersecting )
309 object2d_B->push_back( hole2d );
314 auto clipCutouts = [
this, &object2d_A, &object2d_B](
const BVH_CONTAINER_2D& cutouts )
316 if( !cutouts.GetList().empty() )
319 cutouts.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
321 for(
const OBJECT_2D* cutout : intersecting )
322 object2d_B->push_back( cutout );
326 if( aLayer_id ==
F_Cu )
332 else if( aLayer_id ==
B_Cu )
347 for(
const OBJECT_2D* obj : intersecting )
348 object2d_B->push_back( obj );
354 && ( ( aLayer_id ==
B_SilkS && mapLayers.find(
B_Mask ) != mapLayers.end() )
355 || ( aLayer_id ==
F_SilkS && mapLayers.find(
F_Mask ) != mapLayers.end() ) ) )
363 if( containerMaskLayer2d )
366 for(
const OBJECT_2D* obj2d : intersecting )
367 object2d_B->push_back( obj2d );
370 if( object2d_B->empty() )
408 bool aOnlyLoadCopperAndShapes )
419 if( !aOnlyLoadCopperAndShapes )
424 m_camera.SetBoardLookAtPos( camera_pos );
432 if( aStatusReporter )
433 aStatusReporter->
Report(
_(
"Load Raytracing: board" ) );
442 std::bitset<LAYER_3D_END> layerFlags =
m_boardAdapter.GetVisibleLayers();
444 if( !aOnlyLoadCopperAndShapes )
446 const int outlineCount =
m_boardAdapter.GetBoardPoly().OutlineCount();
448 if( outlineCount > 0 )
450 float divFactor = 0.0f;
467 for(
int ii = 0; ii < antiboardPoly.
OutlineCount(); ii++ )
478 for(
int ii = 0; ii < boardPolyCopy.
OutlineCount(); ii++ )
489 for(
const OBJECT_2D* object2d_A : listObjects )
491 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
501 for(
const OBJECT_2D* hole : intersecting )
503 if( object2d_A->Intersects( hole->GetBBox() ) )
504 object2d_B->push_back( hole );
509 auto addCutoutsFromContainer =
512 if( !aContainer.GetList().empty() )
515 aContainer.GetIntersectingObjects( object2d_A->GetBBox(),
518 for(
const OBJECT_2D* cutout : intersecting )
520 if( object2d_A->Intersects( cutout->GetBBox() ) )
521 object2d_B->push_back( cutout );
526 addCutoutsFromContainer(
m_boardAdapter.GetFrontCounterboreCutouts() );
527 addCutoutsFromContainer(
m_boardAdapter.GetBackCounterboreCutouts() );
528 addCutoutsFromContainer(
m_boardAdapter.GetFrontCountersinkCutouts() );
529 addCutoutsFromContainer(
m_boardAdapter.GetBackCountersinkCutouts() );
534 if( layerHolesMap.find(
F_Cu ) != layerHolesMap.end() )
541 for(
const OBJECT_2D* hole2d : intersecting )
543 if( object2d_A->Intersects( hole2d->GetBBox() ) )
544 object2d_B->push_back( hole2d );
548 if( layerHolesMap.find(
B_Cu ) != layerHolesMap.end() )
555 for(
const OBJECT_2D* hole2d : intersecting )
557 if( object2d_A->Intersects( hole2d->GetBBox() ) )
558 object2d_B->push_back( hole2d );
569 for(
const OBJECT_2D* obj : intersecting )
570 object2d_B->push_back( obj );
573 if( object2d_B->empty() )
618 for(
const OBJECT_2D* hole2d : holeList )
628 if( !intersecting.empty() )
632 switch( hole2d->GetObjectType() )
636 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
663 if( aStatusReporter )
664 aStatusReporter->
Report(
_(
"Load Raytracing: layers" ) );
667 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
742 else if(
m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
744 layerColor =
SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
772 if( !aOnlyLoadCopperAndShapes )
784 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
812 const float zLayerMin =
m_boardAdapter.GetLayerBottomZPos( layer_id );
813 const float zLayerMax =
m_boardAdapter.GetLayerTopZPos( layer_id );
818 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
828 for(
const OBJECT_2D* hole : intersecting )
830 if( object2d_A->Intersects( hole->GetBBox() ) )
831 object2d_B->push_back( hole );
837 if( !container2d->
GetList().empty() )
843 for(
const OBJECT_2D* obj : intersecting )
844 object2d_B->push_back( obj );
847 if( object2d_B->empty() )
857 materialLayer, layerColor );
871 object2d_A->GetBoardItem() );
888#ifdef PRINT_STATISTICS_3D_VIEWER
890 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
893 if( aStatusReporter )
894 aStatusReporter->
Report(
_(
"Loading 3D models..." ) );
898#ifdef PRINT_STATISTICS_3D_VIEWER
902 if( !aOnlyLoadCopperAndShapes )
911 boardBBox.
Scale( 3.0f );
917 containerBBox.
Scale( 1.3f );
922 const float minZ = glm::min( containerBBox.
Min().z, boardBBox.
Min().z );
926 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
930 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
946 newTriangle1->
SetColor( floorColor );
947 newTriangle2->
SetColor( floorColor );
950 const float maxZ = glm::max( containerBBox.
Max().z, boardBBox.
Max().z );
966 newTriangle3->
SetColor( floorColor );
967 newTriangle4->
SetColor( floorColor );
981 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
982 && ( aSource.b < ( 1.0f / 255.0f ) ) );
995 if( !IsColorZero( cameraLightColor ) )
1000 if( !IsColorZero( topLightColor ) )
1007 if( !IsColorZero( bottomLightColor ) )
1011 bottomLightColor ) );
1014 for(
size_t i = 0; i <
m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
1019 if( !IsColorZero( lightColor ) )
1040 / -
m_camera.GetCameraInitPos().z );
1042 if( min_zoom > max_zoom )
1043 std::swap( min_zoom, max_zoom );
1045 float zoom_ratio = max_zoom / min_zoom;
1049 steps -=
static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
1050 steps = std::max( steps, 0 );
1053 float increased_zoom = pow( 1.26f, steps / 2 );
1054 max_zoom *= increased_zoom;
1055 min_zoom /= increased_zoom;
1060 min_zoom = std::min( min_zoom, 1.0f );
1070 if( aStatusReporter )
1073 double calculation_time = (double) (
GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
1075 aStatusReporter->
Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1082 float aInnerRadius,
float aDepth,
1083 float aSurfaceZ,
bool aIsFront )
1085 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1088 if( platingThickness <= 0.0f || aInnerRadius <= 0.0f || aDepth <= 0.0f )
1091 const float outerRadius = aInnerRadius + platingThickness;
1092 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1093 const float zMin = std::min( aSurfaceZ, zOther );
1094 const float zMax = std::max( aSurfaceZ, zOther );
1096 RING_2D* ring =
new RING_2D( aCenter, aInnerRadius, outerRadius, aSource );
1108 float aTopInnerRadius,
1109 float aBottomInnerRadius,
1110 float aSurfaceZ,
float aDepth,
1113 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1116 if( platingThickness <= 0.0f || aTopInnerRadius <= 0.0f || aBottomInnerRadius <= 0.0f
1122 const float topOuterRadius = aTopInnerRadius + platingThickness;
1123 const float bottomOuterRadius = aBottomInnerRadius + platingThickness;
1125 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1126 const float zTop = std::max( aSurfaceZ, zOther );
1127 const float zBot = std::min( aSurfaceZ, zOther );
1129 if( topOuterRadius <= 0.0f || bottomOuterRadius <= 0.0f )
1132 const float largestDiameter = 2.0f * std::max( aTopInnerRadius, aBottomInnerRadius );
1133 unsigned int segments = std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( largestDiameter ) );
1152 auto makePoint = [&](
float radius,
float angle,
float z )
1155 aCenter.y + sinf( angle ) *
radius,
1159 const float step = 2.0f * glm::pi<float>() / (float) segments;
1161 SFVEC3F innerTopPrev = makePoint( aTopInnerRadius, 0.0f, zTop );
1162 SFVEC3F innerBotPrev = makePoint( aBottomInnerRadius, 0.0f, zBot );
1163 SFVEC3F outerTopPrev = makePoint( topOuterRadius, 0.0f, zTop );
1164 SFVEC3F outerBotPrev = makePoint( bottomOuterRadius, 0.0f, zBot );
1166 const SFVEC3F innerTopFirst = innerTopPrev;
1167 const SFVEC3F innerBotFirst = innerBotPrev;
1168 const SFVEC3F outerTopFirst = outerTopPrev;
1169 const SFVEC3F outerBotFirst = outerBotPrev;
1171 for(
unsigned int i = 1; i <= segments; ++i )
1173 const float angle = ( i == segments ) ? 0.0f : step * i;
1175 const SFVEC3F innerTopCurr = ( i == segments ) ? innerTopFirst
1176 : makePoint( aTopInnerRadius, angle, zTop );
1177 const SFVEC3F innerBotCurr = ( i == segments ) ? innerBotFirst
1178 : makePoint( aBottomInnerRadius, angle, zBot );
1179 const SFVEC3F outerTopCurr = ( i == segments ) ? outerTopFirst
1180 : makePoint( topOuterRadius, angle, zTop );
1181 const SFVEC3F outerBotCurr = ( i == segments ) ? outerBotFirst
1182 : makePoint( bottomOuterRadius, angle, zBot );
1185 addQuad( innerTopPrev, innerTopCurr, innerBotCurr, innerBotPrev );
1188 addQuad( outerTopPrev, outerBotPrev, outerBotCurr, outerTopCurr );
1191 addQuad( outerTopPrev, outerTopCurr, innerTopCurr, innerTopPrev );
1194 addQuad( outerBotPrev, innerBotPrev, innerBotCurr, outerBotCurr );
1196 innerTopPrev = innerTopCurr;
1197 innerBotPrev = innerBotCurr;
1198 outerTopPrev = outerTopCurr;
1199 outerBotPrev = outerBotCurr;
1210 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1211 const float platingThickness3d = platingThickness * unitScale;
1225 const float holeDiameter =
via->GetDrillValue() * unitScale;
1226 const float holeInnerRadius = holeDiameter / 2.0f;
1227 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1231 via->LayerPair( &topLayer, &bottomLayer );
1233 const float viaZTop =
m_boardAdapter.GetLayerBottomZPos( topLayer );
1234 const float viaZBot =
m_boardAdapter.GetLayerBottomZPos( bottomLayer );
1237 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
1239 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
1241 const float backdrillRadius = secondaryDrillSize.value() * 0.5f * unitScale;
1243 if( backdrillRadius > holeOuterRadius )
1249 const float secEndZ =
m_boardAdapter.GetLayerBottomZPos( secEnd );
1251 float plugZTop, plugZBot;
1253 if( secStart ==
F_Cu )
1266 if( plugZTop > plugZBot )
1281 const auto frontMode =
via->GetFrontPostMachining();
1283 if( frontMode.has_value()
1287 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
1288 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
1290 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1293 const float pmBottomZ = viaZTop - frontDepth;
1294 const float plugZBot = viaZBot;
1296 if( pmBottomZ > plugZBot )
1303 if( angleRad < 0.01f )
1306 float radialDiff = frontRadius - holeOuterRadius;
1307 float innerHeight = radialDiff / tanf( angleRad );
1308 float totalHeight = pmBottomZ - plugZBot;
1310 if( innerHeight > totalHeight )
1311 innerHeight = totalHeight;
1313 float zInnerTop = plugZBot + innerHeight;
1317 holeOuterRadius, frontRadius );
1323 if( zInnerTop > plugZBot )
1349 const auto backMode =
via->GetBackPostMachining();
1351 if( backMode.has_value()
1355 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
1356 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
1358 if( backRadius > holeOuterRadius && backDepth > 0 )
1361 const float plugZTop = viaZTop;
1362 const float pmTopZ = viaZBot + backDepth;
1364 if( plugZTop > pmTopZ )
1371 if( angleRad < 0.01f )
1374 float radialDiff = backRadius - holeOuterRadius;
1375 float innerHeight = radialDiff / tanf( angleRad );
1376 float totalHeight = plugZTop - pmTopZ;
1378 if( innerHeight > totalHeight )
1379 innerHeight = totalHeight;
1381 float zInnerBot = plugZTop - innerHeight;
1385 backRadius, holeOuterRadius );
1391 if( zInnerBot < plugZTop )
1420 for(
const PAD*
pad : footprint->Pads() )
1425 if( !
pad->HasHole() )
1431 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
1432 -
pad->GetPosition().y * unitScale );
1433 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
1434 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1436 const float padZTop = boardZTop;
1437 const float padZBot = boardZBot;
1440 const auto frontMode =
pad->GetFrontPostMachining();
1442 if( frontMode.has_value()
1446 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
1447 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
1449 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1451 const float pmBottomZ = padZTop - frontDepth;
1452 const float plugZBot = padZBot;
1454 if( pmBottomZ > plugZBot )
1461 if( angleRad < 0.01f )
1464 float radialDiff = frontRadius - holeOuterRadius;
1465 float innerHeight = radialDiff / tanf( angleRad );
1466 float totalHeight = pmBottomZ - plugZBot;
1468 if( innerHeight > totalHeight )
1469 innerHeight = totalHeight;
1471 float zInnerTop = plugZBot + innerHeight;
1475 holeOuterRadius, frontRadius );
1481 if( zInnerTop > plugZBot )
1507 const auto backMode =
pad->GetBackPostMachining();
1509 if( backMode.has_value()
1513 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
1514 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
1516 if( backRadius > holeOuterRadius && backDepth > 0 )
1518 const float plugZTop = padZTop;
1519 const float pmTopZ = padZBot + backDepth;
1521 if( plugZTop > pmTopZ )
1528 if( angleRad < 0.01f )
1531 float radialDiff = backRadius - holeOuterRadius;
1532 float innerHeight = radialDiff / tanf( angleRad );
1533 float totalHeight = plugZTop - pmTopZ;
1535 if( innerHeight > totalHeight )
1536 innerHeight = totalHeight;
1538 float zInnerBot = plugZTop - innerHeight;
1542 backRadius, holeOuterRadius );
1548 if( zInnerBot < plugZTop )
1585 aVia->
LayerPair( &top_layer, &bottom_layer );
1587 float frontDepth = 0.0f;
1588 float backDepth = 0.0f;
1606 ( radiusBUI +
m_boardAdapter.GetHolePlatingThickness() ) * unitScale, *aVia );
1617 const float holeInnerRadius = radiusBUI * unitScale;
1618 const float frontSurface = topZ + frontDepth;
1619 const float backSurface = botZ - backDepth;
1625 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1642 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1666 const bool hasHole = drillsize.
x && drillsize.
y;
1668 const bool isRoundHole = drillsize.
x == drillsize.
y;
1670 float holeInnerRadius = 0.0f;
1677 float frontDepth = 0.0f;
1678 float backDepth = 0.0f;
1697 int innerRadius = drillsize.
x / 2;
1698 int outerRadius = innerRadius +
m_boardAdapter.GetHolePlatingThickness();
1699 holeInnerRadius = innerRadius * unitScale;
1701 RING_2D* ring =
new RING_2D( holeCenter, innerRadius * unitScale,
1702 outerRadius * unitScale, *aPad );
1713 antiOutlineIntersectionList );
1716 if( !antiOutlineIntersectionList.empty() )
1719 holeCenter, innerRadius * unitScale, *aPad );
1722 holeCenter, outerRadius * unitScale, *aPad );
1723 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1724 object2d_B->push_back( innerCircle );
1733 object2d_A = itemCSG2d;
1741 if( drillsize.
x > drillsize.
y )
1743 ends_offset.
x = ( drillsize.
x - drillsize.
y ) / 2;
1744 width = drillsize.
y;
1748 ends_offset.
y = ( drillsize.
y - drillsize.
x ) / 2;
1749 width = drillsize.
x;
1759 -start.
y * unitScale ),
1761 -
end.y * unitScale ),
1762 width * unitScale, *aPad );
1766 -start.
y * unitScale ),
1768 -
end.y * unitScale ),
1770 * unitScale, *aPad );
1773 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1774 object2d_B->push_back( innerSeg );
1782 object2d_A = itemCSG2d;
1787 antiOutlineIntersectionList );
1793 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1803 for(
const OBJECT_2D* hole2d : intersecting )
1805 if( object2d_A->
Intersects( hole2d->GetBBox() ) )
1806 object2d_B->push_back( hole2d );
1810 for(
const OBJECT_2D* obj : antiOutlineIntersectionList )
1811 object2d_B->push_back( obj );
1813 if( object2d_B->empty() )
1843 if( object2d_A && isRoundHole )
1845 const float frontSurface = topZ + frontDepth;
1846 const float backSurface = botZ - backDepth;
1852 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1870 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1907 for(
PAD*
pad : footprint->Pads() )
1917 const glm::mat4& aFpMatrix )
1923 float scaleZ = std::min( bboxW, bboxH ) * 0.5f;
1926 float offsetX = localCenter.
x /
pcbIUScale.IU_PER_MM;
1927 float offsetY = -localCenter.
y /
pcbIUScale.IU_PER_MM;
1933 SFVEC3F boxMin( offsetX - bboxW * 0.5f, offsetY - bboxH * 0.5f, 0.0f );
1934 SFVEC3F boxMax( offsetX + bboxW * 0.5f, offsetY + bboxH * 0.5f, scaleZ );
1939 for(
int i = 0; i < 8; ++i )
1941 SFVEC3F corner( ( i & 1 ) ? boxMax.x : boxMin.x, ( i & 2 ) ? boxMax.y : boxMin.y,
1942 ( i & 4 ) ? boxMax.z : boxMin.z );
1944 glm::vec4 transformed = aFpMatrix * glm::vec4( corner, 1.0f );
1953 aDstContainer.
Add( placeholder );
1958 bool aSkipMaterialInformation )
1974 bool hasModels = !fp->Models().empty();
1975 bool showMissing =
m_boardAdapter.m_Cfg->m_Render.show_missing_models;
1977 if( ( hasModels || showMissing ) &&
m_boardAdapter.IsFootprintShown( fp ) )
1979 double zpos =
m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1983 glm::mat4 fpMatrix = glm::mat4( 1.0f );
1985 fpMatrix = glm::translate( fpMatrix,
1990 if( !fp->GetOrientation().IsZero() )
1992 fpMatrix = glm::rotate( fpMatrix, (
float) fp->GetOrientation().AsRadians(),
1993 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1996 if( fp->IsFlipped() )
1998 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
2000 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
2003 const double modelunit_to_3d_units_factor =
2006 fpMatrix = glm::scale(
2007 fpMatrix,
SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
2008 modelunit_to_3d_units_factor ) );
2013 wxString libraryName = fp->GetFPID().GetLibNickname();
2015 wxString footprintBasePath = wxEmptyString;
2022 std::optional<LIBRARY_TABLE_ROW*> fpRow =
2037 if( !
model.m_Show ||
model.m_Filename.empty() )
2041 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
2042 embeddedFilesStack.push_back( fp->GetEmbeddedFiles() );
2043 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
2046 std::move( embeddedFilesStack ) );
2051 glm::mat4 modelMatrix = fpMatrix;
2053 modelMatrix = glm::translate( modelMatrix,
2056 modelMatrix = glm::rotate( modelMatrix,
2057 (
float) -(
model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
2058 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
2060 modelMatrix = glm::rotate( modelMatrix,
2061 (
float) -(
model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
2062 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
2064 modelMatrix = glm::rotate( modelMatrix,
2065 (
float) -(
model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
2066 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
2068 modelMatrix = glm::scale( modelMatrix,
2071 addModels( aDstContainer, modelPtr, modelMatrix, (
float)
model.m_Opacity,
2072 aSkipMaterialInformation, fp );
2074 else if( showMissing )
2081 if( !hasModels && showMissing )
2110 for(
unsigned int imat = 0; imat < a3DModel->
m_MaterialsSize; ++imat )
2118 float reflectionFactor = 0.0f;
2120 if( ( material.
m_Shininess - 0.35f ) > FLT_EPSILON )
2122 reflectionFactor = glm::clamp(
2123 glm::sqrt( ( material.
m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
2134 if(
m_boardAdapter.m_Cfg->m_Render.raytrace_procedural_textures )
2189 return materialVector;
2194 const glm::mat4& aModelMatrix,
float aFPOpacity,
2195 bool aSkipMaterialInformation,
BOARD_ITEM* aBoardItem )
2198 wxASSERT( a3DModel !=
nullptr );
2200 if( a3DModel ==
nullptr )
2204 wxASSERT( a3DModel->
m_Meshes !=
nullptr );
2208 if( aFPOpacity > 1.0f )
2211 if( aFPOpacity < 0.0f )
2219 if( !aSkipMaterialInformation )
2224 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
2226 for(
unsigned int mesh_i = 0; mesh_i < a3DModel->
m_MeshesSize; ++mesh_i )
2243 float fpTransparency;
2246 if( !aSkipMaterialInformation )
2255 for(
unsigned int faceIdx = 0; faceIdx < mesh.
m_FaceIdxSize; faceIdx += 3 )
2257 const unsigned int idx0 = mesh.
m_FaceIdx[faceIdx + 0];
2258 const unsigned int idx1 = mesh.
m_FaceIdx[faceIdx + 1];
2259 const unsigned int idx2 = mesh.
m_FaceIdx[faceIdx + 2];
2277 const SFVEC3F vt0 =
SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
2281 const SFVEC3F nt0 = glm::normalize(
SFVEC3F( normalMatrix * n0 ) );
2282 const SFVEC3F nt1 = glm::normalize(
SFVEC3F( normalMatrix * n1 ) );
2283 const SFVEC3F nt2 = glm::normalize(
SFVEC3F( normalMatrix * n2 ) );
2289 aDstContainer.
Add( newTriangle );
2291 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
BOX2I CalcPlaceholderLocalBox(const FOOTPRINT *aFootprint)
Calculate a local space bounding box for a placeholder 3D model.
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.
constexpr size_type GetWidth() const
constexpr const Vec GetCenter() const
constexpr size_type GetHeight() const
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.
A dummy block is used to fill the polygons.
void SetColor(SFVEC3F aObjColor)
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)
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)
void addPlaceholderToRaytracer(CONTAINER_3D &aDstContainer, const FOOTPRINT *aFootprint, const glm::mat4 &aFpMatrix)
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.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
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:
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
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...
static float TransparencyControl(float aGrayColorValue, float aTransparency)
Attempt to control the transparency based on the gray value of the color.
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.
void Union(const SFVEC3F &aPoint)
Recalculate the bounding box adding a point.
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.
void Reset()
Reset the bounding box to zero and de-initialize it.
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