53 const float f = ( sqrtf( 2.0f ) / 2.0f ) *
radius * texture_factor;
76 float aZtop,
float aZbot )
89 float aOuterRadius,
unsigned int aNr_sides_per_circle,
90 std::vector< SFVEC2F >& aInnerContourResult,
91 std::vector< SFVEC2F >& aOuterContourResult,
94 aInnerContourResult.clear();
95 aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
97 aOuterContourResult.clear();
98 aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
100 const int delta = 3600 / aNr_sides_per_circle;
102 for(
int ii = 0; ii < 3600; ii +=
delta )
104 float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
105 * 2.0f * glm::pi<float>() / 3600.0f;
108 aInnerContourResult.emplace_back( aCenter.x + rotatedDir.x * aInnerRadius,
109 aCenter.y + rotatedDir.y * aInnerRadius );
111 aOuterContourResult.emplace_back( aCenter.x + rotatedDir.x * aOuterRadius,
112 aCenter.y + rotatedDir.y * aOuterRadius );
115 aInnerContourResult.push_back( aInnerContourResult[0] );
116 aOuterContourResult.push_back( aOuterContourResult[0] );
118 wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
123 float aZtop,
float aZbot )
129 std::vector< SFVEC2F > innerContour;
130 std::vector< SFVEC2F > outerContour;
133 innerContour, outerContour,
false );
136 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
138 const SFVEC2F& vi0 = innerContour[i + 0];
139 const SFVEC2F& vi1 = innerContour[i + 1];
140 const SFVEC2F& vo0 = outerContour[i + 0];
141 const SFVEC2F& vo1 = outerContour[i + 1];
144 SFVEC3F( vi0.x, vi0.y, aZtop ),
145 SFVEC3F( vo0.x, vo0.y, aZtop ),
146 SFVEC3F( vo1.x, vo1.y, aZtop ) );
149 SFVEC3F( vo1.x, vo1.y, aZbot ),
150 SFVEC3F( vo0.x, vo0.y, aZbot ),
151 SFVEC3F( vi0.x, vi0.y, aZbot ) );
157 float aZtop,
float aZbot )
169 float aZtop,
float aZbot )
186 const float radius_of_the_square = sqrtf( aSeg->
GetRadiusSquared() * 2.0f );
187 const float radius_triangle_factor = ( radius_of_the_square -
radius ) /
radius;
190 rightDir.x *
radius * radius_triangle_factor );
193 leftDir.x *
radius * radius_triangle_factor );
197 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
198 rightEnd.y + texture_factor * factorS.y,
200 SFVEC3F( leftStart.x + texture_factor * factorE.x,
201 leftStart.y + texture_factor * factorE.y,
203 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
204 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
208 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
209 leftEnd.y + texture_factor * factorE.y, aZtop ),
210 SFVEC3F( rightStart.x + texture_factor * factorS.x,
211 rightStart.y + texture_factor * factorS.y, aZtop ),
213 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
218 SFVEC3F( leftStart.x + texture_factor * factorE.x,
219 leftStart.y + texture_factor * factorE.y,
221 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
222 rightEnd.y + texture_factor * factorS.y,
224 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
225 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
229 SFVEC3F( rightStart.x + texture_factor * factorS.x,
230 rightStart.y + texture_factor * factorS.y, aZbot ),
231 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
232 leftEnd.y + texture_factor * factorE.y, aZbot ),
234 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
239 SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
240 SFVEC3F( rightStart.x, rightStart.y, aZtop ),
241 SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
242 SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
245 SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
246 SFVEC3F( leftStart.x, leftStart.y, aZbot ),
247 SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
248 SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
256 if( aListHolesObject2d.size() == 0 )
263 for(
const OBJECT_2D* object2d : aListHolesObject2d )
265 switch( object2d->GetObjectType() )
276 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL::generateHoles: Object type not implemented" ) );
291 delete layerTriangles;
301 if( aContainer ==
nullptr )
306 if( listObject2d.size() == 0 )
315 unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
323 for(
const OBJECT_2D* object2d : listObject2d )
325 switch( object2d->GetObjectType() )
348 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL: Object type is not implemented" ) );
366 float layer_z_bot = 0.0f;
367 float layer_z_top = 0.0f;
391 if( listBoardObject2d.size() > 0 )
395 const float layer_z_top = 1.0f;
396 const float layer_z_bot = 0.0f;
402 for(
const OBJECT_2D* itemOnLayer : listBoardObject2d )
404 const OBJECT_2D* object2d_A = itemOnLayer;
424 layer_z_top, layer_z_top );
427 delete layerTriangles;
439 const int copperLayerCount =
m_boardAdapter.GetBoard()->GetCopperLayerCount();
441 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
442 const float boardBodyThickness =
m_boardAdapter.GetBoardBodyThickness();
445 const float boardZTop = 1.0f;
446 const float boardZBot = 0.0f;
449 auto normalizeZ = [&](
float absZ ) ->
float
453 float boardThick = boardTop - boardBot;
455 if( boardThick <= 0 )
459 return ( absZ - boardBot ) / boardThick;
473 const float holeDiameter =
via->GetDrillValue() * unitScale;
474 const float holeInnerRadius = holeDiameter / 2.0f;
475 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
477 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
480 via->LayerPair( &topLayer, &bottomLayer );
482 float viaZTop, viaZBot,
dummy;
487 const float secondaryDrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
488 const float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
490 if( secondaryDrillRadius > holeOuterRadius || tertiaryDrillRadius > holeOuterRadius )
496 if( secondaryDrillRadius > holeOuterRadius )
498 plug_end_layer =
via->GetSecondaryDrillEndLayer();
501 if( tertiaryDrillRadius > holeOuterRadius )
503 plug_start_layer =
via->GetTertiaryDrillStartLayer();
507 float plugZTop, plugZBot, temp;
513 plugZTop, plugZBot, nrSegments, plugTriangles );
517 const auto frontMode =
via->GetFrontPostMachining();
519 if( frontMode.has_value()
523 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
524 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
526 if( frontRadius > holeOuterRadius && frontDepth > 0 )
529 float pmBottomZ = normalizeZ( viaZTop - frontDepth );
530 float plugZBot = normalizeZ( viaZBot );
532 if( pmBottomZ > plugZBot )
538 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
543 pmBottomZ, plugZBot, nrSegments, plugTriangles );
550 const auto backMode =
via->GetBackPostMachining();
552 if( backMode.has_value()
556 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
557 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
559 if( backRadius > holeOuterRadius && backDepth > 0 )
562 float plugZTop = normalizeZ( viaZTop );
563 float pmTopZ = normalizeZ( viaZBot + backDepth );
565 if( plugZTop > pmTopZ )
571 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
576 plugZTop, pmTopZ, nrSegments, plugTriangles );
586 for(
const PAD*
pad : footprint->Pads() )
588 if( !
pad->HasHole() )
594 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
595 -
pad->GetPosition().y * unitScale );
596 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
597 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
598 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
pad->GetDrillSize().x );
600 float padZTop, padZBot, padDummy;
605 const auto frontMode =
pad->GetFrontPostMachining();
607 if( frontMode.has_value()
611 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
612 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
614 if( frontRadius > holeOuterRadius && frontDepth > 0 )
616 float pmBottomZ = normalizeZ( padZTop - frontDepth );
617 float plugZBot = normalizeZ( padZBot );
619 if( pmBottomZ > plugZBot )
625 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
630 pmBottomZ, plugZBot, nrSegments, plugTriangles );
637 const auto backMode =
pad->GetBackPostMachining();
639 if( backMode.has_value()
643 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
644 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
646 if( backRadius > holeOuterRadius && backDepth > 0 )
648 float plugZTop = normalizeZ( padZTop );
649 float pmTopZ = normalizeZ( padZBot + backDepth );
651 if( plugZTop > pmTopZ )
657 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
662 plugZTop, pmTopZ, nrSegments, plugTriangles );
681 boardZTop, boardZTop );
685 delete plugTriangles;
699 if( !fp->HasExtrudedBody() )
720 bool isBack = fp->IsFlipped();
722 float standoff3d = body->
m_standoff * biuTo3d;
730 zBot = boardSurfaceZ + standoff3d + zOffset3d;
731 zTop = zBot + bodyThickness;
735 zTop = boardSurfaceZ - standoff3d - zOffset3d;
736 zBot = zTop - bodyThickness;
744 if( triList.empty() )
764 if( standoff3d > 0.0f )
772 float oppositeSurfaceZ =
m_boardAdapter.GetFootprintZPos( !isBack );
773 float protrusion = 1.0f *
pcbIUScale.IU_PER_MM * biuTo3d;
774 float pinZBot, pinZTop;
778 pinZBot = oppositeSurfaceZ - protrusion;
779 pinZTop = boardSurfaceZ + standoff3d;
783 pinZTop = oppositeSurfaceZ + protrusion;
784 pinZBot = boardSurfaceZ - standoff3d;
792 if( !pinTriList.empty() )
831 m_camera.SetBoardLookAtPos( camera_pos );
833 if( aStatusReporter )
834 aStatusReporter->
Report(
_(
"Load OpenGL: board" ) );
855 if(
m_boardAdapter.GetFrontCounterborePolys().OutlineCount() > 0 )
861 if(
m_boardAdapter.GetFrontCountersinkPolys().OutlineCount() > 0 )
883 if( aStatusReporter )
884 aStatusReporter->
Report(
_(
"Load OpenGL: holes and vias" ) );
910 wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
914 if( outerMapHoles.size() > 0 )
916 float layer_z_bot = 0.0f;
917 float layer_z_top = 0.0f;
919 for(
const auto& [ layer, poly ] : outerMapHoles )
924 layer_z_top, layer_z_bot,
false );
927 for(
const auto& [ layer, poly ] : innerMapHoles )
932 layer_z_top, layer_z_bot,
false );
940 if( aStatusReporter )
941 aStatusReporter->
Report(
_(
"Load OpenGL: layers" ) );
943 std::bitset<LAYER_3D_END> visibilityFlags =
m_boardAdapter.GetVisibleLayers();
947 for(
const auto& [ layer, container2d ] :
m_boardAdapter.GetLayerMap() )
952 if( aStatusReporter )
955 aStatusReporter->
Report( wxString::Format(
_(
"Load OpenGL layer %s" ), msg ) );
965 if( map_poly.contains( layer ) )
967 polyListSubtracted = *map_poly.at( layer );
985 else if( layer ==
B_Cu )
1004 polyList = &polyListSubtracted;
1011 if( oglList !=
nullptr )
1020 if( frontPlatedCopperPolys )
1038 if( backPlatedCopperPolys )
1066 if( aStatusReporter )
1067 aStatusReporter->
Report(
_(
"Loading 3D models..." ) );
1073 if( aStatusReporter )
1078 aStatusReporter->
Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1102 if( aOutZtop < aOutZbot )
1104 float tmpFloat = aOutZbot;
1105 aOutZbot = aOutZtop;
1106 aOutZtop = tmpFloat;
1112 float aOuterRadius,
float aZtop,
float aZbot,
1113 unsigned int aNr_sides_per_circle,
1116 std::vector< SFVEC2F > innerContour;
1117 std::vector< SFVEC2F > outerContour;
1119 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1120 outerContour,
false );
1122 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1124 const SFVEC2F& vi0 = innerContour[i + 0];
1125 const SFVEC2F& vi1 = innerContour[i + 1];
1126 const SFVEC2F& vo0 = outerContour[i + 0];
1127 const SFVEC2F& vo1 = outerContour[i + 1];
1130 SFVEC3F( vi0.x, vi0.y, aZtop ),
1131 SFVEC3F( vo0.x, vo0.y, aZtop ),
1132 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1135 SFVEC3F( vo1.x, vo1.y, aZbot ),
1136 SFVEC3F( vo0.x, vo0.y, aZbot ),
1137 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1146 float aOuterRadius,
float aZtop,
float aZbot,
1147 unsigned int aNr_sides_per_circle,
1159 float radialDiff = aOuterRadius - aInnerRadius;
1163 if( angleRad < 0.01f )
1166 float innerHeight = radialDiff / tanf( angleRad );
1167 float totalHeight = aZtop - aZbot;
1170 if( innerHeight > totalHeight )
1171 innerHeight = totalHeight;
1173 float zInnerTop = aZbot + innerHeight;
1175 std::vector< SFVEC2F > innerContour;
1176 std::vector< SFVEC2F > outerContour;
1178 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1179 outerContour,
false );
1181 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1183 const SFVEC2F& vi0 = innerContour[i + 0];
1184 const SFVEC2F& vi1 = innerContour[i + 1];
1185 const SFVEC2F& vo0 = outerContour[i + 0];
1186 const SFVEC2F& vo1 = outerContour[i + 1];
1190 SFVEC3F( vi0.x, vi0.y, zInnerTop ),
1191 SFVEC3F( vo0.x, vo0.y, aZtop ),
1192 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1196 SFVEC3F( vo1.x, vo1.y, aZbot ),
1197 SFVEC3F( vo0.x, vo0.y, aZbot ),
1198 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1212 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1214 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1216 float a0 =
delta * i;
1217 float a1 =
delta * ( i + 1 );
1218 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1219 aCenter.y + sinf( a0 ) * aRadius, aZ );
1220 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1221 aCenter.y + sinf( a1 ) * aRadius, aZ );
1222 const SFVEC3F c( aCenter.x, aCenter.y, aZ );
1233 float aDepth,
unsigned int aNr_sides_per_circle,
1236 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1237 const SFVEC3F c( aCenter.x, aCenter.y, aTop ? aZ - aDepth : aZ + aDepth );
1239 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1241 float a0 =
delta * i;
1242 float a1 =
delta * ( i + 1 );
1243 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1244 aCenter.y + sinf( a0 ) * aRadius, aZ );
1245 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1246 aCenter.y + sinf( a1 ) * aRadius, aZ );
1261 float aHoleInnerRadius,
1264 float aPlatingThickness3d,
1271 if( !aDstLayer || aPlatingThickness3d <= 0.0f || aHoleInnerRadius <= 0.0f )
1280 if( aSizeIU <= 0 || aDepthIU <= 0 )
1283 const float radius = aSizeIU * 0.5f * aUnitScale;
1284 const float depth = aDepthIU * aUnitScale;
1286 if(
radius <= aHoleInnerRadius || depth <= 0.0f )
1289 float zEnd = aIsFront ? ( aZSurface - depth ) : ( aZSurface + depth );
1294 const float zTop = std::max( aZSurface, zEnd );
1295 const float zBot = std::min( aZSurface, zEnd );
1297 const int diameterBIU = std::max( aSizeIU,
1299 (
int) ( ( aHoleInnerRadius * 2.0f )
1301 const unsigned int nrSegments =
1302 std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( diameterBIU ) );
1307 nrSegments, aDstLayer );
1311 float csTopRadius =
radius;
1312 float csBotRadius = aHoleInnerRadius;
1314 std::vector< SFVEC2F > innerContourTop, outerContourTop;
1315 std::vector< SFVEC2F > innerContourBot, outerContourBot;
1317 generateRing( aHoleCenter, csTopRadius, csTopRadius + aPlatingThickness3d, nrSegments,
1318 innerContourTop, outerContourTop,
false );
1319 generateRing( aHoleCenter, csBotRadius, csBotRadius + aPlatingThickness3d, nrSegments,
1320 innerContourBot, outerContourBot,
false );
1322 for(
unsigned int i = 0; i < ( innerContourTop.size() - 1 ); ++i )
1324 const SFVEC2F& vi0_top = innerContourTop[i + 0];
1325 const SFVEC2F& vi1_top = innerContourTop[i + 1];
1326 const SFVEC2F& vo0_top = outerContourTop[i + 0];
1327 const SFVEC2F& vo1_top = outerContourTop[i + 1];
1329 const SFVEC2F& vi0_bot = innerContourBot[i + 0];
1330 const SFVEC2F& vi1_bot = innerContourBot[i + 1];
1331 const SFVEC2F& vo0_bot = outerContourBot[i + 0];
1332 const SFVEC2F& vo1_bot = outerContourBot[i + 1];
1335 SFVEC3F( vi1_top.x, vi1_top.y, zTop ),
1336 SFVEC3F( vi0_top.x, vi0_top.y, zTop ),
1337 SFVEC3F( vi0_bot.x, vi0_bot.y, zBot ),
1338 SFVEC3F( vi1_bot.x, vi1_bot.y, zBot ) );
1341 SFVEC3F( vo1_top.x, vo1_top.y, zTop ),
1342 SFVEC3F( vo0_top.x, vo0_top.y, zTop ),
1343 SFVEC3F( vo0_bot.x, vo0_bot.y, zBot ),
1344 SFVEC3F( vo1_bot.x, vo1_bot.y, zBot ) );
1359 float averageDiameter =
m_boardAdapter.GetAverageViaHoleDiameter();
1360 unsigned int averageSegCount =
m_boardAdapter.GetCircleSegmentCount( averageDiameter );
1361 unsigned int trianglesEstimate = averageSegCount * 8 *
m_boardAdapter.GetViaCount();
1371 bool isBackdrilled =
via->GetSecondaryDrillSize().has_value();
1372 bool isTertiarydrilled =
via->GetTertiaryDrillSize().has_value();
1383 && !hasFrontPostMachining && !hasBackPostMachining )
1388 const float holediameter =
via->GetDrillValue() * aUnitScale;
1389 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1390 const float hole_inner_radius = holediameter / 2.0f;
1392 const SFVEC2F via_center(
via->GetStart().x * aUnitScale,
1393 -
via->GetStart().y * aUnitScale );
1396 via->LayerPair( &top_layer, &bottom_layer );
1398 float ztop, zbot,
dummy;
1403 wxASSERT( zbot < ztop );
1405 float ztop_plated = ztop;
1406 float zbot_plated = zbot;
1416 zbot_plated = std::max( zbot_plated, secZEnd );
1419 if( isTertiarydrilled )
1427 ztop_plated = std::min( ztop_plated, terZEnd );
1430 auto applyViaPostMachining = [&](
bool isFront )
1432 auto modeOpt = isFront ?
via->GetFrontPostMachining()
1433 :
via->GetBackPostMachining();
1441 int sizeIU = isFront ?
via->GetFrontPostMachiningSize()
1442 :
via->GetBackPostMachiningSize();
1443 int depthIU = isFront ?
via->GetFrontPostMachiningDepth()
1444 :
via->GetBackPostMachiningDepth();
1445 float zSurface = isFront ? ztop : zbot;
1449 sizeIU, depthIU, hole_inner_radius, zSurface,
1450 isFront, aPlatingThickness3d, aUnitScale, &zEnd ) )
1453 ztop_plated = std::min( ztop_plated, zEnd );
1455 zbot_plated = std::max( zbot_plated, zEnd );
1459 if( hasFrontPostMachining )
1460 applyViaPostMachining(
true );
1461 if( hasBackPostMachining )
1462 applyViaPostMachining(
false );
1464 generateCylinder( via_center, hole_inner_radius, hole_inner_radius + aPlatingThickness3d, ztop_plated,
1465 zbot_plated, nrSegments, layerTriangleVIA );
1468 const float padFrontSurface =
1471 const float padBackSurface =
1477 for(
const PAD*
pad : footprint->Pads() )
1482 if( !
pad->HasHole() )
1488 const SFVEC2F padCenter(
pad->GetPosition().x * aUnitScale,
1489 -
pad->GetPosition().y * aUnitScale );
1490 const float holeInnerRadius =
1491 pad->GetDrillSize().x * 0.5f * aUnitScale;
1493 auto emitPadPostMachining = [&](
bool isFront )
1495 auto modeOpt = isFront ?
pad->GetFrontPostMachining()
1496 :
pad->GetBackPostMachining();
1504 int sizeIU = isFront ?
pad->GetFrontPostMachiningSize()
1505 :
pad->GetBackPostMachiningSize();
1506 int depthIU = isFront ?
pad->GetFrontPostMachiningDepth()
1507 :
pad->GetBackPostMachiningDepth();
1508 float zSurface = isFront ? padFrontSurface : padBackSurface;
1511 sizeIU, depthIU, holeInnerRadius, zSurface,
1512 isFront, aPlatingThickness3d, aUnitScale,
1516 emitPadPostMachining(
true );
1517 emitPadPostMachining(
false );
1523 delete layerTriangleVIA;
1551 via->GetDrill() / 2 + aPlatingThickness,
1561 for(
const PAD*
pad : footprint->Pads() )
1565 if( !
pad->HasHole() )
1568 pad->TransformHoleToPolygon( tht_outer_holes_poly, aPlatingThickness,
1570 pad->TransformHoleToPolygon( tht_inner_holes_poly, 0,
1587 if( holes2D.size() > 0 &&
m_boardAdapter.m_Cfg->m_Render.show_plated_barrels )
1589 float layer_z_top, layer_z_bot,
dummy;
1596 for(
const OBJECT_2D* itemOnLayer : holes2D )
1598 const OBJECT_2D* object2d_A = itemOnLayer;
1616 layer_z_bot, layer_z_top,
1617 aUnitScale,
false );
1620 layer_z_top, layer_z_top );
1623 delete layerTriangles;
1643 const float holediameter =
via->GetDrillValue() * aUnitScale;
1644 const float hole_radius = holediameter / 2.0f + 2.0f * aPlatingThickness3d;
1646 -
via->GetStart().y * aUnitScale );
1647 unsigned int seg =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1650 via->LayerPair( &top_layer, &bottom_layer );
1651 float ztop, zbot,
dummy;
1664 const auto frontPostMachining =
1666 const auto backPostMachining =
1674 bool hasFrontBackdrill =
via->GetSecondaryDrillStartLayer() ==
F_Cu;
1675 bool hasBackBackdrill =
via->GetSecondaryDrillStartLayer() ==
B_Cu;
1677 const float depth = hole_radius * 0.3f;
1679 if( frontCovering && !hasFrontPostMachining && !hasFrontBackdrill )
1681 if( filled || !frontPlugged )
1687 if( backCovering && !hasBackPostMachining && !hasBackBackdrill )
1689 if( filled || !backPlugged )
1712 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1714 const float platingThickness3d = platingThickness * unitScale;
1727 if( wxFrame* frame =
dynamic_cast<wxFrame*
>(
m_canvas->GetParent() ) )
1763 wxString libraryName = footprint->GetFPID().GetLibNickname();
1764 wxString footprintBasePath = wxEmptyString;
1771 std::optional<LIBRARY_TABLE_ROW*> fpRow =
1784 for(
const FP_3DMODEL& fp_model : footprint->Models() )
1786 if( fp_model.m_Show && !fp_model.m_Filename.empty() )
1788 if( aStatusReporter )
1792 wxFileName fn( fp_model.m_Filename );
1793 aStatusReporter->
Report( wxString::Format(
_(
"Loading %s..." ),
1794 fn.GetFullName() ) );
1802 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
1803 embeddedFilesStack.push_back( footprint->GetEmbeddedFiles() );
1804 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
1806 const S3DMODEL* modelPtr = cacheMgr->
GetModel( fp_model.m_Filename, footprintBasePath,
1807 std::move( embeddedFilesStack ) );
MATERIAL_MODE
Render 3d model shape materials mode.
Defines math related functions.
void ApplyExtrusionTransform(SHAPE_POLY_SET &aOutline, const EXTRUDED_3D_BODY *aBody, const VECTOR2I &aFpPos)
Apply 2D extrusion transforms (rotation, scale, offset) to an outline.
bool GetExtrusionPinOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aPinPoly)
Get the pin outline polygons for extruded THT pin rendering.
bool GetExtrusionOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aOutline, PCB_LAYER_ID aLayerOverride)
Get the extrusion outline polygon for a footprint in board coordinates.
constexpr EDA_IU_SCALE pcbIUScale
std::map< PCB_LAYER_ID, SHAPE_POLY_SET * > MAP_POLY
A type that stores polysets for each layer id.
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.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
const LIST_OBJECT2D & GetList() const
const SFVEC2F & GetCenter() const
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...
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
static OBJECT_2D_STATS & Instance()
OBJECT_2D_TYPE GetObjectType() const
Store the OpenGL display lists to related with a layer.
Simple non-intersecting polygon with 4 points.
const SFVEC2F & GetV3() const
const SFVEC2F & GetV0() const
const SFVEC2F & GetV1() const
const SFVEC2F & GetV2() const
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
OPENGL_RENDER_LIST * m_board
void reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
void renderExtrudedBodies()
OPENGL_RENDER_LIST * generateHoles(const LIST_OBJECT2D &aListHolesObject2d, const SHAPE_POLY_SET &aPoly, float aZtop, float aZbot, bool aInvertFaces, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
void generateCylinder(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST *aDstLayer)
OPENGL_RENDER_LIST * m_outerThroughHoleRings
OPENGL_RENDER_LIST * m_offboardPadsFront
void generateRing(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, unsigned int aNr_sides_per_circle, std::vector< SFVEC2F > &aInnerContourResult, std::vector< SFVEC2F > &aOuterContourResult, bool aInvertOrder)
SHAPE_POLY_SET m_antiBoardPolys
The negative polygon representation of the board outline.
void load3dModels(REPORTER *aStatusReporter)
Load footprint models from the cache and load it to openGL lists in the form of MODEL_3D objects.
void generateViasAndPads()
OPENGL_RENDER_LIST * generateLayerList(const BVH_CONTAINER_2D *aContainer, const SHAPE_POLY_SET *aPolyList, PCB_LAYER_ID aLayer, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
OPENGL_RENDER_LIST * m_microviaHoles
OPENGL_RENDER_LIST * createBoard(const SHAPE_POLY_SET &aBoardPoly, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
void Load3dModelsIfNeeded()
Load footprint models if they are not already loaded, i.e.
std::map< const FOOTPRINT *, OPENGL_RENDER_LIST * > m_extrudedPadLists
void addObjectTriangles(const RING_2D *aRing, TRIANGLE_DISPLAY_LIST *aDstLayer, float aZtop, float aZbot)
MAP_OGL_DISP_LISTS m_layers
MAP_OGL_DISP_LISTS m_innerLayerHoles
OPENGL_RENDER_LIST * m_boardWithHoles
void generateInvCone(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST *aDstLayer, EDA_ANGLE aAngle)
MAP_OGL_DISP_LISTS m_outerLayerHoles
OPENGL_RENDER_LIST * m_offboardPadsBack
std::map< wxString, MODEL_3D * > m_3dModelMap
OPENGL_RENDER_LIST * m_viaBackCover
OPENGL_RENDER_LIST * m_viaFrontCover
OPENGL_RENDER_LIST * generateEmptyLayerList(PCB_LAYER_ID aLayer)
LIST_TRIANGLES m_triangles
store pointers so can be deleted latter
OPENGL_RENDER_LIST * m_outerViaThroughHoles
OPENGL_RENDER_LIST * m_outerThroughHoles
void generateViaCovers(float aPlatingThickness3d, float aUnitScale)
OPENGL_RENDER_LIST * m_platedPadsFront
void createPlaceholderModel()
void generatePlatedHoleShells(int aPlatingThickness, float aUnitScale)
std::map< const FOOTPRINT *, OPENGL_RENDER_LIST * > m_extrudedBodyLists
void generateDisk(const SFVEC2F &aCenter, float aRadius, float aZ, unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST *aDstLayer, bool aTop)
OPENGL_RENDER_LIST * m_postMachinePlugs
Board material plugs for backdrill/counterbore/countersink.
bool appendPostMachiningGeometry(TRIANGLE_DISPLAY_LIST *aDstLayer, const SFVEC2F &aHoleCenter, PAD_DRILL_POST_MACHINING_MODE aMode, int aSizeIU, int aDepthIU, float aHoleInnerRadius, float aZSurface, bool aIsFront, float aPlatingThickness3d, float aUnitScale, float *aZEnd)
OPENGL_RENDER_LIST * m_antiBoard
void getLayerZPos(PCB_LAYER_ID aLayerID, float &aOutZtop, float &aOutZbot) const
OPENGL_RENDER_LIST * m_padHoles
void addTopAndBottomTriangles(TRIANGLE_DISPLAY_LIST *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot)
void generateViaBarrels(float aPlatingThickness3d, float aUnitScale)
OPENGL_RENDER_LIST * m_platedPadsBack
void generateDimple(const SFVEC2F &aCenter, float aRadius, float aZ, float aDepth, unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST *aDstLayer, bool aTop)
void backfillPostMachine()
Create ring-shaped plugs for holes that have backdrill or post-machining.
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.
float GetOuterRadius() const
float GetInnerRadius() const
const SFVEC2F & GetCenter() const
const SFVEC2F & GetLeftEnd() const
const SFVEC2F & GetRightEnd() const
const SFVEC2F & GetLeftStar() const
const SFVEC2F & GetLeftDir() const
const SFVEC2F & GetEnd() const
float GetRadiusSquared() const
const SFVEC2F & GetStart() const
const SFVEC2F & GetRightDir() const
const SFVEC2F & GetRightStar() const
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 RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
A wrapper for reporting to a specific text location in a statusbar.
const SFVEC2F & GetP2() const
const SFVEC2F & GetP3() const
const SFVEC2F & GetP1() const
Store arrays of triangles to be used to create display lists.
TRIANGLE_LIST * m_layer_bot_segment_ends
void AddToMiddleContours(const SHAPE_LINE_CHAIN &outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
TRIANGLE_LIST * m_layer_middle_contours_quads
TRIANGLE_LIST * m_layer_top_segment_ends
TRIANGLE_LIST * m_layer_bot_triangles
TRIANGLE_LIST * m_layer_top_triangles
void AddTriangle(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3)
void AddQuad(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4)
unsigned int GetVertexSize() const
std::list< OBJECT_2D * > LIST_OBJECT2D
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
Declaration of the eda_3d_viewer class.
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
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
#define SIZE_OF_CIRCLE_TEXTURE
std::vector< FAB_LAYER_COLOR > dummy
Store the a model based on meshes and materials.
KIBIS top(path, &reporter)
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I