diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 569e082ff6..052fd94d23 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -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(); diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index fb113c478a..dfa75412fb 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -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, diff --git a/3d-viewer/3d_rendering/opengl/create_scene.cpp b/3d-viewer/3d_rendering/opengl/create_scene.cpp index 5115481cb7..df3f275aa0 100644 --- a/3d-viewer/3d_rendering/opengl/create_scene.cpp +++ b/3d-viewer/3d_rendering/opengl/create_scene.cpp @@ -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,9 +597,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.m_Cfg->m_Render.subtract_mask_from_silk ) @@ -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 ); } } diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp index 2fce63b6c6..be0306c372 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp @@ -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 ); diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.h b/3d-viewer/3d_rendering/opengl/render_3d_opengl.h index a9bd38b1c0..3c2ae1d002 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.h +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.h @@ -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 ); diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index e2803d0010..3a128460df 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -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(); diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 97f178f68e..b1af61fe63 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -232,34 +232,14 @@ bool PAD::FlashLayer( LSET aLayers ) const bool PAD::FlashLayer( int aLayer ) const { - std::initializer_list types + static std::initializer_list 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( 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( aLayer ) ); - - if( !m_removeUnconnectedLayer ) - return IsOnLayer( static_cast( 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( aLayer ) ); - - return board && board->GetConnectivity()->IsConnectedOnLayer( this, - static_cast( 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; + if( aLayer == UNDEFINED_LAYER ) + return true; - case PAD_ATTRIB::SMD: - case PAD_ATTRIB::CONN: - default: - if( aLayer == UNDEFINED_LAYER ) + 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; - return IsOnLayer( static_cast( 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; }