Handle plated vs non-plated copper for copper other than pads.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/5569
This commit is contained in:
parent
cce366bc1d
commit
c1a988e3ff
|
@ -143,6 +143,8 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
|
|||
|
||||
m_frontPlatedPadPolys = nullptr;
|
||||
m_backPlatedPadPolys = nullptr;
|
||||
m_frontPlatedCopperPolys = nullptr;
|
||||
m_backPlatedCopperPolys = nullptr;
|
||||
|
||||
if( !g_ColorsLoaded )
|
||||
{
|
||||
|
|
|
@ -434,6 +434,8 @@ private:
|
|||
|
||||
SHAPE_POLY_SET* m_frontPlatedPadPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadPolys;
|
||||
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedCopperPolys;
|
||||
|
||||
MAP_POLY m_layerHoleOdPolys; ///< Hole outer diameters (per layer)
|
||||
MAP_POLY m_layerHoleIdPolys; ///< Hole inner diameters (per layer)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "board_adapter.h"
|
||||
#include "../3d_rendering/raytracing/shapes2D/filled_circle_2d.h"
|
||||
#include "raytracing/shapes2D/triangle_2d.h"
|
||||
#include <board_design_settings.h>
|
||||
#include <footprint.h>
|
||||
#include <pad.h>
|
||||
|
@ -118,6 +119,8 @@ void BOARD_ADAPTER::destroyLayers()
|
|||
|
||||
DELETE_AND_FREE( m_frontPlatedPadPolys )
|
||||
DELETE_AND_FREE( m_backPlatedPadPolys )
|
||||
DELETE_AND_FREE( m_frontPlatedCopperPolys )
|
||||
DELETE_AND_FREE( m_backPlatedCopperPolys )
|
||||
|
||||
DELETE_AND_FREE_MAP( m_layerHoleOdPolys )
|
||||
DELETE_AND_FREE_MAP( m_layerHoleIdPolys )
|
||||
|
@ -234,10 +237,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
}
|
||||
}
|
||||
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
m_frontPlatedPadPolys = new SHAPE_POLY_SET;
|
||||
m_backPlatedPadPolys = new SHAPE_POLY_SET;
|
||||
m_frontPlatedCopperPolys = new SHAPE_POLY_SET;
|
||||
m_backPlatedCopperPolys = new SHAPE_POLY_SET;
|
||||
|
||||
m_platedPadsFront = new BVH_CONTAINER_2D;
|
||||
m_platedPadsBack = new BVH_CONTAINER_2D;
|
||||
|
@ -339,6 +344,17 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
m_TH_IDs.Add( new FILLED_CIRCLE_2D( via_center, hole_inner_radius, *track ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( cfg.differentiate_plated_copper && layer == F_Cu )
|
||||
{
|
||||
track->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
else if( cfg.differentiate_plated_copper && layer == B_Cu )
|
||||
{
|
||||
track->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,26 +545,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
// ADD PADS
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPads( footprint, layerContainer, layer, cfg.renderPlatedPadsAsPlated, false );
|
||||
addPads( footprint, layerContainer, layer, cfg.differentiate_plated_copper, false );
|
||||
|
||||
// Micro-wave footprints may have items on copper layers
|
||||
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
|
||||
}
|
||||
}
|
||||
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
{
|
||||
// ADD PLATED PADS
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
|
||||
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
|
||||
}
|
||||
|
||||
m_platedPadsFront->BuildBVH();
|
||||
m_platedPadsBack->BuildBVH();
|
||||
}
|
||||
|
||||
// Add footprints PADs poly contours (vertical outlines)
|
||||
if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
|
||||
{
|
||||
|
@ -564,13 +567,13 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
// Note: NPTH pads are not drawn on copper layers when the pad has same shape as
|
||||
// its hole
|
||||
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE,
|
||||
true, cfg.renderPlatedPadsAsPlated, false );
|
||||
true, cfg.differentiate_plated_copper, false );
|
||||
|
||||
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
// ADD PLATED PADS contours
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
|
@ -688,6 +691,17 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
{
|
||||
zones.emplace_back( std::make_pair( zone, layer ) );
|
||||
layer_lock.emplace( layer, std::make_unique<std::mutex>() );
|
||||
|
||||
if( cfg.differentiate_plated_copper && layer == F_Cu )
|
||||
{
|
||||
zone->TransformShapeToPolygon( *m_frontPlatedCopperPolys, F_Cu, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
else if( cfg.differentiate_plated_copper && layer == B_Cu )
|
||||
{
|
||||
zone->TransformShapeToPolygon( *m_backPlatedCopperPolys, B_Cu, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,45 +751,339 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
|
||||
while( threadsFinished < parallelThreadCount )
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||
|
||||
}
|
||||
// End Build Copper layers
|
||||
|
||||
// This will make a union of all added contours
|
||||
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
// Build Tech layers
|
||||
// Based on:
|
||||
// https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Build Tech layers" ) );
|
||||
|
||||
// draw graphic items, on technical layers
|
||||
|
||||
static const PCB_LAYER_ID techLayerList[] = {
|
||||
B_Adhes,
|
||||
F_Adhes,
|
||||
B_Paste,
|
||||
F_Paste,
|
||||
B_SilkS,
|
||||
F_SilkS,
|
||||
B_Mask,
|
||||
F_Mask,
|
||||
|
||||
// Aux Layers
|
||||
Dwgs_User,
|
||||
Cmts_User,
|
||||
Eco1_User,
|
||||
Eco2_User
|
||||
};
|
||||
|
||||
std::bitset<LAYER_3D_END> enabledFlags = visibilityFlags;
|
||||
|
||||
if( cfg.subtract_mask_from_silk || cfg.differentiate_plated_copper )
|
||||
{
|
||||
enabledFlags.set( LAYER_3D_SOLDERMASK_TOP );
|
||||
enabledFlags.set( LAYER_3D_SOLDERMASK_BOTTOM );
|
||||
}
|
||||
|
||||
for( PCB_LAYER_ID layer : LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) ) )
|
||||
{
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
|
||||
|
||||
if( !Is3dLayerEnabled( layer, enabledFlags ) )
|
||||
continue;
|
||||
|
||||
BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
|
||||
m_layerMap[layer] = layerContainer;
|
||||
|
||||
SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
|
||||
m_layers_poly[layer] = layerPoly;
|
||||
|
||||
if( Is3dLayerEnabled( layer, visibilityFlags ) )
|
||||
{
|
||||
// Add drawing objects
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_SHAPE_T:
|
||||
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
|
||||
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
|
||||
break;
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add via tech layers
|
||||
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
|
||||
{
|
||||
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T
|
||||
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
|
||||
{
|
||||
createViaWithMargin( track, layerContainer, maskExpansion );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add footprints tech layers - objects
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( layer == F_SilkS || layer == B_SilkS )
|
||||
{
|
||||
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
|
||||
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
buildPadOutlineAsSegments( pad, layerContainer, linewidth );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addPads( footprint, layerContainer, layer, false, false );
|
||||
}
|
||||
|
||||
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
|
||||
}
|
||||
|
||||
// Draw non copper zones
|
||||
if( cfg.show_zones )
|
||||
{
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
if( zone->IsOnLayer( layer ) )
|
||||
addSolidAreasShapes( zone, layerContainer, layer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add item contours. We need these if we're building vertical walls or if this is a
|
||||
// mask layer and we're differentiating copper from plated copper.
|
||||
if( ( cfg.engine == RENDER_ENGINE::OPENGL && cfg.opengl_copper_thickness )
|
||||
|| ( cfg.differentiate_plated_copper && ( layer == F_Mask || layer == B_Mask ) ) )
|
||||
{
|
||||
// DRAWINGS
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_SHAPE_T:
|
||||
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
|
||||
|
||||
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
{
|
||||
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
|
||||
|
||||
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// NON-TENTED VIAS
|
||||
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
|
||||
{
|
||||
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T
|
||||
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
|
||||
{
|
||||
track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FOOTPRINT CHILDREN
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( layer == F_SilkS || layer == B_SilkS )
|
||||
{
|
||||
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
|
||||
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
if( pad->IsOnLayer( layer ) )
|
||||
{
|
||||
buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
}
|
||||
|
||||
// On tech layers, use a poor circle approximation, only for texts (stroke font)
|
||||
footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
|
||||
// Add the remaining things with dynamic seg count for circles
|
||||
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
|
||||
}
|
||||
|
||||
if( cfg.show_zones || layer == F_Mask || layer == B_Mask )
|
||||
{
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
if( zone->IsOnLayer( layer ) )
|
||||
zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
|
||||
}
|
||||
}
|
||||
|
||||
// This will make a union of all added contours
|
||||
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
// End Build Tech layers
|
||||
|
||||
#if 1
|
||||
// A somewhat experimental feature: if we're rendering off-board silk, turn any pads of
|
||||
// footprints which are entirely outside the board outline into silk. This makes off-board
|
||||
// footprints more visually recognizable.
|
||||
if( cfg.show_off_board_silk )
|
||||
{
|
||||
BOX2I boardBBox = m_board_poly.BBox();
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
|
||||
{
|
||||
if( footprint->IsFlipped() )
|
||||
{
|
||||
BVH_CONTAINER_2D *layerContainer = m_layerMap[ B_SilkS ];
|
||||
addPads( footprint, layerContainer, B_Cu, false, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
BVH_CONTAINER_2D *layerContainer = m_layerMap[ F_SilkS ];
|
||||
addPads( footprint, layerContainer, F_Cu, false, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simplify layer polygons
|
||||
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Simplifying copper layers polygons" ) );
|
||||
aStatusReporter->Report( _( "Simplifying copper layer polygons" ) );
|
||||
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Calculating plated copper" ) );
|
||||
|
||||
// TRIM PLATED COPPER TO SOLDERMASK
|
||||
if( m_layers_poly.find( F_Mask ) != m_layers_poly.end() )
|
||||
{
|
||||
m_frontPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( F_Mask ),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( m_layers_poly.find( B_Mask ) != m_layers_poly.end() )
|
||||
{
|
||||
m_backPlatedCopperPolys->BooleanIntersection( *m_layers_poly.at( B_Mask ),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
// SUBTRACT PLATED COPPER FROM (UNPLATED) COPPER
|
||||
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_frontPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
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_backPlatedCopperPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_frontPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_backPlatedCopperPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
// ADD PLATED PADS
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
|
||||
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
|
||||
}
|
||||
|
||||
// ADD PLATED COPPER
|
||||
ConvertPolygonToTriangles( *m_frontPlatedCopperPolys, *m_platedPadsFront, m_biuTo3Dunits,
|
||||
*m_board->GetItem( niluuid ) );
|
||||
|
||||
ConvertPolygonToTriangles( *m_backPlatedCopperPolys, *m_platedPadsBack, m_biuTo3Dunits,
|
||||
*m_board->GetItem( niluuid ) );
|
||||
|
||||
m_platedPadsFront->BuildBVH();
|
||||
m_platedPadsBack->BuildBVH();
|
||||
}
|
||||
|
||||
if( cfg.opengl_copper_thickness && cfg.engine == RENDER_ENGINE::OPENGL )
|
||||
{
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
{
|
||||
if( m_frontPlatedPadPolys && ( m_layers_poly.find( F_Cu ) != m_layers_poly.end() ) )
|
||||
{
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Simplifying polygons on F_Cu" ) );
|
||||
|
||||
SHAPE_POLY_SET *layerPoly_F_Cu = m_layers_poly[F_Cu];
|
||||
layerPoly_F_Cu->BooleanSubtract( *m_frontPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
m_frontPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( m_backPlatedPadPolys && ( m_layers_poly.find( B_Cu ) != m_layers_poly.end() ) )
|
||||
{
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Simplifying polygons on B_Cu" ) );
|
||||
|
||||
SHAPE_POLY_SET *layerPoly_B_Cu = m_layers_poly[B_Cu];
|
||||
layerPoly_B_Cu->BooleanSubtract( *m_backPlatedPadPolys, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
m_backPlatedPadPolys->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PCB_LAYER_ID> &selected_layer_id = layer_ids;
|
||||
std::vector<PCB_LAYER_ID> layer_id_without_F_and_B;
|
||||
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
if( cfg.differentiate_plated_copper )
|
||||
{
|
||||
layer_id_without_F_and_B.clear();
|
||||
layer_id_without_F_and_B.reserve( layer_ids.size() );
|
||||
|
@ -816,8 +1124,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
auto layerPoly = m_layers_poly.find( selected_layer_id[i] );
|
||||
|
||||
if( layerPoly != m_layers_poly.end() )
|
||||
{
|
||||
// This will make a union of all added contours
|
||||
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
|
||||
threadsFinished++;
|
||||
|
@ -850,268 +1160,6 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
}
|
||||
}
|
||||
|
||||
// End Build Copper layers
|
||||
|
||||
// This will make a union of all added contours
|
||||
m_TH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_NPTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_viaTH_ODPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
m_viaAnnuliPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
// Build Tech layers
|
||||
// Based on:
|
||||
// https://github.com/KiCad/kicad-source-mirror/blob/master/3d-viewer/3d_draw.cpp#L1059
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( _( "Build Tech layers" ) );
|
||||
|
||||
// draw graphic items, on technical layers
|
||||
|
||||
// Vertical walls (layer thickness) around shapes is really time consumming
|
||||
// They are built on request
|
||||
bool buildVerticalWallsForTechLayers = cfg.opengl_copper_thickness
|
||||
&& cfg.engine == RENDER_ENGINE::OPENGL;
|
||||
|
||||
static const PCB_LAYER_ID techLayerList[] = {
|
||||
B_Adhes,
|
||||
F_Adhes,
|
||||
B_Paste,
|
||||
F_Paste,
|
||||
B_SilkS,
|
||||
F_SilkS,
|
||||
B_Mask,
|
||||
F_Mask,
|
||||
|
||||
// Aux Layers
|
||||
Dwgs_User,
|
||||
Cmts_User,
|
||||
Eco1_User,
|
||||
Eco2_User
|
||||
};
|
||||
|
||||
for( LSEQ seq = LSET::AllNonCuMask().Seq( techLayerList, arrayDim( techLayerList ) );
|
||||
seq;
|
||||
++seq )
|
||||
{
|
||||
const PCB_LAYER_ID layer = *seq;
|
||||
|
||||
if( !Is3dLayerEnabled( layer, visibilityFlags ) )
|
||||
continue;
|
||||
|
||||
if( aStatusReporter )
|
||||
aStatusReporter->Report( wxString::Format( _( "Build Tech layer %d" ), (int) layer ) );
|
||||
|
||||
BVH_CONTAINER_2D *layerContainer = new BVH_CONTAINER_2D;
|
||||
m_layerMap[layer] = layerContainer;
|
||||
|
||||
SHAPE_POLY_SET *layerPoly = new SHAPE_POLY_SET;
|
||||
m_layers_poly[layer] = layerPoly;
|
||||
|
||||
// Add drawing objects
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_SHAPE_T:
|
||||
addShape( static_cast<PCB_SHAPE*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
addText( static_cast<PCB_TEXT*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
addText( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
if( static_cast<PCB_TEXTBOX*>( item )->IsBorderEnabled() )
|
||||
addShape( static_cast<PCB_TEXTBOX*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
case PCB_DIM_ALIGNED_T:
|
||||
case PCB_DIM_CENTER_T:
|
||||
case PCB_DIM_RADIAL_T:
|
||||
case PCB_DIM_ORTHOGONAL_T:
|
||||
case PCB_DIM_LEADER_T:
|
||||
addShape( static_cast<PCB_DIMENSION_BASE*>( item ), layerContainer, item );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add drawing contours (vertical walls)
|
||||
if( buildVerticalWallsForTechLayers )
|
||||
{
|
||||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
{
|
||||
if( !item->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_SHAPE_T:
|
||||
item->TransformShapeToPolygon( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
|
||||
case PCB_TEXT_T:
|
||||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
|
||||
|
||||
text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_TEXTBOX_T:
|
||||
{
|
||||
PCB_TEXTBOX* textbox = static_cast<PCB_TEXTBOX*>( item );
|
||||
|
||||
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add via tech layers
|
||||
if( ( layer == F_Mask || layer == B_Mask ) && !m_board->GetTentVias() )
|
||||
{
|
||||
int maskExpansion = GetBoard()->GetDesignSettings().m_SolderMaskExpansion;
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T
|
||||
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
|
||||
{
|
||||
createViaWithMargin( track, layerContainer, maskExpansion );
|
||||
}
|
||||
}
|
||||
|
||||
// Add via tech layers - contours (vertical walls)
|
||||
if( buildVerticalWallsForTechLayers )
|
||||
{
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T
|
||||
&& static_cast<const PCB_VIA*>( track )->FlashLayer( layer ) )
|
||||
{
|
||||
track->TransformShapeToPolygon( *layerPoly, layer, maskExpansion, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add footprints tech layers - objects
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( layer == F_SilkS || layer == B_SilkS )
|
||||
{
|
||||
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
|
||||
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
if( !pad->IsOnLayer( layer ) )
|
||||
continue;
|
||||
|
||||
buildPadOutlineAsSegments( pad, layerContainer, linewidth );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addPads( footprint, layerContainer, layer, false, false );
|
||||
}
|
||||
|
||||
addFootprintShapes( footprint, layerContainer, layer, visibilityFlags );
|
||||
}
|
||||
|
||||
|
||||
// Add footprints tech layers - contours (vertical walls)
|
||||
if( buildVerticalWallsForTechLayers )
|
||||
{
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( layer == F_SilkS || layer == B_SilkS )
|
||||
{
|
||||
int linewidth = m_board->GetDesignSettings().m_LineThickness[ LAYER_CLASS_SILK ];
|
||||
|
||||
for( PAD* pad : footprint->Pads() )
|
||||
{
|
||||
if( pad->IsOnLayer( layer ) )
|
||||
{
|
||||
buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
|
||||
ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
footprint->TransformPadsToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
}
|
||||
|
||||
// On tech layers, use a poor circle approximation, only for texts (stroke font)
|
||||
footprint->TransformFPTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
|
||||
// Add the remaining things with dynamic seg count for circles
|
||||
transformFPShapesToPolySet( footprint, layer, *layerPoly, maxError, ERROR_INSIDE );
|
||||
}
|
||||
}
|
||||
|
||||
// Draw non copper zones
|
||||
if( cfg.show_zones )
|
||||
{
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
if( zone->IsOnLayer( layer ) )
|
||||
addSolidAreasShapes( zone, layerContainer, layer );
|
||||
}
|
||||
|
||||
if( buildVerticalWallsForTechLayers )
|
||||
{
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
if( zone->IsOnLayer( layer ) )
|
||||
zone->TransformSolidAreasShapesToPolygon( layer, *layerPoly );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will make a union of all added contours
|
||||
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
// End Build Tech layers
|
||||
|
||||
#if 1
|
||||
// A somewhat experimental feature: if we're rendering off-board silk, turn any pads of
|
||||
// footprints which are entirely outside the board outline into silk. This makes off-board
|
||||
// footprints more visually recognizable.
|
||||
if( cfg.show_off_board_silk )
|
||||
{
|
||||
BOX2I boardBBox = m_board_poly.BBox();
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
{
|
||||
if( !footprint->GetBoundingBox().Intersects( boardBBox ) )
|
||||
{
|
||||
if( footprint->IsFlipped() )
|
||||
{
|
||||
BVH_CONTAINER_2D *layerContainer = m_layerMap[ B_SilkS ];
|
||||
addPads( footprint, layerContainer, B_Cu, false, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
BVH_CONTAINER_2D *layerContainer = m_layerMap[ F_SilkS ];
|
||||
addPads( footprint, layerContainer, F_Cu, false, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Build BVH (Bounding volume hierarchy) for holes and vias
|
||||
|
||||
if( aStatusReporter )
|
||||
|
|
|
@ -565,39 +565,42 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
|
||||
if( map_poly.find( layer ) != map_poly.end() )
|
||||
if( m_boardAdapter.m_Cfg->m_Render.opengl_copper_thickness )
|
||||
{
|
||||
polyListSubtracted = *map_poly.at( layer );
|
||||
|
||||
if( LSET::PhysicalLayersMask().test( layer ) )
|
||||
if( map_poly.find( layer ) != map_poly.end() )
|
||||
{
|
||||
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
polyListSubtracted = *map_poly.at( layer );
|
||||
|
||||
if( layer != B_Mask && layer != F_Mask )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
|
||||
{
|
||||
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
|
||||
if( LSET::PhysicalLayersMask().test( layer ) )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
|
||||
polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
|
||||
if( layer != B_Mask && layer != F_Mask )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
|
||||
polyList = &polyListSubtracted;
|
||||
if( m_boardAdapter.m_Cfg->m_Render.subtract_mask_from_silk )
|
||||
{
|
||||
if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
|
||||
{
|
||||
polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
}
|
||||
|
||||
polyList = &polyListSubtracted;
|
||||
}
|
||||
}
|
||||
|
||||
OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer,
|
||||
|
@ -607,20 +610,19 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
m_layers[layer] = oglList;
|
||||
}
|
||||
|
||||
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated )
|
||||
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();
|
||||
|
||||
if( frontPlatedPadPolys )
|
||||
{
|
||||
SHAPE_POLY_SET polySubtracted = frontPlatedPadPolys->CloneDropTriangulation();
|
||||
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
||||
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
SHAPE_POLY_SET poly = frontPlatedPadPolys->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 );
|
||||
|
||||
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(),
|
||||
&polySubtracted, F_Cu );
|
||||
m_platedPadsFront = generateLayerList( m_boardAdapter.GetPlatedPadsFront(), &poly, 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 )
|
||||
|
@ -629,13 +631,12 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
|
|||
|
||||
if( backPlatedPadPolys )
|
||||
{
|
||||
SHAPE_POLY_SET polySubtracted = backPlatedPadPolys->CloneDropTriangulation();
|
||||
polySubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(), SHAPE_POLY_SET::PM_FAST );
|
||||
polySubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
polySubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(), SHAPE_POLY_SET::PM_FAST );
|
||||
SHAPE_POLY_SET poly = backPlatedPadPolys->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 );
|
||||
|
||||
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(),
|
||||
&polySubtracted, B_Cu );
|
||||
m_platedPadsBack = generateLayerList( m_boardAdapter.GetPlatedPadsBack(), &poly, 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 )
|
||||
|
|
|
@ -584,7 +584,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
|||
|
||||
if( isCopperLayer )
|
||||
{
|
||||
if( cfg.renderPlatedPadsAsPlated )
|
||||
if( cfg.differentiate_plated_copper )
|
||||
setCopperMaterial();
|
||||
else
|
||||
setLayerMaterial( layer_id );
|
||||
|
|
|
@ -625,7 +625,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
|
|||
break;
|
||||
|
||||
default:
|
||||
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated )
|
||||
if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
|
||||
{
|
||||
layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
|
||||
materialLayer = &m_materials.m_NonPlatedCopper;
|
||||
|
@ -643,7 +643,7 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
|
|||
} // for each layer on map
|
||||
|
||||
// Create plated copper
|
||||
if( m_boardAdapter.m_Cfg->m_Render.renderPlatedPadsAsPlated )
|
||||
if( m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
|
||||
{
|
||||
createItemsFromContainer( m_boardAdapter.GetPlatedPadsFront(), F_Cu, &m_materials.m_Copper,
|
||||
m_boardAdapter.m_CopperColor,
|
||||
|
|
|
@ -367,7 +367,7 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() :
|
|||
m_params.emplace_back( new PARAM<bool>( "render.clip_silk_on_via_annulus",
|
||||
&m_Render.clip_silk_on_via_annuli, false ) );
|
||||
m_params.emplace_back( new PARAM<bool>( "render.plated_and_bare_copper",
|
||||
&m_Render.renderPlatedPadsAsPlated, false ) );
|
||||
&m_Render.differentiate_plated_copper, false ) );
|
||||
m_params.emplace_back( new PARAM<bool>( "camera.animation_enabled",
|
||||
&m_Camera.animation_enabled, true ) );
|
||||
m_params.emplace_back( new PARAM<int>( "camera.moving_speed_multiplier",
|
||||
|
|
|
@ -120,7 +120,6 @@ public:
|
|||
std::vector<int> raytrace_lightElevation; // -90 .. 90
|
||||
std::vector<int> raytrace_lightAzimuth; // 0 .. 359
|
||||
|
||||
bool realistic;
|
||||
bool show_adhesive;
|
||||
bool show_axis;
|
||||
bool show_board_body;
|
||||
|
@ -146,7 +145,7 @@ public:
|
|||
bool show_fp_text;
|
||||
bool subtract_mask_from_silk;
|
||||
bool clip_silk_on_via_annuli;
|
||||
bool renderPlatedPadsAsPlated;
|
||||
bool differentiate_plated_copper;
|
||||
};
|
||||
|
||||
struct CAMERA_SETTINGS
|
||||
|
|
|
@ -49,7 +49,7 @@ void PANEL_3D_DISPLAY_OPTIONS::loadViewSettings( EDA_3D_VIEWER_SETTINGS* aCfg )
|
|||
|
||||
m_checkBoxSubtractMaskFromSilk->SetValue( aCfg->m_Render.subtract_mask_from_silk );
|
||||
m_checkBoxClipSilkOnViaAnnulus->SetValue( aCfg->m_Render.clip_silk_on_via_annuli );
|
||||
m_checkBoxRenderPlatedPadsAsPlated->SetValue( aCfg->m_Render.renderPlatedPadsAsPlated );
|
||||
m_checkBoxRenderPlatedPadsAsPlated->SetValue( aCfg->m_Render.differentiate_plated_copper );
|
||||
|
||||
m_materialProperties->SetSelection( static_cast<int>( aCfg->m_Render.material_mode ) );
|
||||
|
||||
|
@ -80,7 +80,7 @@ bool PANEL_3D_DISPLAY_OPTIONS::TransferDataFromWindow()
|
|||
cfg->m_Render.show_zones = m_checkBoxAreas->GetValue();
|
||||
cfg->m_Render.subtract_mask_from_silk = m_checkBoxSubtractMaskFromSilk->GetValue();
|
||||
cfg->m_Render.clip_silk_on_via_annuli = m_checkBoxClipSilkOnViaAnnulus->GetValue();
|
||||
cfg->m_Render.renderPlatedPadsAsPlated = m_checkBoxRenderPlatedPadsAsPlated->GetValue();
|
||||
cfg->m_Render.differentiate_plated_copper = m_checkBoxRenderPlatedPadsAsPlated->GetValue();
|
||||
|
||||
cfg->m_Render.material_mode = static_cast<MATERIAL_MODE>( m_materialProperties->GetSelection() );
|
||||
|
||||
|
|
Loading…
Reference in New Issue