Clean up pad handling in 3D viewer.
Most importantly, create F_Cu/B_Cu layers if they're otherwise empty
but we have plated pads to render on them.
Fixes https://gitlab.com/kicad/code/kicad/issues/10207
(cherry picked from commit 0dc857b5ab
)
This commit is contained in:
parent
330b1fd733
commit
0fc4ccf8d9
|
@ -493,15 +493,10 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
|
|||
{
|
||||
for( PAD* pad : aFootprint->Pads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( aLayerId ) )
|
||||
if( !pad->FlashLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// Skip pad annulus when not connected on this layer (if removing is enabled)
|
||||
if( !pad->FlashLayer( aLayerId ) && IsCopperLayer( aLayerId ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the
|
||||
// shape size and pos is the same as their hole:
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||
{
|
||||
if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
|
||||
|
@ -526,19 +521,28 @@ void BOARD_ADAPTER::addPadsWithClearance( const FOOTPRINT* aFootprint,
|
|||
}
|
||||
}
|
||||
|
||||
const bool isPlated = ( ( aLayerId == F_Cu ) && pad->FlashLayer( F_Mask ) ) ||
|
||||
( ( aLayerId == B_Cu ) && pad->FlashLayer( B_Mask ) );
|
||||
|
||||
if( aSkipPlatedPads && isPlated )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !isPlated )
|
||||
continue;
|
||||
|
||||
wxSize margin( aInflateValue, aInflateValue );
|
||||
|
||||
switch( aLayerId )
|
||||
{
|
||||
case F_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x += pad->GetSolderMaskMargin();
|
||||
|
|
|
@ -549,7 +549,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPadsWithClearance( footprint, m_platedPadsFront, F_Cu, 0, true, false, true );
|
||||
|
||||
addPadsWithClearance( footprint, m_platedPadsBack, B_Cu, 0, true, false, true );
|
||||
}
|
||||
|
||||
|
@ -569,8 +568,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
// Add pads to polygon list
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad
|
||||
// has same shape as its hole
|
||||
// Note: NPTH pads are not drawn on copper layers when the pad has same shape as
|
||||
// its hole
|
||||
footprint->TransformPadsWithClearanceToPolygon( *layerPoly, curr_layer_id,
|
||||
0, ARC_HIGH_DEF, ERROR_INSIDE,
|
||||
true, renderPlatedPadsAsPlated,
|
||||
|
|
|
@ -374,6 +374,22 @@ OPENGL_RENDER_LIST* RENDER_3D_OPENGL::generateLayerList( const BVH_CONTAINER_2D*
|
|||
}
|
||||
|
||||
|
||||
OPENGL_RENDER_LIST* RENDER_3D_OPENGL::generateEmptyLayerList( PCB_LAYER_ID aLayerId )
|
||||
{
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
getLayerZPos( aLayerId, layer_z_top, layer_z_bot );
|
||||
|
||||
TRIANGLE_DISPLAY_LIST* layerTriangles = new TRIANGLE_DISPLAY_LIST( 1 );
|
||||
|
||||
// store in a list so it will be latter deleted
|
||||
m_triangles.push_back( layerTriangles );
|
||||
|
||||
return new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture, layer_z_bot, layer_z_top );
|
||||
}
|
||||
|
||||
|
||||
OPENGL_RENDER_LIST* RENDER_3D_OPENGL::createBoard( const SHAPE_POLY_SET& aBoardPoly,
|
||||
const BVH_CONTAINER_2D* aThroughHoles )
|
||||
{
|
||||
|
@ -388,9 +404,8 @@ OPENGL_RENDER_LIST* RENDER_3D_OPENGL::createBoard( const SHAPE_POLY_SET& aBoardP
|
|||
|
||||
if( listBoardObject2d.size() > 0 )
|
||||
{
|
||||
// We will set a unitary Z so it will in future used with transformations
|
||||
// since the board poly will be used not only to draw itself but also the
|
||||
// solder mask layers.
|
||||
// We will set a unitary Z so it will in future used with transformations since the
|
||||
// board poly will be used not only to draw itself but also the solder mask layers.
|
||||
const float layer_z_top = 1.0f;
|
||||
const float layer_z_bot = 0.0f;
|
||||
|
||||
|
@ -563,7 +578,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
const BVH_CONTAINER_2D* container2d = ii.second;
|
||||
|
||||
SHAPE_POLY_SET polyListSubtracted;
|
||||
SHAPE_POLY_SET* aPolyList = nullptr;
|
||||
SHAPE_POLY_SET* polyList = nullptr;
|
||||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
|
||||
|
@ -580,9 +595,8 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
{
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetThroughHoleOdPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract(
|
||||
m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( m_boardAdapter.GetFlag( FL_SUBTRACT_MASK_FROM_SILK ) )
|
||||
|
@ -600,10 +614,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
}
|
||||
}
|
||||
|
||||
aPolyList = &polyListSubtracted;
|
||||
polyList = &polyListSubtracted;
|
||||
}
|
||||
|
||||
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, aPolyList, layer_id,
|
||||
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer_id,
|
||||
&m_boardAdapter.GetThroughHoleIds() );
|
||||
|
||||
if( oglList != nullptr )
|
||||
|
@ -626,6 +640,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
|
||||
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(),
|
||||
&polySubtracted, F_Cu );
|
||||
|
||||
// An entry for F_Cu must exist in m_layers or we'll never look at m_platedPadsFront
|
||||
if( m_layers.count( F_Cu ) == 0 )
|
||||
m_layers[F_Cu] = generateEmptyLayerList( F_Cu );
|
||||
}
|
||||
|
||||
if( m_boardAdapter.GetBackPlatedPadPolys() )
|
||||
|
@ -640,6 +658,10 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
|
||||
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(),
|
||||
&polySubtracted, B_Cu );
|
||||
|
||||
// An entry for B_Cu must exist in m_layers or we'll never look at m_platedPadsBack
|
||||
if( m_layers.count( B_Cu ) == 0 )
|
||||
m_layers[B_Cu] = generateEmptyLayerList( B_Cu );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -504,7 +504,7 @@ void RENDER_3D_OPENGL::setCopperMaterial()
|
|||
void RENDER_3D_OPENGL::setPlatedCopperAndDepthOffset( PCB_LAYER_ID aLayer_id )
|
||||
{
|
||||
glEnable( GL_POLYGON_OFFSET_FILL );
|
||||
glPolygonOffset(-0.1f, -2.0f );
|
||||
glPolygonOffset( -0.1f, -2.0f );
|
||||
setLayerMaterial( aLayer_id );
|
||||
}
|
||||
|
||||
|
@ -704,18 +704,16 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
|||
{
|
||||
pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments );
|
||||
|
||||
// Draw copper plated pads
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
|
||||
// Draw plated pads
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulled( m_camera.GetPos().z,
|
||||
drawMiddleSegments );
|
||||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulled( m_camera.GetPos().z,
|
||||
drawMiddleSegments );
|
||||
}
|
||||
|
@ -751,16 +749,10 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
|||
viasHolesLayer,
|
||||
m_antiBoard );
|
||||
|
||||
// Draw copper plated pads
|
||||
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
}
|
||||
|
||||
// Draw plated pads
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulledSubtractLayer(
|
||||
drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
|
@ -769,6 +761,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
|||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulledSubtractLayer(
|
||||
drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
|
@ -785,21 +778,16 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
|||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
|
||||
// Draw copper plated pads
|
||||
if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) &&
|
||||
( m_platedPadsFront || m_platedPadsBack ) )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
}
|
||||
|
||||
if( layer_id == F_Cu && m_platedPadsFront )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsFront->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
}
|
||||
else if( layer_id == B_Cu && m_platedPadsBack )
|
||||
{
|
||||
setPlatedCopperAndDepthOffset( layer_id );
|
||||
m_platedPadsBack->DrawAllCameraCulledSubtractLayer( drawMiddleSegments,
|
||||
m_outerThroughHoles,
|
||||
m_antiBoard );
|
||||
|
|
|
@ -84,6 +84,8 @@ private:
|
|||
PCB_LAYER_ID aLayerId,
|
||||
const BVH_CONTAINER_2D* aThroughHoles = nullptr );
|
||||
|
||||
OPENGL_RENDER_LIST* generateEmptyLayerList( PCB_LAYER_ID aLayerId );
|
||||
|
||||
void addTopAndBottomTriangles( TRIANGLE_DISPLAY_LIST* aDst, const SFVEC2F& v0,
|
||||
const SFVEC2F& v1, const SFVEC2F& v2, float top, float bot );
|
||||
|
||||
|
|
|
@ -2214,51 +2214,31 @@ void FOOTPRINT::TransformPadsWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuff
|
|||
{
|
||||
for( const PAD* pad : m_pads )
|
||||
{
|
||||
if( aLayer != UNDEFINED_LAYER && !pad->IsOnLayer(aLayer) )
|
||||
continue;
|
||||
|
||||
if( !pad->FlashLayer( aLayer ) && IsCopperLayer( aLayer ) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
||||
// as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && pad->GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE::CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case PAD_SHAPE::OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool isPlated = ( ( aLayer == F_Cu ) && pad->FlashLayer( F_Mask ) ) ||
|
||||
( ( aLayer == B_Cu ) && pad->FlashLayer( B_Mask ) );
|
||||
|
||||
if( aSkipPlatedPads && isPlated )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !isPlated )
|
||||
if( !pad->FlashLayer( aLayer ) )
|
||||
continue;
|
||||
|
||||
wxSize clearance( aClearance, aClearance );
|
||||
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( F_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
if( aSkipPlatedPads && pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
if( aSkipNonPlatedPads && !pad->FlashLayer( B_Mask ) )
|
||||
continue;
|
||||
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
clearance.x += pad->GetSolderMaskMargin();
|
||||
|
|
|
@ -216,31 +216,11 @@ bool PAD::FlashLayer( int aLayer ) const
|
|||
std::vector<KICAD_T> types
|
||||
{ PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T, PCB_FP_ZONE_T };
|
||||
|
||||
const BOARD* board = GetBoard();
|
||||
if( aLayer != UNDEFINED_LAYER && !IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) ) )
|
||||
return false;
|
||||
|
||||
switch( GetAttribute() )
|
||||
if( GetAttribute() == PAD_ATTRIB::NPTH && IsCopperLayer( aLayer ) )
|
||||
{
|
||||
case PAD_ATTRIB::PTH:
|
||||
if( aLayer == UNDEFINED_LAYER )
|
||||
return true;
|
||||
|
||||
/// Heat sink pads always get copper
|
||||
if( GetProperty() == PAD_PROP::HEATSINK )
|
||||
return IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
|
||||
|
||||
if( !m_removeUnconnectedLayer )
|
||||
return IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
|
||||
|
||||
// Plated through hole pads need copper on the top/bottom layers for proper soldering
|
||||
// Unless the user has removed them in the pad dialog
|
||||
if( m_keepTopBottomLayer && ( aLayer == F_Cu || aLayer == B_Cu ) )
|
||||
return IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
|
||||
|
||||
return board && board->GetConnectivity()->IsConnectedOnLayer( this,
|
||||
static_cast<int>( aLayer ),
|
||||
types, true );
|
||||
|
||||
case PAD_ATTRIB::NPTH:
|
||||
if( GetShape() == PAD_SHAPE::CIRCLE && GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
{
|
||||
if( GetOffset() == wxPoint( 0, 0 ) && GetDrillSize().x >= GetSize().x )
|
||||
|
@ -254,17 +234,32 @@ bool PAD::FlashLayer( int aLayer ) const
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KI_FALLTHROUGH;
|
||||
if( LSET::FrontBoardTechMask().test( aLayer ) )
|
||||
aLayer = F_Cu;
|
||||
else if( LSET::BackBoardTechMask().test( aLayer ) )
|
||||
aLayer = B_Cu;
|
||||
|
||||
case PAD_ATTRIB::SMD:
|
||||
case PAD_ATTRIB::CONN:
|
||||
default:
|
||||
if( aLayer == UNDEFINED_LAYER )
|
||||
if( GetAttribute() == PAD_ATTRIB::PTH && IsCopperLayer( aLayer ) )
|
||||
{
|
||||
/// Heat sink pads always get copper
|
||||
if( GetProperty() == PAD_PROP::HEATSINK )
|
||||
return true;
|
||||
|
||||
return IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
|
||||
if( !m_removeUnconnectedLayer )
|
||||
return true;
|
||||
|
||||
// Plated through hole pads need copper on the top/bottom layers for proper soldering
|
||||
// Unless the user has removed them in the pad dialog
|
||||
if( m_keepTopBottomLayer && ( aLayer == F_Cu || aLayer == B_Cu ) )
|
||||
return true;
|
||||
|
||||
if( const BOARD* board = GetBoard() )
|
||||
return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types, true );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue