diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index d84e713920..112d9f6e45 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -3,7 +3,7 @@ * * Copyright (C) 2015-2023 Mario Luzeiro * Copyright (C) 2023 CERN - * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2024 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -142,8 +142,8 @@ BOARD_ADAPTER::BOARD_ADAPTER() : m_offboardPadsFront = nullptr; m_offboardPadsBack = nullptr; - m_frontPlatedPadPolys = nullptr; - m_backPlatedPadPolys = nullptr; + m_frontPlatedPadAndGraphicPolys = nullptr; + m_backPlatedPadAndGraphicPolys = nullptr; m_frontPlatedCopperPolys = nullptr; m_backPlatedCopperPolys = nullptr; @@ -397,13 +397,18 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR break; case BS_ITEM_TYPE_COPPER: - if( item->GetBrdLayerId() == F_Cu ) - m_frontCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits; - else if( item->GetBrdLayerId() == B_Cu ) - m_backCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits; - else if( item->IsEnabled() ) - thickness += item->GetThickness(); + { + // The copper thickness must be > 0 to avoid draw issues (divide by 0 for instance) + // We use a minimal arbitrary value = 1 micrometer here: + int copper_thickness = std::max( item->GetThickness(), pcbIUScale.mmToIU( 0.001 ) ); + if( item->GetBrdLayerId() == F_Cu ) + m_frontCopperThickness3DU = copper_thickness * m_biuTo3Dunits; + else if( item->GetBrdLayerId() == B_Cu ) + m_backCopperThickness3DU = copper_thickness * m_biuTo3Dunits; + else if( item->IsEnabled() ) + thickness += copper_thickness; + } break; default: @@ -449,7 +454,7 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR for( ; layer < MAX_CU_LAYERS; layer++ ) { m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f ); - m_layerZcoordTop[layer] = -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU; + m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_backCopperThickness3DU; } // This is the top of the copper layer thickness. diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index 9816096b85..c8023fe905 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -333,8 +333,8 @@ public: */ const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; } - const SHAPE_POLY_SET* GetFrontPlatedPadPolys() { return m_frontPlatedPadPolys; } - const SHAPE_POLY_SET* GetBackPlatedPadPolys() { return m_backPlatedPadPolys; } + const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys() { return m_frontPlatedPadAndGraphicPolys; } + const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys() { return m_backPlatedPadAndGraphicPolys; } const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; } const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; } @@ -443,8 +443,8 @@ private: MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types ///< of items - SHAPE_POLY_SET* m_frontPlatedPadPolys; - SHAPE_POLY_SET* m_backPlatedPadPolys; + SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys; + SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys; SHAPE_POLY_SET* m_frontPlatedCopperPolys; SHAPE_POLY_SET* m_backPlatedCopperPolys; diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 8dab395953..d817a456c4 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -118,8 +118,8 @@ void BOARD_ADAPTER::destroyLayers() DELETE_AND_FREE_MAP( m_layers_poly ); - DELETE_AND_FREE( m_frontPlatedPadPolys ) - DELETE_AND_FREE( m_backPlatedPadPolys ) + DELETE_AND_FREE( m_frontPlatedPadAndGraphicPolys ) + DELETE_AND_FREE( m_backPlatedPadAndGraphicPolys ) DELETE_AND_FREE( m_frontPlatedCopperPolys ) DELETE_AND_FREE( m_backPlatedCopperPolys ) @@ -242,8 +242,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) if( cfg.differentiate_plated_copper ) { - m_frontPlatedPadPolys = new SHAPE_POLY_SET; - m_backPlatedPadPolys = new SHAPE_POLY_SET; + m_frontPlatedPadAndGraphicPolys = new SHAPE_POLY_SET; + m_backPlatedPadAndGraphicPolys = new SHAPE_POLY_SET; m_frontPlatedCopperPolys = new SHAPE_POLY_SET; m_backPlatedCopperPolys = new SHAPE_POLY_SET; @@ -587,10 +587,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) // ADD PLATED PADS contours for( FOOTPRINT* footprint : m_board->Footprints() ) { - footprint->TransformPadsToPolySet( *m_frontPlatedPadPolys, F_Cu, 0, maxError, + footprint->TransformPadsToPolySet( *m_frontPlatedPadAndGraphicPolys, F_Cu, 0, maxError, ERROR_INSIDE, true, false, true ); - footprint->TransformPadsToPolySet( *m_backPlatedPadPolys, B_Cu, 0, maxError, + footprint->TransformPadsToPolySet( *m_backPlatedPadAndGraphicPolys, B_Cu, 0, maxError, ERROR_INSIDE, true, false, true ); } } @@ -1067,21 +1067,33 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) SHAPE_POLY_SET::PM_FAST ); } - // SUBTRACT PLATED COPPER FROM (UNPLATED) COPPER + // Subtract plated copper from unplated copper + bool hasF_Cu = false; + bool hasB_Cu = false; + if( m_layers_poly.find( F_Cu ) != m_layers_poly.end() ) { - m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadPolys, SHAPE_POLY_SET::PM_FAST ); + m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST ); m_layers_poly[F_Cu]->BooleanSubtract( *m_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST ); + hasF_Cu = true; } if( m_layers_poly.find( B_Cu ) != m_layers_poly.end() ) { - m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadPolys, SHAPE_POLY_SET::PM_FAST ); + m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedPadAndGraphicPolys, SHAPE_POLY_SET::PM_FAST ); m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST ); + hasB_Cu = true; } - m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); - m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); + // Add plated graphic items to build vertical walls + if( hasF_Cu && m_frontPlatedCopperPolys->OutlineCount() ) + m_frontPlatedPadAndGraphicPolys->Append( *m_frontPlatedCopperPolys ); + + if( hasB_Cu && m_backPlatedCopperPolys->OutlineCount() ) + m_backPlatedPadAndGraphicPolys->Append( *m_backPlatedCopperPolys ); + + m_frontPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); + m_backPlatedPadAndGraphicPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); diff --git a/3d-viewer/3d_rendering/opengl/create_scene.cpp b/3d-viewer/3d_rendering/opengl/create_scene.cpp index 9492541b9c..687e8d4ab7 100644 --- a/3d-viewer/3d_rendering/opengl/create_scene.cpp +++ b/3d-viewer/3d_rendering/opengl/create_scene.cpp @@ -613,12 +613,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper ) { - const SHAPE_POLY_SET* frontPlatedPadPolys = m_boardAdapter.GetFrontPlatedPadPolys(); - const SHAPE_POLY_SET* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys(); + const SHAPE_POLY_SET* frontPlatedPadAndGraphicPolys = m_boardAdapter.GetFrontPlatedPadAndGraphicPolys(); + const SHAPE_POLY_SET* backPlatedPadAndGraphicPolys = m_boardAdapter.GetBackPlatedPadAndGraphicPolys(); - if( frontPlatedPadPolys ) + if( frontPlatedPadAndGraphicPolys ) { - SHAPE_POLY_SET poly = frontPlatedPadPolys->CloneDropTriangulation(); + SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation(); poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); @@ -630,9 +630,9 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo m_layers[F_Cu] = generateEmptyLayerList( F_Cu ); } - if( backPlatedPadPolys ) + if( backPlatedPadAndGraphicPolys ) { - SHAPE_POLY_SET poly = backPlatedPadPolys->CloneDropTriangulation(); + SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation(); poly.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST ); poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );