60 const float aaa = aTransparency * aTransparency * aTransparency;
63 float ca = 1.0f - aTransparency;
64 ca = 1.00f - 1.05f * ca * ca * ca;
66 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
79 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_refractions );
81 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_reflections );
99 const SFVEC3F copperSpecularLinear =
105 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
112 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
123 0.10f * 128.0f, 0.0f, 0.0f );
131 0.10f * 128.0f, 0.0f, 0.0f );
137 SFVEC3F( 0.0f ),
SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
143 const float solderMask_gray =
153 const float minSolderMaskShininess = 0.85f * 128.0f;
154 const float maxSolderMaskShininess = 512.0f;
155 const float solderMaskShininess = minSolderMaskShininess
156 + ( maxSolderMaskShininess - minSolderMaskShininess ) * ( 1.0f - solderMask_gray );
159 const float solderMaskReflection = glm::clamp( solderMask_gray * 0.3f, 0.02f, 0.16f );
164 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.30f, 1.0f ) ), solderMaskShininess,
165 solderMask_transparency, solderMaskReflection );
168 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
189 (
SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
190 0.10f * 128.0f, 1.0f, 0.50f );
192 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
197 float aZMin,
float aZMax,
const MATERIAL* aMaterial,
212 aDstContainer.
Add( objPtr );
219 aDstContainer.
Add( objPtr );
231 aDstContainer.
Add( objPtr );
240 aDstContainer.
Add( objPtr );
251 float aLayerZOffset )
253 if( aContainer2d ==
nullptr )
260 if( listObject2d.size() == 0 )
263 for(
const OBJECT_2D* object2d_A : listObject2d )
271 object2d_B =
new std::vector<const OBJECT_2D*>();
281 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
289 for(
const OBJECT_2D* hole2d : intersecting )
290 object2d_B->push_back( hole2d );
300 if( !throughHoleOuter.
GetList().empty() )
306 for(
const OBJECT_2D* hole2d : intersecting )
307 object2d_B->push_back( hole2d );
312 auto clipCutouts = [
this, &object2d_A, &object2d_B](
const BVH_CONTAINER_2D& cutouts )
314 if( !cutouts.GetList().empty() )
317 cutouts.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
319 for(
const OBJECT_2D* cutout : intersecting )
320 object2d_B->push_back( cutout );
324 if( aLayer_id ==
F_Cu )
330 else if( aLayer_id ==
B_Cu )
345 for(
const OBJECT_2D* obj : intersecting )
346 object2d_B->push_back( obj );
352 && ( ( aLayer_id ==
B_SilkS && mapLayers.find(
B_Mask ) != mapLayers.end() )
353 || ( aLayer_id ==
F_SilkS && mapLayers.find(
F_Mask ) != mapLayers.end() ) ) )
361 if( containerMaskLayer2d )
364 for(
const OBJECT_2D* obj2d : intersecting )
365 object2d_B->push_back( obj2d );
368 if( object2d_B->empty() )
416 if( !aOnlyLoadCopperAndShapes )
422 m_camera.SetBoardLookAtPos( camera_pos );
437 if( aStop.stop_requested() )
442 if( aOnlyLoadCopperAndShapes )
455 std::bitset<LAYER_3D_END> layerFlags =
m_boardAdapter.GetVisibleLayers();
457 if( !aOnlyLoadCopperAndShapes )
459 const int outlineCount =
m_boardAdapter.GetBoardPoly().OutlineCount();
461 if( outlineCount > 0 )
463 float divFactor = 0.0f;
480 for(
int ii = 0; ii < antiboardPoly.
OutlineCount(); ii++ )
491 for(
int ii = 0; ii < boardPolyCopy.
OutlineCount(); ii++ )
502 for(
const OBJECT_2D* object2d_A : listObjects )
504 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
514 for(
const OBJECT_2D* hole : intersecting )
516 if( object2d_A->Intersects( hole->GetBBox() ) )
517 object2d_B->push_back( hole );
522 auto addCutoutsFromContainer =
525 if( !aContainer.GetList().empty() )
528 aContainer.GetIntersectingObjects( object2d_A->GetBBox(),
531 for(
const OBJECT_2D* cutout : intersecting )
533 if( object2d_A->Intersects( cutout->GetBBox() ) )
534 object2d_B->push_back( cutout );
539 addCutoutsFromContainer(
m_boardAdapter.GetFrontCounterboreCutouts() );
540 addCutoutsFromContainer(
m_boardAdapter.GetBackCounterboreCutouts() );
541 addCutoutsFromContainer(
m_boardAdapter.GetFrontCountersinkCutouts() );
542 addCutoutsFromContainer(
m_boardAdapter.GetBackCountersinkCutouts() );
547 if( layerHolesMap.find(
F_Cu ) != layerHolesMap.end() )
554 for(
const OBJECT_2D* hole2d : intersecting )
556 if( object2d_A->Intersects( hole2d->GetBBox() ) )
557 object2d_B->push_back( hole2d );
561 if( layerHolesMap.find(
B_Cu ) != layerHolesMap.end() )
568 for(
const OBJECT_2D* hole2d : intersecting )
570 if( object2d_A->Intersects( hole2d->GetBBox() ) )
571 object2d_B->push_back( hole2d );
582 for(
const OBJECT_2D* obj : intersecting )
583 object2d_B->push_back( obj );
586 if( object2d_B->empty() )
631 for(
const OBJECT_2D* hole2d : holeList )
641 if( !intersecting.empty() )
645 switch( hole2d->GetObjectType() )
649 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
678 if( aOnlyLoadCopperAndShapes )
685 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
770 else if(
m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
772 layerColor =
SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
787 if( aStop.stop_requested() )
803 if( !aOnlyLoadCopperAndShapes )
815 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
843 const float zLayerMin =
m_boardAdapter.GetLayerBottomZPos( layer_id );
844 const float zLayerMax =
m_boardAdapter.GetLayerTopZPos( layer_id );
849 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
859 for(
const OBJECT_2D* hole : intersecting )
861 if( object2d_A->Intersects( hole->GetBBox() ) )
862 object2d_B->push_back( hole );
868 if( !container2d->
GetList().empty() )
874 for(
const OBJECT_2D* obj : intersecting )
875 object2d_B->push_back( obj );
878 if( object2d_B->empty() )
888 materialLayer, layerColor );
902 object2d_A->GetBoardItem() );
919#ifdef PRINT_STATISTICS_3D_VIEWER
921 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
926 if( aOnlyLoadCopperAndShapes )
934 if( aStop.stop_requested() )
937#ifdef PRINT_STATISTICS_3D_VIEWER
941 if( !aOnlyLoadCopperAndShapes )
950 boardBBox.
Scale( 3.0f );
956 containerBBox.
Scale( 1.3f );
961 const float minZ = glm::min( containerBBox.
Min().z, boardBBox.
Min().z );
965 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
969 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
985 newTriangle1->
SetColor( floorColor );
986 newTriangle2->
SetColor( floorColor );
989 const float maxZ = glm::max( containerBBox.
Max().z, boardBBox.
Max().z );
1005 newTriangle3->
SetColor( floorColor );
1006 newTriangle4->
SetColor( floorColor );
1020 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
1021 && ( aSource.b < ( 1.0f / 255.0f ) ) );
1034 if( !IsColorZero( cameraLightColor ) )
1039 if( !IsColorZero( topLightColor ) )
1046 if( !IsColorZero( bottomLightColor ) )
1050 bottomLightColor ) );
1053 for(
size_t i = 0; i <
m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
1058 if( !IsColorZero( lightColor ) )
1079 / -
m_camera.GetCameraInitPos().z );
1081 if( min_zoom > max_zoom )
1082 std::swap( min_zoom, max_zoom );
1084 float zoom_ratio = max_zoom / min_zoom;
1088 steps -=
static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
1089 steps = std::max( steps, 0 );
1092 float increased_zoom = pow( 1.26f, steps / 2 );
1093 max_zoom *= increased_zoom;
1094 min_zoom /= increased_zoom;
1099 min_zoom = std::min( min_zoom, 1.0f );
1105 if( aStop.stop_requested() )
1109 std::unique_ptr<ACCELERATOR_3D> accelerator =
1120 double calculation_time = (double) (
GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
1122 if( aOnlyLoadCopperAndShapes )
1124 m_activityReporter->Report( wxString::Format(
_(
"Hit-test scene ready in %.3f s" ), calculation_time ) );
1128 m_activityReporter->Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1136 float aInnerRadius,
float aDepth,
1137 float aSurfaceZ,
bool aIsFront )
1139 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1142 if( platingThickness <= 0.0f || aInnerRadius <= 0.0f || aDepth <= 0.0f )
1145 const float outerRadius = aInnerRadius + platingThickness;
1146 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1147 const float zMin = std::min( aSurfaceZ, zOther );
1148 const float zMax = std::max( aSurfaceZ, zOther );
1150 RING_2D* ring =
new RING_2D( aCenter, aInnerRadius, outerRadius, aSource );
1162 float aTopInnerRadius,
1163 float aBottomInnerRadius,
1164 float aSurfaceZ,
float aDepth,
1167 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1170 if( platingThickness <= 0.0f || aTopInnerRadius <= 0.0f || aBottomInnerRadius <= 0.0f
1176 const float topOuterRadius = aTopInnerRadius + platingThickness;
1177 const float bottomOuterRadius = aBottomInnerRadius + platingThickness;
1179 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1180 const float zTop = std::max( aSurfaceZ, zOther );
1181 const float zBot = std::min( aSurfaceZ, zOther );
1183 if( topOuterRadius <= 0.0f || bottomOuterRadius <= 0.0f )
1186 const float largestDiameter = 2.0f * std::max( aTopInnerRadius, aBottomInnerRadius );
1187 unsigned int segments = std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( largestDiameter ) );
1206 auto makePoint = [&](
float radius,
float angle,
float z )
1209 aCenter.y + sinf( angle ) *
radius,
1213 const float step = 2.0f * glm::pi<float>() / (float) segments;
1215 SFVEC3F innerTopPrev = makePoint( aTopInnerRadius, 0.0f, zTop );
1216 SFVEC3F innerBotPrev = makePoint( aBottomInnerRadius, 0.0f, zBot );
1217 SFVEC3F outerTopPrev = makePoint( topOuterRadius, 0.0f, zTop );
1218 SFVEC3F outerBotPrev = makePoint( bottomOuterRadius, 0.0f, zBot );
1220 const SFVEC3F innerTopFirst = innerTopPrev;
1221 const SFVEC3F innerBotFirst = innerBotPrev;
1222 const SFVEC3F outerTopFirst = outerTopPrev;
1223 const SFVEC3F outerBotFirst = outerBotPrev;
1225 for(
unsigned int i = 1; i <= segments; ++i )
1227 const float angle = ( i == segments ) ? 0.0f : step * i;
1229 const SFVEC3F innerTopCurr = ( i == segments ) ? innerTopFirst
1230 : makePoint( aTopInnerRadius, angle, zTop );
1231 const SFVEC3F innerBotCurr = ( i == segments ) ? innerBotFirst
1232 : makePoint( aBottomInnerRadius, angle, zBot );
1233 const SFVEC3F outerTopCurr = ( i == segments ) ? outerTopFirst
1234 : makePoint( topOuterRadius, angle, zTop );
1235 const SFVEC3F outerBotCurr = ( i == segments ) ? outerBotFirst
1236 : makePoint( bottomOuterRadius, angle, zBot );
1239 addQuad( innerTopPrev, innerTopCurr, innerBotCurr, innerBotPrev );
1242 addQuad( outerTopPrev, outerBotPrev, outerBotCurr, outerTopCurr );
1245 addQuad( outerTopPrev, outerTopCurr, innerTopCurr, innerTopPrev );
1248 addQuad( outerBotPrev, innerBotPrev, innerBotCurr, outerBotCurr );
1250 innerTopPrev = innerTopCurr;
1251 innerBotPrev = innerBotCurr;
1252 outerTopPrev = outerTopCurr;
1253 outerBotPrev = outerBotCurr;
1264 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1265 const float platingThickness3d = platingThickness * unitScale;
1279 const float holeDiameter =
via->GetDrillValue() * unitScale;
1280 const float holeInnerRadius = holeDiameter / 2.0f;
1281 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1285 via->LayerPair( &topLayer, &bottomLayer );
1287 const float viaZTop =
m_boardAdapter.GetLayerBottomZPos( topLayer );
1288 const float viaZBot =
m_boardAdapter.GetLayerBottomZPos( bottomLayer );
1291 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
1293 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
1295 const float backdrillRadius = secondaryDrillSize.value() * 0.5f * unitScale;
1297 if( backdrillRadius > holeOuterRadius )
1303 const float secEndZ =
m_boardAdapter.GetLayerBottomZPos( secEnd );
1305 float plugZTop, plugZBot;
1307 if( secStart ==
F_Cu )
1320 if( plugZTop > plugZBot )
1335 const auto frontMode =
via->GetFrontPostMachining();
1337 if( frontMode.has_value()
1341 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
1342 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
1344 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1347 const float pmBottomZ = viaZTop - frontDepth;
1348 const float plugZBot = viaZBot;
1350 if( pmBottomZ > plugZBot )
1357 if( angleRad < 0.01f )
1360 float radialDiff = frontRadius - holeOuterRadius;
1361 float innerHeight = radialDiff / tanf( angleRad );
1362 float totalHeight = pmBottomZ - plugZBot;
1364 if( innerHeight > totalHeight )
1365 innerHeight = totalHeight;
1367 float zInnerTop = plugZBot + innerHeight;
1371 holeOuterRadius, frontRadius );
1377 if( zInnerTop > plugZBot )
1403 const auto backMode =
via->GetBackPostMachining();
1405 if( backMode.has_value()
1409 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
1410 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
1412 if( backRadius > holeOuterRadius && backDepth > 0 )
1415 const float plugZTop = viaZTop;
1416 const float pmTopZ = viaZBot + backDepth;
1418 if( plugZTop > pmTopZ )
1425 if( angleRad < 0.01f )
1428 float radialDiff = backRadius - holeOuterRadius;
1429 float innerHeight = radialDiff / tanf( angleRad );
1430 float totalHeight = plugZTop - pmTopZ;
1432 if( innerHeight > totalHeight )
1433 innerHeight = totalHeight;
1435 float zInnerBot = plugZTop - innerHeight;
1439 backRadius, holeOuterRadius );
1445 if( zInnerBot < plugZTop )
1474 for(
const PAD*
pad : footprint->Pads() )
1479 if( !
pad->HasHole() )
1485 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
1486 -
pad->GetPosition().y * unitScale );
1487 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
1488 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1490 const float padZTop = boardZTop;
1491 const float padZBot = boardZBot;
1494 const auto frontMode =
pad->GetFrontPostMachining();
1496 if( frontMode.has_value()
1500 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
1501 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
1503 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1505 const float pmBottomZ = padZTop - frontDepth;
1506 const float plugZBot = padZBot;
1508 if( pmBottomZ > plugZBot )
1515 if( angleRad < 0.01f )
1518 float radialDiff = frontRadius - holeOuterRadius;
1519 float innerHeight = radialDiff / tanf( angleRad );
1520 float totalHeight = pmBottomZ - plugZBot;
1522 if( innerHeight > totalHeight )
1523 innerHeight = totalHeight;
1525 float zInnerTop = plugZBot + innerHeight;
1529 holeOuterRadius, frontRadius );
1535 if( zInnerTop > plugZBot )
1561 const auto backMode =
pad->GetBackPostMachining();
1563 if( backMode.has_value()
1567 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
1568 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
1570 if( backRadius > holeOuterRadius && backDepth > 0 )
1572 const float plugZTop = padZTop;
1573 const float pmTopZ = padZBot + backDepth;
1575 if( plugZTop > pmTopZ )
1582 if( angleRad < 0.01f )
1585 float radialDiff = backRadius - holeOuterRadius;
1586 float innerHeight = radialDiff / tanf( angleRad );
1587 float totalHeight = plugZTop - pmTopZ;
1589 if( innerHeight > totalHeight )
1590 innerHeight = totalHeight;
1592 float zInnerBot = plugZTop - innerHeight;
1596 backRadius, holeOuterRadius );
1602 if( zInnerBot < plugZTop )
1639 aVia->
LayerPair( &top_layer, &bottom_layer );
1641 float frontDepth = 0.0f;
1642 float backDepth = 0.0f;
1660 ( radiusBUI +
m_boardAdapter.GetHolePlatingThickness() ) * unitScale, *aVia );
1671 const float holeInnerRadius = radiusBUI * unitScale;
1672 const float frontSurface = topZ + frontDepth;
1673 const float backSurface = botZ - backDepth;
1679 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1696 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1720 const bool hasHole = drillsize.
x && drillsize.
y;
1722 const bool isRoundHole = drillsize.
x == drillsize.
y;
1724 float holeInnerRadius = 0.0f;
1731 float frontDepth = 0.0f;
1732 float backDepth = 0.0f;
1751 int innerRadius = drillsize.
x / 2;
1752 int outerRadius = innerRadius +
m_boardAdapter.GetHolePlatingThickness();
1753 holeInnerRadius = innerRadius * unitScale;
1755 RING_2D* ring =
new RING_2D( holeCenter, innerRadius * unitScale,
1756 outerRadius * unitScale, *aPad );
1767 antiOutlineIntersectionList );
1770 if( !antiOutlineIntersectionList.empty() )
1773 holeCenter, innerRadius * unitScale, *aPad );
1776 holeCenter, outerRadius * unitScale, *aPad );
1777 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1778 object2d_B->push_back( innerCircle );
1787 object2d_A = itemCSG2d;
1795 if( drillsize.
x > drillsize.
y )
1797 ends_offset.
x = ( drillsize.
x - drillsize.
y ) / 2;
1798 width = drillsize.
y;
1802 ends_offset.
y = ( drillsize.
y - drillsize.
x ) / 2;
1803 width = drillsize.
x;
1813 -start.
y * unitScale ),
1815 -
end.y * unitScale ),
1816 width * unitScale, *aPad );
1820 -start.
y * unitScale ),
1822 -
end.y * unitScale ),
1824 * unitScale, *aPad );
1827 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1828 object2d_B->push_back( innerSeg );
1836 object2d_A = itemCSG2d;
1841 antiOutlineIntersectionList );
1847 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1857 for(
const OBJECT_2D* hole2d : intersecting )
1859 if( object2d_A->
Intersects( hole2d->GetBBox() ) )
1860 object2d_B->push_back( hole2d );
1864 for(
const OBJECT_2D* obj : antiOutlineIntersectionList )
1865 object2d_B->push_back( obj );
1867 if( object2d_B->empty() )
1897 if( object2d_A && isRoundHole )
1899 const float frontSurface = topZ + frontDepth;
1900 const float backSurface = botZ - backDepth;
1906 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1924 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1961 for(
PAD*
pad : footprint->Pads() )
1971 const glm::mat4& aFpMatrix,
bool aHasExtrudedBody,
1974 if( aHasExtrudedBody )
1981 float scaleZ = std::min( bboxW, bboxH ) * 0.5f;
1984 float offsetX = localCenter.
x /
pcbIUScale.IU_PER_MM;
1985 float offsetY = -localCenter.
y /
pcbIUScale.IU_PER_MM;
1990 SFVEC3F boxMin( offsetX - bboxW * 0.5f, offsetY - bboxH * 0.5f, 0.0f );
1991 SFVEC3F boxMax( offsetX + bboxW * 0.5f, offsetY + bboxH * 0.5f, scaleZ );
1995 for(
int i = 0; i < 8; ++i )
1997 SFVEC3F corner( ( i & 1 ) ? boxMax.x : boxMin.x, ( i & 2 ) ? boxMax.y : boxMin.y,
1998 ( i & 4 ) ? boxMax.z : boxMin.z );
2000 corners[i] =
SFVEC3F( aFpMatrix * glm::vec4( corner, 1.0f ) );
2003 static const int faces[6][4] = { { 4, 5, 7, 6 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 },
2004 { 3, 2, 6, 7 }, { 0, 4, 6, 2 }, { 1, 3, 7, 5 } };
2013 aDstContainer.
Add( triangle );
2016 for(
const int* face : faces )
2018 addTriangle( corners[face[0]], corners[face[2]], corners[face[1]] );
2019 addTriangle( corners[face[0]], corners[face[3]], corners[face[2]] );
2033 if(
chain.PointCount() < 3 )
2040 for(
int i = 0; i <
chain.PointCount(); i++ )
2043 SFVEC2F pt( (
float) a.
x * aBiuTo3d, (
float) ( -a.
y ) * aBiuTo3d );
2045 if( ( i == 0 ) || ( fabs( prevPt.x - pt.x ) > FLT_EPSILON ) || ( fabs( prevPt.y - pt.y ) > FLT_EPSILON ) )
2051 segNormals.push_back( sn );
2056 if( segNormals.size() >= 3 )
2058 std::vector<SFVEC2F> tmpNormals( segNormals.size() );
2059 unsigned int j = segNormals.size() - 1;
2061 for(
unsigned int i = 0; i < segNormals.size(); j = i++ )
2063 SFVEC2F slope = segNormals[j].m_Start - segNormals[i].m_Start;
2064 segNormals[i].m_Precalc_slope = slope;
2065 tmpNormals[i] = glm::normalize(
SFVEC2F( slope.y, -slope.x ) );
2068 j = segNormals.size() - 1;
2070 for(
unsigned int i = 0; i < segNormals.size(); j = i++ )
2072 const SFVEC2F& nBefore = tmpNormals[j];
2073 const SFVEC2F& nCur = tmpNormals[i];
2074 const SFVEC2F& nAfter = tmpNormals[( i + 1 ) % segNormals.size()];
2076 float dotBefore = glm::dot( nBefore, nCur );
2077 float dotAfter = glm::dot( nAfter, nCur );
2079 segNormals[i].m_Normals.m_Start =
2080 ( dotBefore < 0.7f ) ? nCur : glm::normalize( nBefore * dotBefore + nCur );
2081 segNormals[i].m_Normals.m_End = ( dotAfter < 0.7f ) ? nCur : glm::normalize( nAfter * dotAfter + nCur );
2084 SEGMENTS capSegments( segNormals.size() );
2086 for(
unsigned int i = 0; i < segNormals.size(); i++ )
2087 capSegments[i].m_Start = segNormals[i].m_Start;
2089 j = capSegments.size() - 1;
2091 for(
unsigned int i = 0; i < capSegments.size(); j = i++ )
2093 capSegments[i].m_inv_JY_minus_IY = 1.0f / ( capSegments[j].m_Start.y - capSegments[i].m_Start.y );
2094 capSegments[i].m_JX_minus_IX = capSegments[j].m_Start.x - capSegments[i].m_Start.x;
2098 outersAndHoles.
m_Outers.push_back( capSegments );
2100 aObjContainer.
Add(
new POLYGON_2D( segNormals, outersAndHoles, aBoardItem ) );
2106 size_t prevSize = aObjContainer.
GetList().size();
2108 added += aObjContainer.
GetList().size() - prevSize;
2134 float standoff3d = body->
m_standoff * biuTo3d;
2142 zBot = boardSurfaceZ + standoff3d + zOffset3d;
2143 zTop = zBot + bodyThickness;
2147 zTop = boardSurfaceZ - standoff3d - zOffset3d;
2148 zBot = zTop - bodyThickness;
2162 size_t prevCount = objList.size();
2173 auto it = objList.begin();
2174 std::advance( it, prevCount );
2176 for( ; it != objList.end(); ++it )
2183 aDstContainer.
Add( layerItem );
2187 if( standoff3d > 0.0f )
2194 float oppositeSurfaceZ =
m_boardAdapter.GetFootprintZPos( !isBack );
2195 float protrusion = 1.0f *
pcbIUScale.IU_PER_MM * biuTo3d;
2196 float pinZBot, pinZTop;
2200 pinZBot = oppositeSurfaceZ - protrusion + zOffset3d;
2201 pinZTop = boardSurfaceZ + standoff3d + zOffset3d;
2205 pinZTop = oppositeSurfaceZ + protrusion - zOffset3d;
2206 pinZBot = boardSurfaceZ - standoff3d - zOffset3d;
2209 auto addPinObjects =
2218 size_t prevPinCount = objList.size();
2222 auto pinIt = objList.begin();
2223 std::advance( pinIt, prevPinCount );
2225 for( ; pinIt != objList.end(); ++pinIt )
2232 aDstContainer.
Add( layerItem );
2238 addPinObjects( pinPoly, &
m_materials.m_Copper, metalColor, 0.0f );
2239 addPinObjects( pegPoly, bodyMaterial, objColor, 1.0f - (
float) c.
a );
2248 std::stop_token aStop )
2264 if( aStop.stop_requested() )
2267 bool hasModels = !fp->Models().empty();
2270 bool hasExtrudedBody =
false;
2272 if( fp->HasBody() && fp->GetBody()->GetExtruded()->m_show &&
m_boardAdapter.IsFootprintShown( fp ) )
2277 const glm::mat4 fpMatrix =
m_boardAdapter.GetFootprintMatrix( *fp );
2282 const wxString footprintBasePath =
m_boardAdapter.GetFootprintLibraryPath( fp );
2284 bool placeholderAdded =
false;
2288 if( !
model.m_Show ||
model.m_Filename.empty() )
2292 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
2293 embeddedFilesStack.push_back( fp->GetEmbeddedFiles() );
2294 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
2297 std::move( embeddedFilesStack ) );
2307 addModels( aDstContainer, modelPtr, modelMatrix, (
float)
model.m_Opacity,
2308 aSkipMaterialInformation, fp );
2310 else if(
m_boardAdapter.ShowMissingModels() && !placeholderAdded )
2313 placeholderAdded =
true;
2347 for(
unsigned int imat = 0; imat < a3DModel->
m_MaterialsSize; ++imat )
2355 float reflectionFactor = 0.0f;
2357 if( ( material.
m_Shininess - 0.35f ) > FLT_EPSILON )
2359 reflectionFactor = glm::clamp(
2360 glm::sqrt( ( material.
m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
2371 if(
m_boardAdapter.m_Cfg->m_Render.raytrace_procedural_textures )
2426 return materialVector;
2431 const glm::mat4& aModelMatrix,
float aFPOpacity,
2432 bool aSkipMaterialInformation,
BOARD_ITEM* aBoardItem )
2435 wxASSERT( a3DModel !=
nullptr );
2437 if( a3DModel ==
nullptr )
2441 wxASSERT( a3DModel->
m_Meshes !=
nullptr );
2445 if( aFPOpacity > 1.0f )
2448 if( aFPOpacity < 0.0f )
2456 if( !aSkipMaterialInformation )
2461 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
2463 for(
unsigned int mesh_i = 0; mesh_i < a3DModel->
m_MeshesSize; ++mesh_i )
2480 float fpTransparency;
2483 if( !aSkipMaterialInformation )
2492 for(
unsigned int faceIdx = 0; faceIdx < mesh.
m_FaceIdxSize; faceIdx += 3 )
2494 const unsigned int idx0 = mesh.
m_FaceIdx[faceIdx + 0];
2495 const unsigned int idx1 = mesh.
m_FaceIdx[faceIdx + 1];
2496 const unsigned int idx2 = mesh.
m_FaceIdx[faceIdx + 2];
2513 const SFVEC3F vt0 =
SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
2517 const SFVEC3F nt0 = glm::normalize(
SFVEC3F( normalMatrix * n0 ) );
2518 const SFVEC3F nt1 = glm::normalize(
SFVEC3F( normalMatrix * n1 ) );
2519 const SFVEC3F nt2 = glm::normalize(
SFVEC3F( normalMatrix * n2 ) );
2525 aDstContainer.
Add( newTriangle );
2527 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)
glm::mat4 CalcModelMatrix(const SFVEC3F &aOffset, const SFVEC3F &aRotation, const SFVEC3F &aScale)
Build the model-to-footprint transform used by rendering and picking.
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
bool GetExtrusionPinOutlines(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aPinPoly, SHAPE_POLY_SET &aPegPoly)
Get the hole outline polygons for extruded pin rendering.
void ApplyExtrusionTransform(SHAPE_POLY_SET &aOutline, const EXTRUDED_3D_BODY *aBody, const VECTOR2I &aFpPos)
Apply 2D extrusion transforms (rotation, scale, offset) to an outline.
EXTRUSION_MATERIAL_PROPS GetMaterialProps(EXTRUSION_MATERIAL aMaterial, const SFVEC3F &aDiffuse)
bool GetExtrusionOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aOutline, PCB_LAYER_ID aLayerOverride)
Get the extrusion outline polygon for a footprint in board coordinates.
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...
bool IsTriangleInRange(const unsigned int *aFaceIdx, unsigned int aTriangleIdx, unsigned int aVertexCount)
Test whether the three face indices of a triangle all reference valid vertices.
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
void Add(OBJECT_2D *aObject)
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.
static KIGFX::COLOR4D GetDefaultColor(EXTRUSION_MATERIAL aMaterial)
EXTRUSION_MATERIAL m_material
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Make solid geometry for objects on layers.
void SetColor(SFVEC3F aObjColor)
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
VECTOR2I GetPosition() const override
VECTOR2I GetDrillSize() const
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 EXTRUDED_3D_BODY * GetExtruded() 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....
Represent a sub polygon block.
std::shared_ptr< REPORTER > m_warningReporter
std::shared_ptr< REPORTER > m_activityReporter
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
SILK_SCREEN_NORMAL m_silkScreenMaterial
struct RENDER_3D_RAYTRACE_BASE::@013206213056006125230376122042346155134272177300 m_materials
std::mutex m_hitTestMutex
Serializes hover BVH use.
void addCountersinkPlating(const SFVEC2F &aCenter, float aTopInnerRadius, float aBottomInnerRadius, float aSurfaceZ, float aDepth, bool aIsFront)
BOARD_NORMAL m_boardMaterial
CONTAINER_3D m_objectContainer
std::vector< std::unique_ptr< BLINN_PHONG_MATERIAL > > m_extrusionMaterials
COPPER_NORMAL m_copperMaterial
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
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
bool addExtrudedBodyToRaytracer(CONTAINER_3D &aDstContainer, const FOOTPRINT *aFootprint)
void backfillPostMachine()
void addCounterborePlating(const BOARD_ITEM &aSource, const SFVEC2F &aCenter, float aInnerRadius, float aDepth, float aSurfaceZ, bool aIsFront)
CONTAINER_2D * m_outlineBoard2dObjects
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation, std::stop_token aStop={})
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.
std::unique_ptr< ACCELERATOR_3D > m_accelerator
void addPlaceholderToRaytracer(CONTAINER_3D &aDstContainer, const FOOTPRINT *aFootprint, const glm::mat4 &aFpMatrix, bool aHasExtrudedBody=false, float aOpacity=1.0f)
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
void Reload(bool aOnlyLoadCopperAndShapes, std::stop_token aStop={})
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 polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
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.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
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
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...
std::vector< SEGMENT_WITH_NORMALS > SEGMENTS_WIDTH_NORMALS
List used to test ray2d intersections.
std::vector< POLYSEGMENT > SEGMENTS
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 size_t addOutlineToRaytracerObjects(CONTAINER_2D &aObjContainer, const SHAPE_POLY_SET &aOutline, float aBiuTo3d, const BOARD_ITEM &aBoardItem)
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
Handle a subset of a polygon.
std::vector< SEGMENTS > m_Outers
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.
const SHAPE_LINE_CHAIN chain
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
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