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
This commit is contained in:
parent
dbfdd3fb56
commit
0dc857b5ab
|
@ -421,15 +421,10 @@ void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aCo
|
|||
{
|
||||
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 ) )
|
||||
|
@ -454,19 +449,28 @@ void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aCo
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
VECTOR2I margin( 0, 0 );
|
||||
|
||||
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->GetSolderMaskExpansion();
|
||||
|
|
|
@ -544,7 +544,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPads( footprint, m_platedPadsFront, F_Cu, true, false, true );
|
||||
|
||||
addPads( footprint, m_platedPadsBack, B_Cu, true, false, true );
|
||||
}
|
||||
|
||||
|
@ -564,8 +563,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;
|
||||
|
||||
|
@ -565,7 +580,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
|
||||
|
||||
|
@ -582,8 +597,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
{
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetThroughHoleOdPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract(
|
||||
m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetOuterNonPlatedThroughHolePoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
|
@ -602,10 +616,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 )
|
||||
|
@ -628,6 +642,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() )
|
||||
|
@ -642,6 +660,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 );
|
||||
}
|
||||
|
||||
|
@ -700,20 +700,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 );
|
||||
}
|
||||
|
@ -749,16 +745,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,
|
||||
|
@ -767,6 +757,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,
|
||||
|
@ -783,21 +774,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 );
|
||||
|
|
|
@ -82,6 +82,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 );
|
||||
|
||||
|
|
|
@ -2336,51 +2336,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() == VECTOR2I( 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;
|
||||
|
||||
VECTOR2I 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->GetSolderMaskExpansion();
|
||||
|
|
|
@ -232,34 +232,14 @@ bool PAD::FlashLayer( LSET aLayers ) const
|
|||
|
||||
bool PAD::FlashLayer( int aLayer ) const
|
||||
{
|
||||
std::initializer_list<KICAD_T> types
|
||||
static std::initializer_list<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( !IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) ) )
|
||||
return false;
|
||||
|
||||
switch( GetAttribute() )
|
||||
if( GetAttribute() == PAD_ATTRIB::NPTH )
|
||||
{
|
||||
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() == VECTOR2I( 0, 0 ) && GetDrillSize().x >= GetSize().x )
|
||||
|
@ -273,17 +253,35 @@ bool PAD::FlashLayer( int aLayer ) const
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KI_FALLTHROUGH;
|
||||
|
||||
case PAD_ATTRIB::SMD:
|
||||
case PAD_ATTRIB::CONN:
|
||||
default:
|
||||
if( aLayer == UNDEFINED_LAYER )
|
||||
return true;
|
||||
|
||||
return IsOnLayer( static_cast<PCB_LAYER_ID>( aLayer ) );
|
||||
if( LSET::FrontBoardTechMask().test( aLayer ) )
|
||||
aLayer = F_Cu;
|
||||
else if( LSET::BackBoardTechMask().test( aLayer ) )
|
||||
aLayer = B_Cu;
|
||||
|
||||
if( GetAttribute() == PAD_ATTRIB::PTH && IsCopperLayer( aLayer ) )
|
||||
{
|
||||
/// Heat sink pads always get copper
|
||||
if( GetProperty() == PAD_PROP::HEATSINK )
|
||||
return true;
|
||||
|
||||
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