49 const float f = ( sqrtf( 2.0f ) / 2.0f ) *
radius * texture_factor;
72 float aZtop,
float aZbot )
85 float aOuterRadius,
unsigned int aNr_sides_per_circle,
86 std::vector< SFVEC2F >& aInnerContourResult,
87 std::vector< SFVEC2F >& aOuterContourResult,
90 aInnerContourResult.clear();
91 aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
93 aOuterContourResult.clear();
94 aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
96 const int delta = 3600 / aNr_sides_per_circle;
98 for(
int ii = 0; ii < 3600; ii +=
delta )
100 float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
101 * 2.0f * glm::pi<float>() / 3600.0f;
104 aInnerContourResult.emplace_back( aCenter.x + rotatedDir.x * aInnerRadius,
105 aCenter.y + rotatedDir.y * aInnerRadius );
107 aOuterContourResult.emplace_back( aCenter.x + rotatedDir.x * aOuterRadius,
108 aCenter.y + rotatedDir.y * aOuterRadius );
111 aInnerContourResult.push_back( aInnerContourResult[0] );
112 aOuterContourResult.push_back( aOuterContourResult[0] );
114 wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
119 float aZtop,
float aZbot )
125 std::vector< SFVEC2F > innerContour;
126 std::vector< SFVEC2F > outerContour;
129 innerContour, outerContour,
false );
132 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
134 const SFVEC2F& vi0 = innerContour[i + 0];
135 const SFVEC2F& vi1 = innerContour[i + 1];
136 const SFVEC2F& vo0 = outerContour[i + 0];
137 const SFVEC2F& vo1 = outerContour[i + 1];
140 SFVEC3F( vi0.x, vi0.y, aZtop ),
141 SFVEC3F( vo0.x, vo0.y, aZtop ),
142 SFVEC3F( vo1.x, vo1.y, aZtop ) );
145 SFVEC3F( vo1.x, vo1.y, aZbot ),
146 SFVEC3F( vo0.x, vo0.y, aZbot ),
147 SFVEC3F( vi0.x, vi0.y, aZbot ) );
153 float aZtop,
float aZbot )
165 float aZtop,
float aZbot )
182 const float radius_of_the_square = sqrtf( aSeg->
GetRadiusSquared() * 2.0f );
183 const float radius_triangle_factor = ( radius_of_the_square -
radius ) /
radius;
186 rightDir.x *
radius * radius_triangle_factor );
189 leftDir.x *
radius * radius_triangle_factor );
193 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
194 rightEnd.y + texture_factor * factorS.y,
196 SFVEC3F( leftStart.x + texture_factor * factorE.x,
197 leftStart.y + texture_factor * factorE.y,
199 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
200 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
204 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
205 leftEnd.y + texture_factor * factorE.y, aZtop ),
206 SFVEC3F( rightStart.x + texture_factor * factorS.x,
207 rightStart.y + texture_factor * factorS.y, aZtop ),
209 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
214 SFVEC3F( leftStart.x + texture_factor * factorE.x,
215 leftStart.y + texture_factor * factorE.y,
217 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
218 rightEnd.y + texture_factor * factorS.y,
220 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
221 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
225 SFVEC3F( rightStart.x + texture_factor * factorS.x,
226 rightStart.y + texture_factor * factorS.y, aZbot ),
227 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
228 leftEnd.y + texture_factor * factorE.y, aZbot ),
230 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
235 SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
236 SFVEC3F( rightStart.x, rightStart.y, aZtop ),
237 SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
238 SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
241 SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
242 SFVEC3F( leftStart.x, leftStart.y, aZbot ),
243 SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
244 SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
252 if( aListHolesObject2d.size() == 0 )
259 for(
const OBJECT_2D* object2d : aListHolesObject2d )
261 switch( object2d->GetObjectType() )
272 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL::generateHoles: Object type not implemented" ) );
287 delete layerTriangles;
297 if( aContainer ==
nullptr )
302 if( listObject2d.size() == 0 )
311 unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
319 for(
const OBJECT_2D* object2d : listObject2d )
321 switch( object2d->GetObjectType() )
344 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL: Object type is not implemented" ) );
362 float layer_z_bot = 0.0f;
363 float layer_z_top = 0.0f;
387 if( listBoardObject2d.size() > 0 )
391 const float layer_z_top = 1.0f;
392 const float layer_z_bot = 0.0f;
398 for(
const OBJECT_2D* itemOnLayer : listBoardObject2d )
400 const OBJECT_2D* object2d_A = itemOnLayer;
420 layer_z_top, layer_z_top );
423 delete layerTriangles;
435 const int copperLayerCount =
m_boardAdapter.GetBoard()->GetCopperLayerCount();
437 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
438 const float boardBodyThickness =
m_boardAdapter.GetBoardBodyThickness();
441 const float boardZTop = 1.0f;
442 const float boardZBot = 0.0f;
445 auto normalizeZ = [&](
float absZ ) ->
float
449 float boardThick = boardTop - boardBot;
451 if( boardThick <= 0 )
455 return ( absZ - boardBot ) / boardThick;
469 const float holeDiameter =
via->GetDrillValue() * unitScale;
470 const float holeInnerRadius = holeDiameter / 2.0f;
471 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
473 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
476 via->LayerPair( &topLayer, &bottomLayer );
478 float viaZTop, viaZBot,
dummy;
483 const float secondaryDrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
484 const float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
486 if( secondaryDrillRadius > holeOuterRadius || tertiaryDrillRadius > holeOuterRadius )
492 if( secondaryDrillRadius > holeOuterRadius )
494 plug_end_layer =
via->GetSecondaryDrillEndLayer();
497 if( tertiaryDrillRadius > holeOuterRadius )
499 plug_start_layer =
via->GetTertiaryDrillStartLayer();
503 float plugZTop, plugZBot, temp;
509 plugZTop, plugZBot, nrSegments, plugTriangles );
513 const auto frontMode =
via->GetFrontPostMachining();
515 if( frontMode.has_value()
519 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
520 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
522 if( frontRadius > holeOuterRadius && frontDepth > 0 )
525 float pmBottomZ = normalizeZ( viaZTop - frontDepth );
526 float plugZBot = normalizeZ( viaZBot );
528 if( pmBottomZ > plugZBot )
534 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
539 pmBottomZ, plugZBot, nrSegments, plugTriangles );
546 const auto backMode =
via->GetBackPostMachining();
548 if( backMode.has_value()
552 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
553 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
555 if( backRadius > holeOuterRadius && backDepth > 0 )
558 float plugZTop = normalizeZ( viaZTop );
559 float pmTopZ = normalizeZ( viaZBot + backDepth );
561 if( plugZTop > pmTopZ )
567 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
572 plugZTop, pmTopZ, nrSegments, plugTriangles );
582 for(
const PAD*
pad : footprint->Pads() )
584 if( !
pad->HasHole() )
590 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
591 -
pad->GetPosition().y * unitScale );
592 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
593 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
594 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
pad->GetDrillSize().x );
596 float padZTop, padZBot, padDummy;
601 const auto frontMode =
pad->GetFrontPostMachining();
603 if( frontMode.has_value()
607 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
608 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
610 if( frontRadius > holeOuterRadius && frontDepth > 0 )
612 float pmBottomZ = normalizeZ( padZTop - frontDepth );
613 float plugZBot = normalizeZ( padZBot );
615 if( pmBottomZ > plugZBot )
621 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
626 pmBottomZ, plugZBot, nrSegments, plugTriangles );
633 const auto backMode =
pad->GetBackPostMachining();
635 if( backMode.has_value()
639 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
640 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
642 if( backRadius > holeOuterRadius && backDepth > 0 )
644 float plugZTop = normalizeZ( padZTop );
645 float pmTopZ = normalizeZ( padZBot + backDepth );
647 if( plugZTop > pmTopZ )
653 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
658 plugZTop, pmTopZ, nrSegments, plugTriangles );
677 boardZTop, boardZTop );
681 delete plugTriangles;
695 if( !fp->HasExtrudedBody() )
716 bool isBack = fp->IsFlipped();
718 float standoff3d = body->
m_standoff * biuTo3d;
726 zBot = boardSurfaceZ + standoff3d + zOffset3d;
727 zTop = zBot + bodyThickness;
731 zTop = boardSurfaceZ - standoff3d - zOffset3d;
732 zBot = zTop - bodyThickness;
740 if( triList.empty() )
760 if( standoff3d > 0.0f )
768 float oppositeSurfaceZ =
m_boardAdapter.GetFootprintZPos( !isBack );
769 float protrusion = 1.0f *
pcbIUScale.IU_PER_MM * biuTo3d;
770 float pinZBot, pinZTop;
774 pinZBot = oppositeSurfaceZ - protrusion;
775 pinZTop = boardSurfaceZ + standoff3d;
779 pinZTop = oppositeSurfaceZ + protrusion;
780 pinZBot = boardSurfaceZ - standoff3d;
788 if( !pinTriList.empty() )
827 m_camera.SetBoardLookAtPos( camera_pos );
829 if( aStatusReporter )
830 aStatusReporter->
Report(
_(
"Load OpenGL: board" ) );
851 if(
m_boardAdapter.GetFrontCounterborePolys().OutlineCount() > 0 )
857 if(
m_boardAdapter.GetFrontCountersinkPolys().OutlineCount() > 0 )
879 if( aStatusReporter )
880 aStatusReporter->
Report(
_(
"Load OpenGL: holes and vias" ) );
906 wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
910 if( outerMapHoles.size() > 0 )
912 float layer_z_bot = 0.0f;
913 float layer_z_top = 0.0f;
915 for(
const auto& [ layer, poly ] : outerMapHoles )
920 layer_z_top, layer_z_bot,
false );
923 for(
const auto& [ layer, poly ] : innerMapHoles )
928 layer_z_top, layer_z_bot,
false );
936 if( aStatusReporter )
937 aStatusReporter->
Report(
_(
"Load OpenGL: layers" ) );
939 std::bitset<LAYER_3D_END> visibilityFlags =
m_boardAdapter.GetVisibleLayers();
943 for(
const auto& [ layer, container2d ] :
m_boardAdapter.GetLayerMap() )
948 if( aStatusReporter )
951 aStatusReporter->
Report( wxString::Format(
_(
"Load OpenGL layer %s" ), msg ) );
961 if( map_poly.contains( layer ) )
963 polyListSubtracted = *map_poly.at( layer );
981 else if( layer ==
B_Cu )
1000 polyList = &polyListSubtracted;
1007 if( oglList !=
nullptr )
1016 if( frontPlatedCopperPolys )
1034 if( backPlatedCopperPolys )
1062 if( aStatusReporter )
1063 aStatusReporter->
Report(
_(
"Loading 3D models..." ) );
1069 if( aStatusReporter )
1074 aStatusReporter->
Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1098 if( aOutZtop < aOutZbot )
1100 float tmpFloat = aOutZbot;
1101 aOutZbot = aOutZtop;
1102 aOutZtop = tmpFloat;
1108 float aOuterRadius,
float aZtop,
float aZbot,
1109 unsigned int aNr_sides_per_circle,
1112 std::vector< SFVEC2F > innerContour;
1113 std::vector< SFVEC2F > outerContour;
1115 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1116 outerContour,
false );
1118 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1120 const SFVEC2F& vi0 = innerContour[i + 0];
1121 const SFVEC2F& vi1 = innerContour[i + 1];
1122 const SFVEC2F& vo0 = outerContour[i + 0];
1123 const SFVEC2F& vo1 = outerContour[i + 1];
1126 SFVEC3F( vi0.x, vi0.y, aZtop ),
1127 SFVEC3F( vo0.x, vo0.y, aZtop ),
1128 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1131 SFVEC3F( vo1.x, vo1.y, aZbot ),
1132 SFVEC3F( vo0.x, vo0.y, aZbot ),
1133 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1142 float aOuterRadius,
float aZtop,
float aZbot,
1143 unsigned int aNr_sides_per_circle,
1155 float radialDiff = aOuterRadius - aInnerRadius;
1159 if( angleRad < 0.01f )
1162 float innerHeight = radialDiff / tanf( angleRad );
1163 float totalHeight = aZtop - aZbot;
1166 if( innerHeight > totalHeight )
1167 innerHeight = totalHeight;
1169 float zInnerTop = aZbot + innerHeight;
1171 std::vector< SFVEC2F > innerContour;
1172 std::vector< SFVEC2F > outerContour;
1174 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1175 outerContour,
false );
1177 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1179 const SFVEC2F& vi0 = innerContour[i + 0];
1180 const SFVEC2F& vi1 = innerContour[i + 1];
1181 const SFVEC2F& vo0 = outerContour[i + 0];
1182 const SFVEC2F& vo1 = outerContour[i + 1];
1186 SFVEC3F( vi0.x, vi0.y, zInnerTop ),
1187 SFVEC3F( vo0.x, vo0.y, aZtop ),
1188 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1192 SFVEC3F( vo1.x, vo1.y, aZbot ),
1193 SFVEC3F( vo0.x, vo0.y, aZbot ),
1194 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1208 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1210 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1212 float a0 =
delta * i;
1213 float a1 =
delta * ( i + 1 );
1214 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1215 aCenter.y + sinf( a0 ) * aRadius, aZ );
1216 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1217 aCenter.y + sinf( a1 ) * aRadius, aZ );
1218 const SFVEC3F c( aCenter.x, aCenter.y, aZ );
1229 float aDepth,
unsigned int aNr_sides_per_circle,
1232 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1233 const SFVEC3F c( aCenter.x, aCenter.y, aTop ? aZ - aDepth : aZ + aDepth );
1235 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1237 float a0 =
delta * i;
1238 float a1 =
delta * ( i + 1 );
1239 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1240 aCenter.y + sinf( a0 ) * aRadius, aZ );
1241 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1242 aCenter.y + sinf( a1 ) * aRadius, aZ );
1257 float aHoleInnerRadius,
1260 float aPlatingThickness3d,
1267 if( !aDstLayer || aPlatingThickness3d <= 0.0f || aHoleInnerRadius <= 0.0f )
1276 if( aSizeIU <= 0 || aDepthIU <= 0 )
1279 const float radius = aSizeIU * 0.5f * aUnitScale;
1280 const float depth = aDepthIU * aUnitScale;
1282 if(
radius <= aHoleInnerRadius || depth <= 0.0f )
1285 float zEnd = aIsFront ? ( aZSurface - depth ) : ( aZSurface + depth );
1290 const float zTop = std::max( aZSurface, zEnd );
1291 const float zBot = std::min( aZSurface, zEnd );
1293 const int diameterBIU = std::max( aSizeIU,
1295 (
int) ( ( aHoleInnerRadius * 2.0f )
1297 const unsigned int nrSegments =
1298 std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( diameterBIU ) );
1303 nrSegments, aDstLayer );
1307 float csTopRadius =
radius;
1308 float csBotRadius = aHoleInnerRadius;
1310 std::vector< SFVEC2F > innerContourTop, outerContourTop;
1311 std::vector< SFVEC2F > innerContourBot, outerContourBot;
1313 generateRing( aHoleCenter, csTopRadius, csTopRadius + aPlatingThickness3d, nrSegments,
1314 innerContourTop, outerContourTop,
false );
1315 generateRing( aHoleCenter, csBotRadius, csBotRadius + aPlatingThickness3d, nrSegments,
1316 innerContourBot, outerContourBot,
false );
1318 for(
unsigned int i = 0; i < ( innerContourTop.size() - 1 ); ++i )
1320 const SFVEC2F& vi0_top = innerContourTop[i + 0];
1321 const SFVEC2F& vi1_top = innerContourTop[i + 1];
1322 const SFVEC2F& vo0_top = outerContourTop[i + 0];
1323 const SFVEC2F& vo1_top = outerContourTop[i + 1];
1325 const SFVEC2F& vi0_bot = innerContourBot[i + 0];
1326 const SFVEC2F& vi1_bot = innerContourBot[i + 1];
1327 const SFVEC2F& vo0_bot = outerContourBot[i + 0];
1328 const SFVEC2F& vo1_bot = outerContourBot[i + 1];
1331 SFVEC3F( vi1_top.x, vi1_top.y, zTop ),
1332 SFVEC3F( vi0_top.x, vi0_top.y, zTop ),
1333 SFVEC3F( vi0_bot.x, vi0_bot.y, zBot ),
1334 SFVEC3F( vi1_bot.x, vi1_bot.y, zBot ) );
1337 SFVEC3F( vo1_top.x, vo1_top.y, zTop ),
1338 SFVEC3F( vo0_top.x, vo0_top.y, zTop ),
1339 SFVEC3F( vo0_bot.x, vo0_bot.y, zBot ),
1340 SFVEC3F( vo1_bot.x, vo1_bot.y, zBot ) );
1355 float averageDiameter =
m_boardAdapter.GetAverageViaHoleDiameter();
1356 unsigned int averageSegCount =
m_boardAdapter.GetCircleSegmentCount( averageDiameter );
1357 unsigned int trianglesEstimate = averageSegCount * 8 *
m_boardAdapter.GetViaCount();
1367 bool isBackdrilled =
via->GetSecondaryDrillSize().has_value();
1368 bool isTertiarydrilled =
via->GetTertiaryDrillSize().has_value();
1379 && !hasFrontPostMachining && !hasBackPostMachining )
1384 const float holediameter =
via->GetDrillValue() * aUnitScale;
1385 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1386 const float hole_inner_radius = holediameter / 2.0f;
1388 const SFVEC2F via_center(
via->GetStart().x * aUnitScale,
1389 -
via->GetStart().y * aUnitScale );
1392 via->LayerPair( &top_layer, &bottom_layer );
1394 float ztop, zbot,
dummy;
1399 wxASSERT( zbot < ztop );
1401 float ztop_plated = ztop;
1402 float zbot_plated = zbot;
1412 zbot_plated = std::max( zbot_plated, secZEnd );
1415 if( isTertiarydrilled )
1423 ztop_plated = std::min( ztop_plated, terZEnd );
1426 auto applyViaPostMachining = [&](
bool isFront )
1428 auto modeOpt = isFront ?
via->GetFrontPostMachining()
1429 :
via->GetBackPostMachining();
1437 int sizeIU = isFront ?
via->GetFrontPostMachiningSize()
1438 :
via->GetBackPostMachiningSize();
1439 int depthIU = isFront ?
via->GetFrontPostMachiningDepth()
1440 :
via->GetBackPostMachiningDepth();
1441 float zSurface = isFront ? ztop : zbot;
1445 sizeIU, depthIU, hole_inner_radius, zSurface,
1446 isFront, aPlatingThickness3d, aUnitScale, &zEnd ) )
1449 ztop_plated = std::min( ztop_plated, zEnd );
1451 zbot_plated = std::max( zbot_plated, zEnd );
1455 if( hasFrontPostMachining )
1456 applyViaPostMachining(
true );
1457 if( hasBackPostMachining )
1458 applyViaPostMachining(
false );
1460 generateCylinder( via_center, hole_inner_radius, hole_inner_radius + aPlatingThickness3d, ztop_plated,
1461 zbot_plated, nrSegments, layerTriangleVIA );
1464 const float padFrontSurface =
1467 const float padBackSurface =
1473 for(
const PAD*
pad : footprint->Pads() )
1478 if( !
pad->HasHole() )
1484 const SFVEC2F padCenter(
pad->GetPosition().x * aUnitScale,
1485 -
pad->GetPosition().y * aUnitScale );
1486 const float holeInnerRadius =
1487 pad->GetDrillSize().x * 0.5f * aUnitScale;
1489 auto emitPadPostMachining = [&](
bool isFront )
1491 auto modeOpt = isFront ?
pad->GetFrontPostMachining()
1492 :
pad->GetBackPostMachining();
1500 int sizeIU = isFront ?
pad->GetFrontPostMachiningSize()
1501 :
pad->GetBackPostMachiningSize();
1502 int depthIU = isFront ?
pad->GetFrontPostMachiningDepth()
1503 :
pad->GetBackPostMachiningDepth();
1504 float zSurface = isFront ? padFrontSurface : padBackSurface;
1507 sizeIU, depthIU, holeInnerRadius, zSurface,
1508 isFront, aPlatingThickness3d, aUnitScale,
1512 emitPadPostMachining(
true );
1513 emitPadPostMachining(
false );
1519 delete layerTriangleVIA;
1547 via->GetDrill() / 2 + aPlatingThickness,
1557 for(
const PAD*
pad : footprint->Pads() )
1561 if( !
pad->HasHole() )
1564 pad->TransformHoleToPolygon( tht_outer_holes_poly, aPlatingThickness,
1566 pad->TransformHoleToPolygon( tht_inner_holes_poly, 0,
1583 if( holes2D.size() > 0 &&
m_boardAdapter.m_Cfg->m_Render.show_plated_barrels )
1585 float layer_z_top, layer_z_bot,
dummy;
1592 for(
const OBJECT_2D* itemOnLayer : holes2D )
1594 const OBJECT_2D* object2d_A = itemOnLayer;
1612 layer_z_bot, layer_z_top,
1613 aUnitScale,
false );
1616 layer_z_top, layer_z_top );
1619 delete layerTriangles;
1639 const float holediameter =
via->GetDrillValue() * aUnitScale;
1640 const float hole_radius = holediameter / 2.0f + 2.0f * aPlatingThickness3d;
1642 -
via->GetStart().y * aUnitScale );
1643 unsigned int seg =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1646 via->LayerPair( &top_layer, &bottom_layer );
1647 float ztop, zbot,
dummy;
1660 const auto frontPostMachining =
1662 const auto backPostMachining =
1670 bool hasFrontBackdrill =
via->GetSecondaryDrillStartLayer() ==
F_Cu;
1671 bool hasBackBackdrill =
via->GetSecondaryDrillStartLayer() ==
B_Cu;
1673 const float depth = hole_radius * 0.3f;
1675 if( frontCovering && !hasFrontPostMachining && !hasFrontBackdrill )
1677 if( filled || !frontPlugged )
1683 if( backCovering && !hasBackPostMachining && !hasBackBackdrill )
1685 if( filled || !backPlugged )
1708 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1710 const float platingThickness3d = platingThickness * unitScale;
1723 if( wxFrame* frame =
dynamic_cast<wxFrame*
>(
m_canvas->GetParent() ) )
1759 wxString libraryName = footprint->GetFPID().GetLibNickname();
1760 wxString footprintBasePath = wxEmptyString;
1767 std::optional<LIBRARY_TABLE_ROW*> fpRow =
1780 for(
const FP_3DMODEL& fp_model : footprint->Models() )
1782 if( fp_model.m_Show && !fp_model.m_Filename.empty() )
1784 if( aStatusReporter )
1788 wxFileName fn( fp_model.m_Filename );
1789 aStatusReporter->
Report( wxString::Format(
_(
"Loading %s..." ),
1790 fn.GetFullName() ) );
1798 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
1799 embeddedFilesStack.push_back( footprint->GetEmbeddedFiles() );
1800 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
1802 const S3DMODEL* modelPtr = cacheMgr->
GetModel( fp_model.m_Filename, footprintBasePath,
1803 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