3D viewer: fix some graphic issues:

Avoid issue when a copper layers thickness is 0 (min value is now 1 micrometer)
Fix incorrect rendering of plated graphic items and vias (vertical walls not drawn)
From master branch
This commit is contained in:
jean-pierre charras 2024-03-28 14:52:31 +01:00
parent 92ffd898f5
commit 663e857df6
4 changed files with 48 additions and 31 deletions

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2015-2023 Mario Luzeiro <mrluzeiro@ua.pt> * Copyright (C) 2015-2023 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 2023 CERN * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -142,8 +142,8 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
m_offboardPadsFront = nullptr; m_offboardPadsFront = nullptr;
m_offboardPadsBack = nullptr; m_offboardPadsBack = nullptr;
m_frontPlatedPadPolys = nullptr; m_frontPlatedPadAndGraphicPolys = nullptr;
m_backPlatedPadPolys = nullptr; m_backPlatedPadAndGraphicPolys = nullptr;
m_frontPlatedCopperPolys = nullptr; m_frontPlatedCopperPolys = nullptr;
m_backPlatedCopperPolys = nullptr; m_backPlatedCopperPolys = nullptr;
@ -397,13 +397,18 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
break; break;
case BS_ITEM_TYPE_COPPER: case BS_ITEM_TYPE_COPPER:
if( item->GetBrdLayerId() == F_Cu ) {
m_frontCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits; // The copper thickness must be > 0 to avoid draw issues (divide by 0 for instance)
else if( item->GetBrdLayerId() == B_Cu ) // We use a minimal arbitrary value = 1 micrometer here:
m_backCopperThickness3DU = item->GetThickness() * m_biuTo3Dunits; int copper_thickness = std::max( item->GetThickness(), pcbIUScale.mmToIU( 0.001 ) );
else if( item->IsEnabled() )
thickness += item->GetThickness();
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; break;
default: default:
@ -449,7 +454,7 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
for( ; layer < MAX_CU_LAYERS; layer++ ) for( ; layer < MAX_CU_LAYERS; layer++ )
{ {
m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f ); 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. // This is the top of the copper layer thickness.

View File

@ -331,8 +331,8 @@ public:
*/ */
const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; } const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; }
const SHAPE_POLY_SET* GetFrontPlatedPadPolys() { return m_frontPlatedPadPolys; } const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys() { return m_frontPlatedPadAndGraphicPolys; }
const SHAPE_POLY_SET* GetBackPlatedPadPolys() { return m_backPlatedPadPolys; } const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys() { return m_backPlatedPadAndGraphicPolys; }
const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; } const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; }
const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; } const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; }
@ -438,8 +438,8 @@ private:
MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types
///< of items ///< of items
SHAPE_POLY_SET* m_frontPlatedPadPolys; SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys;
SHAPE_POLY_SET* m_backPlatedPadPolys; SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys;
SHAPE_POLY_SET* m_frontPlatedCopperPolys; SHAPE_POLY_SET* m_frontPlatedCopperPolys;
SHAPE_POLY_SET* m_backPlatedCopperPolys; SHAPE_POLY_SET* m_backPlatedCopperPolys;

View File

@ -117,8 +117,8 @@ void BOARD_ADAPTER::destroyLayers()
DELETE_AND_FREE_MAP( m_layers_poly ); DELETE_AND_FREE_MAP( m_layers_poly );
DELETE_AND_FREE( m_frontPlatedPadPolys ) DELETE_AND_FREE( m_frontPlatedPadAndGraphicPolys )
DELETE_AND_FREE( m_backPlatedPadPolys ) DELETE_AND_FREE( m_backPlatedPadAndGraphicPolys )
DELETE_AND_FREE( m_frontPlatedCopperPolys ) DELETE_AND_FREE( m_frontPlatedCopperPolys )
DELETE_AND_FREE( m_backPlatedCopperPolys ) DELETE_AND_FREE( m_backPlatedCopperPolys )
@ -241,8 +241,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( cfg.differentiate_plated_copper ) if( cfg.differentiate_plated_copper )
{ {
m_frontPlatedPadPolys = new SHAPE_POLY_SET; m_frontPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
m_backPlatedPadPolys = new SHAPE_POLY_SET; m_backPlatedPadAndGraphicPolys = new SHAPE_POLY_SET;
m_frontPlatedCopperPolys = new SHAPE_POLY_SET; m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
m_backPlatedCopperPolys = new SHAPE_POLY_SET; m_backPlatedCopperPolys = new SHAPE_POLY_SET;
@ -586,10 +586,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS contours // ADD PLATED PADS contours
for( FOOTPRINT* footprint : m_board->Footprints() ) 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 ); 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 ); ERROR_INSIDE, true, false, true );
} }
} }
@ -1050,21 +1050,33 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
SHAPE_POLY_SET::PM_FAST ); 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() ) 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 ); 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() ) 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 ); m_layers_poly[B_Cu]->BooleanSubtract( *m_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
hasB_Cu = true;
} }
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); // Add plated graphic items to build vertical walls
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); 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_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST ); m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );

View File

@ -613,12 +613,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper ) if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
{ {
const SHAPE_POLY_SET* frontPlatedPadPolys = m_boardAdapter.GetFrontPlatedPadPolys(); const SHAPE_POLY_SET* frontPlatedPadAndGraphicPolys = m_boardAdapter.GetFrontPlatedPadAndGraphicPolys();
const SHAPE_POLY_SET* backPlatedPadPolys = m_boardAdapter.GetBackPlatedPadPolys(); 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.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), 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 ); 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 ); 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.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
poly.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), 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 ); poly.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );