40 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
float aZtop,
float aZbot )
47 const float f = ( sqrtf( 2.0f ) / 2.0f ) *
radius * texture_factor;
69 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
float aZtop,
float aZbot )
82 float aOuterRadius,
unsigned int aNr_sides_per_circle,
83 std::vector< SFVEC2F >& aInnerContourResult,
84 std::vector< SFVEC2F >& aOuterContourResult,
87 aInnerContourResult.clear();
88 aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
90 aOuterContourResult.clear();
91 aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
93 const int delta = 3600 / aNr_sides_per_circle;
95 for(
int ii = 0; ii < 3600; ii +=
delta )
97 float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
98 * 2.0f * glm::pi<float>() / 3600.0f;
101 aInnerContourResult.emplace_back( aCenter.x + rotatedDir.x * aInnerRadius,
102 aCenter.y + rotatedDir.y * aInnerRadius );
104 aOuterContourResult.emplace_back( aCenter.x + rotatedDir.x * aOuterRadius,
105 aCenter.y + rotatedDir.y * aOuterRadius );
108 aInnerContourResult.push_back( aInnerContourResult[0] );
109 aOuterContourResult.push_back( aOuterContourResult[0] );
111 wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
116 float aZtop,
float aZbot )
122 std::vector< SFVEC2F > innerContour;
123 std::vector< SFVEC2F > outerContour;
126 innerContour, outerContour,
false );
129 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
131 const SFVEC2F& vi0 = innerContour[i + 0];
132 const SFVEC2F& vi1 = innerContour[i + 1];
133 const SFVEC2F& vo0 = outerContour[i + 0];
134 const SFVEC2F& vo1 = outerContour[i + 1];
136 aDstLayer->m_layer_top_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, aZtop ),
137 SFVEC3F( vi0.x, vi0.y, aZtop ),
138 SFVEC3F( vo0.x, vo0.y, aZtop ),
139 SFVEC3F( vo1.x, vo1.y, aZtop ) );
141 aDstLayer->m_layer_bot_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, aZbot ),
142 SFVEC3F( vo1.x, vo1.y, aZbot ),
143 SFVEC3F( vo0.x, vo0.y, aZbot ),
144 SFVEC3F( vi0.x, vi0.y, aZbot ) );
150 float aZtop,
float aZbot )
161 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
float aZtop,
float aZbot )
178 const float radius_of_the_square = sqrtf( aSeg->
GetRadiusSquared() * 2.0f );
179 const float radius_triangle_factor = ( radius_of_the_square -
radius ) /
radius;
182 rightDir.x *
radius * radius_triangle_factor );
185 leftDir.x *
radius * radius_triangle_factor );
188 aDstLayer->m_layer_top_segment_ends->AddTriangle(
189 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
190 rightEnd.y + texture_factor * factorS.y,
192 SFVEC3F( leftStart.x + texture_factor * factorE.x,
193 leftStart.y + texture_factor * factorE.y,
195 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
196 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
199 aDstLayer->m_layer_top_segment_ends->AddTriangle(
200 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
201 leftEnd.y + texture_factor * factorE.y, aZtop ),
202 SFVEC3F( rightStart.x + texture_factor * factorS.x,
203 rightStart.y + texture_factor * factorS.y, aZtop ),
205 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
209 aDstLayer->m_layer_bot_segment_ends->AddTriangle(
210 SFVEC3F( leftStart.x + texture_factor * factorE.x,
211 leftStart.y + texture_factor * factorE.y,
213 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
214 rightEnd.y + texture_factor * factorS.y,
216 SFVEC3F( start.x - texture_factorF * leftDir.x *
radius * sqrtf( 2.0f ),
217 start.y - texture_factorF * leftDir.y *
radius * sqrtf( 2.0f ),
220 aDstLayer->m_layer_bot_segment_ends->AddTriangle(
221 SFVEC3F( rightStart.x + texture_factor * factorS.x,
222 rightStart.y + texture_factor * factorS.y, aZbot ),
223 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
224 leftEnd.y + texture_factor * factorE.y, aZbot ),
226 end.y - texture_factorF * rightDir.y *
radius * sqrtf( 2.0f ),
230 aDstLayer->m_layer_top_triangles->AddQuad(
231 SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
232 SFVEC3F( rightStart.x, rightStart.y, aZtop ),
233 SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
234 SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
236 aDstLayer->m_layer_bot_triangles->AddQuad(
237 SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
238 SFVEC3F( leftStart.x, leftStart.y, aZbot ),
239 SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
240 SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
246 float aZbot,
bool aInvertFaces,
249 if( aListHolesObject2d.size() == 0 )
252 auto layerTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( aListHolesObject2d.size() * 2 );
255 for(
const OBJECT_2D* object2d : aListHolesObject2d )
257 switch( object2d->GetObjectType() )
268 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL::generateHoles: Object type not implemented" ) );
277 layerTriangles->AddToMiddleContours( aPoly, aZbot, aZtop,
m_boardAdapter.BiuTo3dUnits(), aInvertFaces,
281 return std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangles,
m_circleTexture, aZbot, aZtop );
285std::shared_ptr<OPENGL_RENDER_LIST_DEFERRED>
289 if( aContainer ==
nullptr )
294 if( listObject2d.size() == 0 )
303 unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
305 auto layerTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( nrTrianglesEstimation );
311 for(
const OBJECT_2D* object2d : listObject2d )
313 switch( object2d->GetObjectType() )
336 wxFAIL_MSG( wxT(
"RENDER_3D_OPENGL: Object type is not implemented" ) );
343 layerTriangles->AddToMiddleContours( *aPolyList, zBot, zTop,
m_boardAdapter.BiuTo3dUnits(),
false,
348 return std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangles,
m_circleTexture, zBot, zTop );
354 float layer_z_bot = 0.0f;
355 float layer_z_top = 0.0f;
359 auto layerTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( 1 );
364 return std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangles,
m_circleTexture, layer_z_bot, layer_z_top );
372 std::shared_ptr<OPENGL_RENDER_LIST_DEFERRED> dispLists;
380 if( listBoardObject2d.size() > 0 )
384 const float layer_z_top = 1.0f;
385 const float layer_z_bot = 0.0f;
387 auto layerTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( listBoardObject2d.size() );
390 for(
const OBJECT_2D* itemOnLayer : listBoardObject2d )
392 const OBJECT_2D* object2d_A = itemOnLayer;
407 layerTriangles->AddToMiddleContours( aBoardPoly, layer_z_bot, layer_z_top,
411 dispLists = std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangles,
m_circleTexture, layer_z_top,
412 layer_z_top, aTransparent );
425 const int copperLayerCount =
m_boardAdapter.GetBoard()->GetCopperLayerCount();
427 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
428 const float boardBodyThickness =
m_boardAdapter.GetBoardBodyThickness();
431 const float boardZTop = 1.0f;
432 const float boardZBot = 0.0f;
435 auto normalizeZ = [&](
float absZ ) ->
float
439 float boardThick = boardTop - boardBot;
441 if( boardThick <= 0 )
445 return ( absZ - boardBot ) / boardThick;
449 std::shared_ptr<TRIANGLE_DISPLAY_LIST> plugTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( 1024 );
459 const float holeDiameter =
via->GetDrillValue() * unitScale;
460 const float holeInnerRadius = holeDiameter / 2.0f;
461 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
463 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
466 via->LayerPair( &topLayer, &bottomLayer );
468 float viaZTop, viaZBot,
dummy;
473 const float secondaryDrillRadius =
via->GetSecondaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
474 const float tertiaryDrillRadius =
via->GetTertiaryDrillSize().value_or( 0 ) * 0.5f * unitScale;
476 if( secondaryDrillRadius > holeOuterRadius || tertiaryDrillRadius > holeOuterRadius )
482 if( secondaryDrillRadius > holeOuterRadius )
484 plug_end_layer =
via->GetSecondaryDrillEndLayer();
487 if( tertiaryDrillRadius > holeOuterRadius )
489 plug_start_layer =
via->GetTertiaryDrillStartLayer();
493 float plugZTop, plugZBot, temp;
499 plugZTop, plugZBot, nrSegments, plugTriangles );
503 const auto frontMode =
via->GetFrontPostMachining();
505 if( frontMode.has_value()
509 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
510 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
512 if( frontRadius > holeOuterRadius && frontDepth > 0 )
515 float pmBottomZ = normalizeZ( viaZTop - frontDepth );
516 float plugZBot = normalizeZ( viaZBot );
518 if( pmBottomZ > plugZBot )
524 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
529 pmBottomZ, plugZBot, nrSegments, plugTriangles );
536 const auto backMode =
via->GetBackPostMachining();
538 if( backMode.has_value()
542 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
543 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
545 if( backRadius > holeOuterRadius && backDepth > 0 )
548 float plugZTop = normalizeZ( viaZTop );
549 float pmTopZ = normalizeZ( viaZBot + backDepth );
551 if( plugZTop > pmTopZ )
557 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
562 plugZTop, pmTopZ, nrSegments, plugTriangles );
572 for(
const PAD*
pad : footprint->Pads() )
574 if( !
pad->HasHole() )
580 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
581 -
pad->GetPosition().y * unitScale );
582 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
583 const float holeOuterRadius = holeInnerRadius + platingThickness * unitScale;
584 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
pad->GetDrillSize().x );
586 float padZTop, padZBot, padDummy;
591 const auto frontMode =
pad->GetFrontPostMachining();
593 if( frontMode.has_value()
597 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
598 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
600 if( frontRadius > holeOuterRadius && frontDepth > 0 )
602 float pmBottomZ = normalizeZ( padZTop - frontDepth );
603 float plugZBot = normalizeZ( padZBot );
605 if( pmBottomZ > plugZBot )
611 pmBottomZ, plugZBot, nrSegments, plugTriangles, angle );
616 pmBottomZ, plugZBot, nrSegments, plugTriangles );
623 const auto backMode =
pad->GetBackPostMachining();
625 if( backMode.has_value()
629 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
630 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
632 if( backRadius > holeOuterRadius && backDepth > 0 )
634 float plugZTop = normalizeZ( padZTop );
635 float pmTopZ = normalizeZ( padZBot + backDepth );
637 if( plugZTop > pmTopZ )
643 plugZTop, pmTopZ, nrSegments, plugTriangles, angle );
648 plugZTop, pmTopZ, nrSegments, plugTriangles );
657 if( plugTriangles->m_layer_top_triangles->GetVertexSize() > 0
658 || plugTriangles->m_layer_bot_triangles->GetVertexSize() > 0
659 || plugTriangles->m_layer_middle_contours_quads->GetVertexSize() > 0 )
667 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( plugTriangles,
m_circleTexture, boardZTop, boardZTop ) );
681 if( !fp->HasExtrudedBody() )
702 bool isBack = fp->IsFlipped();
704 float standoff3d = body->
m_standoff * biuTo3d;
712 zBot = boardSurfaceZ + standoff3d + zOffset3d;
713 zTop = zBot + bodyThickness;
717 zTop = boardSurfaceZ - standoff3d - zOffset3d;
718 zBot = zTop - bodyThickness;
726 if( triList.empty() )
729 std::shared_ptr<TRIANGLE_DISPLAY_LIST> layerTri = std::make_shared<TRIANGLE_DISPLAY_LIST>( triList.size() );
737 layerTri->AddToMiddleContours( outline, zBot, zTop, biuTo3d,
false );
739 std::shared_ptr<OPENGL_RENDER_LIST_DEFERRED> renderList =
740 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTri,
m_circleTexture, zTop, zBot );
747 if( standoff3d > 0.0f )
754 float oppositeSurfaceZ =
m_boardAdapter.GetFootprintZPos( !isBack );
755 float protrusion = 1.0f *
pcbIUScale.IU_PER_MM * biuTo3d;
756 float pinZBot, pinZTop;
760 pinZBot = oppositeSurfaceZ - protrusion + zOffset3d;
761 pinZTop = boardSurfaceZ + standoff3d + zOffset3d;
765 pinZTop = oppositeSurfaceZ + protrusion - zOffset3d;
766 pinZBot = boardSurfaceZ - standoff3d - zOffset3d;
781 if( pinTriList.empty() )
784 auto pinLayerTri = std::make_shared<TRIANGLE_DISPLAY_LIST>( pinTriList.size() );
793 pinLayerTri->AddToMiddleContours( aPoly, pinZBot, pinZTop, biuTo3d,
false );
795 std::shared_ptr<OPENGL_RENDER_LIST_DEFERRED> pinRenderList =
796 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( pinLayerTri,
m_circleTexture, pinZTop,
820 m_canvas->InvalidateRaytracingHitTesting();
830 m_camera.SetBoardLookAtPos( camera_pos );
850 if( aStop.stop_requested() )
855 m_canvas->InvalidateRaytracingHitTesting();
859 if( aStop.stop_requested() )
870 if( aStop.stop_requested() )
887 if( aStop.stop_requested() )
895 if(
m_boardAdapter.GetFrontCounterborePolys().OutlineCount() > 0 )
901 if(
m_boardAdapter.GetFrontCountersinkPolys().OutlineCount() > 0 )
913 if( aStop.stop_requested() )
921 if( aStop.stop_requested() )
953 wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
957 if( outerMapHoles.size() > 0 )
959 float layer_z_bot = 0.0f;
960 float layer_z_top = 0.0f;
962 for(
const auto& [ layer, poly ] : outerMapHoles )
967 generateHoles( map_holes.at( layer )->GetList(), *poly, layer_z_top, layer_z_bot,
false ) );
970 for(
const auto& [ layer, poly ] : innerMapHoles )
975 generateHoles( map_holes.at( layer )->GetList(), *poly, layer_z_top, layer_z_bot,
false ) );
982 if( aStop.stop_requested() )
991 std::bitset<LAYER_3D_END> visibilityFlags =
m_boardAdapter.GetVisibleLayers();
995 for(
const auto& [ layer, container2d ] :
m_boardAdapter.GetLayerMap() )
1013 if( map_poly.contains( layer ) )
1015 polyListSubtracted = *map_poly.at( layer );
1033 else if( layer ==
B_Cu )
1052 polyList = &polyListSubtracted;
1056 if( aStop.stop_requested() )
1059 std::shared_ptr<OPENGL_RENDER_LIST_DEFERRED> oglList =
1062 if( oglList !=
nullptr )
1065 if( aStop.stop_requested() )
1076 if( frontPlatedCopperPolys )
1094 if( backPlatedCopperPolys )
1122 if( aStop.stop_requested() )
1135 if( aStop.stop_requested() )
1144 if( !aStop.stop_requested() &&
m_canvas )
1150 if( aStop.stop_requested() )
1158 m_activityReporter->Report( wxString::Format(
_(
"Load completed in %.3f s" ), calculation_time ) );
1165 wxLogTrace(
m_logTrace, wxT(
"RENDER_3D_OPENGL::startBgWorker" ) );
1171 [
this]( std::stop_token aStopToken )
1174 BS::this_thread::set_os_thread_priority( BS::os_thread_priority::below_normal );
1192 [
this]( std::stop_token aStop )
1194 BS::this_thread::set_os_thread_priority( BS::os_thread_priority::below_normal );
1209 if( aStop.stop_requested() || !
m_canvas )
1212 m_canvas->ReloadRaytracingForHitTesting( aStop );
1226 wxLogTrace(
m_logTrace, wxT(
"RENDER_3D_OPENGL::StopBgWorker" ) );
1243 wxLogTrace(
m_logTrace, wxT(
"RENDER_3D_OPENGL::JoinBgWorker" ) );
1253 aDst->m_layer_bot_triangles->AddTriangle(
SFVEC3F( v0.x, v0.y, bot ),
1257 aDst->m_layer_top_triangles->AddTriangle(
SFVEC3F(
v2.x,
v2.y,
top ),
1268 if( aOutZtop < aOutZbot )
1270 float tmpFloat = aOutZbot;
1271 aOutZbot = aOutZtop;
1272 aOutZtop = tmpFloat;
1278 float aZbot,
unsigned int aNr_sides_per_circle,
1279 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer )
1281 std::vector< SFVEC2F > innerContour;
1282 std::vector< SFVEC2F > outerContour;
1284 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1285 outerContour,
false );
1287 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1289 const SFVEC2F& vi0 = innerContour[i + 0];
1290 const SFVEC2F& vi1 = innerContour[i + 1];
1291 const SFVEC2F& vo0 = outerContour[i + 0];
1292 const SFVEC2F& vo1 = outerContour[i + 1];
1294 aDstLayer->m_layer_top_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, aZtop ),
1295 SFVEC3F( vi0.x, vi0.y, aZtop ),
1296 SFVEC3F( vo0.x, vo0.y, aZtop ),
1297 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1299 aDstLayer->m_layer_bot_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, aZbot ),
1300 SFVEC3F( vo1.x, vo1.y, aZbot ),
1301 SFVEC3F( vo0.x, vo0.y, aZbot ),
1302 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1305 aDstLayer->AddToMiddleContours( outerContour, aZbot, aZtop,
true );
1306 aDstLayer->AddToMiddleContours( innerContour, aZbot, aZtop,
false );
1311 float aZbot,
unsigned int aNr_sides_per_circle,
1312 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
EDA_ANGLE aAngle )
1323 float radialDiff = aOuterRadius - aInnerRadius;
1327 if( angleRad < 0.01f )
1330 float innerHeight = radialDiff / tanf( angleRad );
1331 float totalHeight = aZtop - aZbot;
1334 if( innerHeight > totalHeight )
1335 innerHeight = totalHeight;
1337 float zInnerTop = aZbot + innerHeight;
1339 std::vector< SFVEC2F > innerContour;
1340 std::vector< SFVEC2F > outerContour;
1342 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
1343 outerContour,
false );
1345 for(
unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
1347 const SFVEC2F& vi0 = innerContour[i + 0];
1348 const SFVEC2F& vi1 = innerContour[i + 1];
1349 const SFVEC2F& vo0 = outerContour[i + 0];
1350 const SFVEC2F& vo1 = outerContour[i + 1];
1353 aDstLayer->m_layer_top_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, zInnerTop ),
1354 SFVEC3F( vi0.x, vi0.y, zInnerTop ),
1355 SFVEC3F( vo0.x, vo0.y, aZtop ),
1356 SFVEC3F( vo1.x, vo1.y, aZtop ) );
1359 aDstLayer->m_layer_bot_triangles->AddQuad(
SFVEC3F( vi1.x, vi1.y, aZbot ),
1360 SFVEC3F( vo1.x, vo1.y, aZbot ),
1361 SFVEC3F( vo0.x, vo0.y, aZbot ),
1362 SFVEC3F( vi0.x, vi0.y, aZbot ) );
1366 aDstLayer->AddToMiddleContours( outerContour, aZbot, aZtop,
true );
1368 aDstLayer->AddToMiddleContours( innerContour, aZbot, zInnerTop,
false );
1373 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
bool aTop )
1375 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1377 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1379 float a0 =
delta * i;
1380 float a1 =
delta * ( i + 1 );
1381 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1382 aCenter.y + sinf( a0 ) * aRadius, aZ );
1383 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1384 aCenter.y + sinf( a1 ) * aRadius, aZ );
1385 const SFVEC3F c( aCenter.x, aCenter.y, aZ );
1388 aDstLayer->m_layer_top_triangles->AddTriangle( p1, p0, c );
1390 aDstLayer->m_layer_bot_triangles->AddTriangle( p0, p1, c );
1396 unsigned int aNr_sides_per_circle,
1397 std::shared_ptr<TRIANGLE_DISPLAY_LIST> aDstLayer,
bool aTop )
1399 const float delta = 2.0f * glm::pi<float>() / (float) aNr_sides_per_circle;
1400 const SFVEC3F c( aCenter.x, aCenter.y, aTop ? aZ - aDepth : aZ + aDepth );
1402 for(
unsigned int i = 0; i < aNr_sides_per_circle; ++i )
1404 float a0 =
delta * i;
1405 float a1 =
delta * ( i + 1 );
1406 const SFVEC3F p0( aCenter.x + cosf( a0 ) * aRadius,
1407 aCenter.y + sinf( a0 ) * aRadius, aZ );
1408 const SFVEC3F p1( aCenter.x + cosf( a1 ) * aRadius,
1409 aCenter.y + sinf( a1 ) * aRadius, aZ );
1412 aDstLayer->m_layer_top_triangles->AddTriangle( p0, p1, c );
1414 aDstLayer->m_layer_bot_triangles->AddTriangle( p1, p0, c );
1424 float aHoleInnerRadius,
1427 float aPlatingThickness3d,
1434 if( !aDstLayer || aPlatingThickness3d <= 0.0f || aHoleInnerRadius <= 0.0f )
1443 if( aSizeIU <= 0 || aDepthIU <= 0 )
1446 const float radius = aSizeIU * 0.5f * aUnitScale;
1447 const float depth = aDepthIU * aUnitScale;
1449 if(
radius <= aHoleInnerRadius || depth <= 0.0f )
1452 float zEnd = aIsFront ? ( aZSurface - depth ) : ( aZSurface + depth );
1457 const float zTop = std::max( aZSurface, zEnd );
1458 const float zBot = std::min( aZSurface, zEnd );
1460 const int diameterBIU = std::max( aSizeIU,
1462 (
int) ( ( aHoleInnerRadius * 2.0f )
1464 const unsigned int nrSegments =
1465 std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( diameterBIU ) );
1470 nrSegments, aDstLayer );
1474 float csTopRadius =
radius;
1475 float csBotRadius = aHoleInnerRadius;
1477 std::vector< SFVEC2F > innerContourTop, outerContourTop;
1478 std::vector< SFVEC2F > innerContourBot, outerContourBot;
1480 generateRing( aHoleCenter, csTopRadius, csTopRadius + aPlatingThickness3d, nrSegments,
1481 innerContourTop, outerContourTop,
false );
1482 generateRing( aHoleCenter, csBotRadius, csBotRadius + aPlatingThickness3d, nrSegments,
1483 innerContourBot, outerContourBot,
false );
1485 for(
unsigned int i = 0; i < ( innerContourTop.size() - 1 ); ++i )
1487 const SFVEC2F& vi0_top = innerContourTop[i + 0];
1488 const SFVEC2F& vi1_top = innerContourTop[i + 1];
1489 const SFVEC2F& vo0_top = outerContourTop[i + 0];
1490 const SFVEC2F& vo1_top = outerContourTop[i + 1];
1492 const SFVEC2F& vi0_bot = innerContourBot[i + 0];
1493 const SFVEC2F& vi1_bot = innerContourBot[i + 1];
1494 const SFVEC2F& vo0_bot = outerContourBot[i + 0];
1495 const SFVEC2F& vo1_bot = outerContourBot[i + 1];
1497 aDstLayer->m_layer_middle_contours_quads->AddQuad(
1498 SFVEC3F( vi1_top.x, vi1_top.y, zTop ),
1499 SFVEC3F( vi0_top.x, vi0_top.y, zTop ),
1500 SFVEC3F( vi0_bot.x, vi0_bot.y, zBot ),
1501 SFVEC3F( vi1_bot.x, vi1_bot.y, zBot ) );
1503 aDstLayer->m_layer_middle_contours_quads->AddQuad(
1504 SFVEC3F( vo1_top.x, vo1_top.y, zTop ),
1505 SFVEC3F( vo0_top.x, vo0_top.y, zTop ),
1506 SFVEC3F( vo0_bot.x, vo0_bot.y, zBot ),
1507 SFVEC3F( vo1_bot.x, vo1_bot.y, zBot ) );
1522 float averageDiameter =
m_boardAdapter.GetAverageViaHoleDiameter();
1523 unsigned int averageSegCount =
m_boardAdapter.GetCircleSegmentCount( averageDiameter );
1524 unsigned int trianglesEstimate = averageSegCount * 8 *
m_boardAdapter.GetViaCount();
1526 std::shared_ptr<TRIANGLE_DISPLAY_LIST> layerTriangleVIA = std::make_shared<TRIANGLE_DISPLAY_LIST>( trianglesEstimate );
1534 bool isBackdrilled =
via->GetSecondaryDrillSize().has_value();
1535 bool isTertiarydrilled =
via->GetTertiaryDrillSize().has_value();
1546 && !hasFrontPostMachining && !hasBackPostMachining )
1551 const float holediameter =
via->GetDrillValue() * aUnitScale;
1552 const int nrSegments =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1553 const float hole_inner_radius = holediameter / 2.0f;
1555 const SFVEC2F via_center(
via->GetStart().x * aUnitScale,
1556 -
via->GetStart().y * aUnitScale );
1559 via->LayerPair( &top_layer, &bottom_layer );
1561 float ztop, zbot,
dummy;
1566 wxASSERT( zbot < ztop );
1568 float ztop_plated = ztop;
1569 float zbot_plated = zbot;
1579 zbot_plated = std::max( zbot_plated, secZEnd );
1582 if( isTertiarydrilled )
1590 ztop_plated = std::min( ztop_plated, terZEnd );
1593 auto applyViaPostMachining = [&](
bool isFront )
1595 auto modeOpt = isFront ?
via->GetFrontPostMachining()
1596 :
via->GetBackPostMachining();
1604 int sizeIU = isFront ?
via->GetFrontPostMachiningSize()
1605 :
via->GetBackPostMachiningSize();
1606 int depthIU = isFront ?
via->GetFrontPostMachiningDepth()
1607 :
via->GetBackPostMachiningDepth();
1608 float zSurface = isFront ? ztop : zbot;
1612 sizeIU, depthIU, hole_inner_radius, zSurface,
1613 isFront, aPlatingThickness3d, aUnitScale, &zEnd ) )
1616 ztop_plated = std::min( ztop_plated, zEnd );
1618 zbot_plated = std::max( zbot_plated, zEnd );
1622 if( hasFrontPostMachining )
1623 applyViaPostMachining(
true );
1624 if( hasBackPostMachining )
1625 applyViaPostMachining(
false );
1627 generateCylinder( via_center, hole_inner_radius, hole_inner_radius + aPlatingThickness3d, ztop_plated,
1628 zbot_plated, nrSegments, layerTriangleVIA );
1631 const float padFrontSurface =
1634 const float padBackSurface =
1640 for(
const PAD*
pad : footprint->Pads() )
1645 if( !
pad->HasHole() )
1651 const SFVEC2F padCenter(
pad->GetPosition().x * aUnitScale,
1652 -
pad->GetPosition().y * aUnitScale );
1653 const float holeInnerRadius =
1654 pad->GetDrillSize().x * 0.5f * aUnitScale;
1656 auto emitPadPostMachining = [&](
bool isFront )
1658 auto modeOpt = isFront ?
pad->GetFrontPostMachining()
1659 :
pad->GetBackPostMachining();
1667 int sizeIU = isFront ?
pad->GetFrontPostMachiningSize()
1668 :
pad->GetBackPostMachiningSize();
1669 int depthIU = isFront ?
pad->GetFrontPostMachiningDepth()
1670 :
pad->GetBackPostMachiningDepth();
1671 float zSurface = isFront ? padFrontSurface : padBackSurface;
1674 sizeIU, depthIU, holeInnerRadius, zSurface,
1675 isFront, aPlatingThickness3d, aUnitScale,
1679 emitPadPostMachining(
true );
1680 emitPadPostMachining(
false );
1685 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangleVIA, 0, 0.0f, 0.0f ) );
1729 for(
const PAD*
pad : footprint->Pads() )
1733 if( !
pad->HasHole() )
1736 pad->TransformHoleToPolygon( tht_outer_holes_poly, aPlatingThickness,
1738 pad->TransformHoleToPolygon( tht_inner_holes_poly, 0,
1747 tht_outer_holes_poly.
BooleanAdd( capped_outer_vias_poly );
1748 tht_inner_holes_poly.
BooleanAdd( capped_inner_vias_poly );
1757 if( holes2D.size() > 0 &&
m_boardAdapter.m_Cfg->m_Render.show_plated_barrels )
1759 float layer_z_top, layer_z_bot,
dummy;
1764 std::shared_ptr<TRIANGLE_DISPLAY_LIST> layerTriangles = std::make_shared<TRIANGLE_DISPLAY_LIST>( holes2D.size() );
1766 for(
const OBJECT_2D* itemOnLayer : holes2D )
1768 const OBJECT_2D* object2d_A = itemOnLayer;
1785 layerTriangles->AddToMiddleContours( tht_outer_holes_poly,
1786 layer_z_bot, layer_z_top,
1787 aUnitScale,
false );
1790 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( layerTriangles,
m_circleTexture, layer_z_top,
1802 std::shared_ptr<TRIANGLE_DISPLAY_LIST> frontCover = std::make_shared<TRIANGLE_DISPLAY_LIST>(
m_boardAdapter.GetViaCount() );
1803 std::shared_ptr<TRIANGLE_DISPLAY_LIST> backCover = std::make_shared<TRIANGLE_DISPLAY_LIST>(
m_boardAdapter.GetViaCount() );
1812 const float holediameter =
via->GetDrillValue() * aUnitScale;
1813 const float hole_radius = holediameter / 2.0f + 2.0f * aPlatingThickness3d;
1815 -
via->GetStart().y * aUnitScale );
1816 unsigned int seg =
m_boardAdapter.GetCircleSegmentCount(
via->GetDrillValue() );
1819 via->LayerPair( &top_layer, &bottom_layer );
1820 float ztop, zbot,
dummy;
1833 const auto frontPostMachining =
1835 const auto backPostMachining =
1843 bool hasFrontBackdrill =
via->GetSecondaryDrillStartLayer() ==
F_Cu;
1844 bool hasBackBackdrill =
via->GetSecondaryDrillStartLayer() ==
B_Cu;
1846 const float depth = hole_radius * 0.3f;
1848 if( frontCovering && !hasFrontPostMachining && !hasFrontBackdrill )
1850 if( filled || !frontPlugged )
1856 if( backCovering && !hasBackPostMachining && !hasBackBackdrill )
1858 if( filled || !backPlugged )
1865 if( frontCover->m_layer_top_triangles->GetVertexSize() > 0 )
1867 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( frontCover, 0, 0.0f, 0.0f ) );
1869 if( backCover->m_layer_bot_triangles->GetVertexSize() > 0 )
1871 std::make_shared<OPENGL_RENDER_LIST_DEFERRED>( backCover, 0, 0.0f, 0.0f ) );
1880 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1882 const float platingThickness3d = platingThickness * unitScale;
1922 wxString libraryName = footprint->GetFPID().GetLibNickname();
1923 wxString footprintBasePath = wxEmptyString;
1930 std::optional<LIBRARY_TABLE_ROW*> fpRow =
1943 for(
const FP_3DMODEL& fp_model : footprint->Models() )
1945 if( fp_model.m_Show && !fp_model.m_Filename.empty() )
1951 wxFileName fn( fp_model.m_Filename );
1960 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
1961 embeddedFilesStack.push_back( footprint->GetEmbeddedFiles() );
1962 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
1964 const S3DMODEL* modelPtr = cacheMgr->
GetModel( fp_model.m_Filename, footprintBasePath,
1965 std::move( embeddedFilesStack ) );
1971 auto model = std::make_shared<MODEL_3D_DEFERRED>( *modelPtr, materialMode );
1978 if( aStop.stop_requested() )
MATERIAL_MODE
Render 3d model shape materials mode.
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.
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
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)
std::shared_ptr< REPORTER > m_warningReporter
std::shared_ptr< REPORTER > m_activityReporter
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
void runHitTestRebuild(std::stop_token aStop)
void renderExtrudedBodies()
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > generateHoles(const LIST_OBJECT2D &aListHolesObject2d, const SHAPE_POLY_SET &aPoly, float aZtop, float aZbot, bool aInvertFaces, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
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)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_offboardPadsBack
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_microviaHoles
SHAPE_POLY_SET m_antiBoardPolys
The negative polygon representation of the board outline.
std::map< const FOOTPRINT *, std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > > m_extrudedBodyLists
void RebuildHitTestAsync()
Rebuild the raytracing hit-test scene in the background after a visibility change.
void generateViasAndPads()
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_viaFrontCover
void Load3dModelsIfNeeded()
Load footprint models if they are not already loaded, i.e.
void StopBgWorker() override
Request stop and join any in-progress background loading.
MAP_OGL_DISP_LISTS m_layers
MAP_OGL_DISP_LISTS m_innerLayerHoles
void appendRenderTriangleList(std::shared_ptr< TRIANGLE_DISPLAY_LIST > aTriangles)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_postMachinePlugs
Board material plugs for backdrill/counterbore/countersink.
std::atomic< bool > m_hitTestDirty
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_offboardPadsFront
MAP_OGL_DISP_LISTS m_outerLayerHoles
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > generateEmptyLayerList(PCB_LAYER_ID aLayer)
void generateDisk(const SFVEC2F &aCenter, float aRadius, float aZ, unsigned int aNr_sides_per_circle, std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDstLayer, bool aTop)
void generateDimple(const SFVEC2F &aCenter, float aRadius, float aZ, float aDepth, unsigned int aNr_sides_per_circle, std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDstLayer, bool aTop)
void assignRenderMap(TMap &aMap, const typename TMap::key_type &aKey, typename TMap::mapped_type aVal)
bool appendPostMachiningGeometry(std::shared_ptr< 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)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_platedPadsFront
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_platedPadsBack
void generateViaCovers(float aPlatingThickness3d, float aUnitScale)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_board
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_boardWithHoles
void load3dModels(std::stop_token aStop=std::stop_token())
Load footprint models from the cache and load it to deferred openGL lists (MODEL_3D_DEFERRED) objects...
void createPlaceholderModel()
void generateInvCone(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDstLayer, EDA_ANGLE aAngle)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_antiBoard
void generatePlatedHoleShells(int aPlatingThickness, float aUnitScale)
std::map< wxString, std::shared_ptr< MODEL_3D_DEFERRED > > m_3dModelMap
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_outerThroughHoles
std::atomic< bool > m_bgWorkerBusy
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > generateLayerList(const BVH_CONTAINER_2D *aContainer, const SHAPE_POLY_SET *aPolyList, PCB_LAYER_ID aLayer, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
std::map< const FOOTPRINT *, std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > > m_extrudedPadLists
void getLayerZPos(PCB_LAYER_ID aLayerID, float &aOutZtop, float &aOutZbot) const
void bgWorker(std::stop_token aStop)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_padHoles
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > createBoard(const SHAPE_POLY_SET &aBoardPoly, const BVH_CONTAINER_2D *aThroughHoles=nullptr, bool aTransparent=false)
void JoinBgWorker() override
Block until any in-progress background loading has finished.
void generateViaBarrels(float aPlatingThickness3d, float aUnitScale)
void addTopAndBottomTriangles(std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot)
std::jthread m_bgWorkerThread
std::map< const FOOTPRINT *, std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > > m_extrudedPegLists
void assignRenderPtr(std::shared_ptr< T > &aDst, std::shared_ptr< T > aVal)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_outerViaThroughHoles
void addObjectTriangles(const RING_2D *aRing, std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDstLayer, float aZtop, float aZbot)
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_outerThroughHoleRings
void backfillPostMachine()
Create ring-shaped plugs for holes that have backdrill or post-machining.
std::shared_ptr< OPENGL_RENDER_LIST_DEFERRED > m_viaBackCover
void generateCylinder(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, std::shared_ptr< TRIANGLE_DISPLAY_LIST > aDstLayer)
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.
const SFVEC2F & GetP2() const
const SFVEC2F & GetP3() const
const SFVEC2F & GetP1() 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.
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this 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