Source 3D dimensions from board stackup.

Also includes a performance improvemnt by caching the 3D model matrices.
This commit is contained in:
Jeff Young 2021-12-03 14:14:50 +00:00
parent 2538ad16aa
commit dabc75bee8
7 changed files with 125 additions and 100 deletions

View File

@ -39,6 +39,15 @@
#include <wx/log.h> #include <wx/log.h>
#define DEFAULT_BOARD_THICKNESS Millimeter2iu( 1.6 )
#define DEFAULT_COPPER_THICKNESS Millimeter2iu( 0.035 ) // for 35 um
// The solder mask layer (and silkscreen) thickness
#define DEFAULT_TECH_LAYER_THICKNESS Millimeter2iu( 0.025 )
// The solder paste thickness is chosen bigger than the solder mask layer
// to be sure is covers the mask when overlapping.
#define SOLDERPASTE_LAYER_THICKNESS Millimeter2iu( 0.04 )
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_SilkscreenColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_SilkscreenColors;
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_MaskColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_MaskColors;
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_PasteColors; CUSTOM_COLORS_LIST BOARD_ADAPTER::g_PasteColors;
@ -91,12 +100,14 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
m_throughHoleOds.Clear(); m_throughHoleOds.Clear();
m_throughHoleAnnularRings.Clear(); m_throughHoleAnnularRings.Clear();
m_copperLayersCount = -1; m_copperLayersCount = 2;
m_epoxyThickness3DU = 0.0f;
m_copperThickness3DU = 0.0f;
m_nonCopperLayerThickness3DU = 0.0f;
m_solderPasteLayerThickness3DU = 0.0f;
m_biuTo3Dunits = 1.0; m_biuTo3Dunits = 1.0;
m_boardBodyThickness3DU = DEFAULT_BOARD_THICKNESS * m_biuTo3Dunits;
m_frontCopperThickness3DU = DEFAULT_COPPER_THICKNESS * m_biuTo3Dunits;
m_backCopperThickness3DU = DEFAULT_COPPER_THICKNESS * m_biuTo3Dunits;
m_nonCopperLayerThickness3DU = DEFAULT_TECH_LAYER_THICKNESS * m_biuTo3Dunits;
m_solderPasteLayerThickness3DU = SOLDERPASTE_LAYER_THICKNESS * m_biuTo3Dunits;
m_trackCount = 0; m_trackCount = 0;
m_viaCount = 0; m_viaCount = 0;
@ -255,18 +266,10 @@ bool BOARD_ADAPTER::IsFootprintShown( FOOTPRINT_ATTR_T aFPAttributes ) const
} }
// !TODO: define the actual copper thickness by user from board stackup
#define COPPER_THICKNESS Millimeter2iu( 0.035 ) // for 35 um
// The solder mask layer (and silkscreen) thickness
#define TECH_LAYER_THICKNESS Millimeter2iu( 0.025 )
// The solder paste thickness is chosen bigger than the solder mask layer
// to be sure is covers the mask when overlapping.
#define SOLDERPASTE_LAYER_THICKNESS Millimeter2iu( 0.04 )
int BOARD_ADAPTER::GetHolePlatingThickness() const noexcept int BOARD_ADAPTER::GetHolePlatingThickness() const noexcept
{ {
return m_board ? m_board->GetDesignSettings().GetHolePlatingThickness() return m_board ? m_board->GetDesignSettings().GetHolePlatingThickness()
: 0.035 * PCB_IU_PER_MM; : DEFAULT_COPPER_THICKNESS;
} }
@ -335,20 +338,51 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
// Calculate the conversion to apply to all positions. // Calculate the conversion to apply to all positions.
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y ); m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
m_epoxyThickness3DU = m_board m_boardBodyThickness3DU = DEFAULT_BOARD_THICKNESS * m_biuTo3Dunits;
? m_board->GetDesignSettings().GetBoardThickness() * m_biuTo3Dunits m_frontCopperThickness3DU = DEFAULT_COPPER_THICKNESS * m_biuTo3Dunits;
: 1.6 * PCB_IU_PER_MM * m_biuTo3Dunits; m_backCopperThickness3DU = DEFAULT_COPPER_THICKNESS * m_biuTo3Dunits;
m_nonCopperLayerThickness3DU = DEFAULT_TECH_LAYER_THICKNESS * m_biuTo3Dunits;
m_solderPasteLayerThickness3DU = SOLDERPASTE_LAYER_THICKNESS * m_biuTo3Dunits;
// !TODO: use value defined by user (currently use default values by ctor if( m_board )
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits; {
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits; const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
m_solderPasteLayerThickness3DU = SOLDERPASTE_LAYER_THICKNESS * m_biuTo3Dunits;
if( bds.GetStackupDescriptor().GetCount() )
{
int thickness = 0;
for( BOARD_STACKUP_ITEM* item : bds.GetStackupDescriptor().GetList() )
{
switch( item->GetType() )
{
case BS_ITEM_TYPE_DIELECTRIC:
thickness += item->GetThickness();
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();
break;
default:
break;
}
}
m_boardBodyThickness3DU = thickness * m_biuTo3Dunits;
}
}
// Init Z position of each layer // Init Z position of each layer
// calculate z position for each copper layer // calculate z position for each copper layer
// Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31) // Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
// Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0) // Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
// all unused copper layer z position are set to 0
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0, // ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
// | | Top = Bottom + m_copperThickness // | | Top = Bottom + m_copperThickness
@ -360,24 +394,26 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
for( layer = 0; layer < m_copperLayersCount; ++layer ) for( layer = 0; layer < m_copperLayersCount; ++layer )
{ {
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f - // This approximates internal layer positions (because we're treating all the dielectric
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) ); // layers as having the same thickness). But we don't render them anyway so it doesn't
// really matter.
m_layerZcoordBottom[layer] = m_boardBodyThickness3DU / 2.0f -
(m_boardBodyThickness3DU * layer / (m_copperLayersCount - 1) );
if( layer < (m_copperLayersCount / 2) ) if( layer < (m_copperLayersCount / 2) )
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU; m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_frontCopperThickness3DU;
else else
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU; m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_backCopperThickness3DU;
} }
#define layerThicknessMargin 1.1 #define layerThicknessMargin 1.1
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin; const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
// Fill remaining unused copper layers and back layer zpos // Fill remaining unused copper layers and back layer zpos with -m_boardBodyThickness / 2.0
// with -m_epoxyThickness / 2.0
for( ; layer < MAX_CU_LAYERS; layer++ ) for( ; layer < MAX_CU_LAYERS; layer++ )
{ {
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f); m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f );
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU; m_layerZcoordTop[layer] = -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
} }
// This is the top of the copper layer thickness. // This is the top of the copper layer thickness.

View File

@ -157,39 +157,23 @@ public:
} }
/** /**
* Get the current epoxy thickness. * Get the board body thickness, including internal copper layers (in 3D units).
*
* @return epoxy thickness in 3D units.
*/ */
float GetEpoxyThickness() const noexcept float GetBoardBodyThickness() const noexcept { return m_boardBodyThickness3DU; }
{
return m_epoxyThickness3DU;
}
/** /**
* Get the current non copper layers thickness. * Get the non copper layers thickness (in 3D units).
*
* @return thickness in 3D units of non copper layers.
*/ */
float GetNonCopperLayerThickness() const noexcept float GetNonCopperLayerThickness() const noexcept { return m_nonCopperLayerThickness3DU; }
{
return m_nonCopperLayerThickness3DU;
}
/** /**
* Get the current copper layer thickness. * Get the copper layer thicknesses (in 3D units).
*
* @return thickness in 3D units of copper layers.
*/ */
float GetCopperThickness() const noexcept float GetFrontCopperThickness() const noexcept { return m_frontCopperThickness3DU; }
{ float GetBackCopperThickness() const noexcept { return m_backCopperThickness3DU; }
return m_copperThickness3DU;
}
/** /**
* Get the current copper layer thickness. * Get the hole plating thickness (NB: in BOARD UNITS!).
*
* @return thickness in board units.
*/ */
int GetHolePlatingThickness() const noexcept; int GetHolePlatingThickness() const noexcept;
@ -604,8 +588,9 @@ private:
std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordBottom; ///< Bottom (Start) Z position of std::array<float, PCB_LAYER_ID_COUNT> m_layerZcoordBottom; ///< Bottom (Start) Z position of
///< each layer in 3D units. ///< each layer in 3D units.
float m_copperThickness3DU; float m_frontCopperThickness3DU;
float m_epoxyThickness3DU; float m_backCopperThickness3DU;
float m_boardBodyThickness3DU;
float m_nonCopperLayerThickness3DU; float m_nonCopperLayerThickness3DU;
float m_solderPasteLayerThickness3DU; float m_solderPasteLayerThickness3DU;

View File

@ -533,8 +533,8 @@ void RENDER_3D_OPENGL::renderBoardBody( bool aSkipRenderHoles )
if( ogl_disp_list ) if( ogl_disp_list )
{ {
ogl_disp_list->ApplyScalePosition( -m_boardAdapter.GetEpoxyThickness() / 2.0f, ogl_disp_list->ApplyScalePosition( -m_boardAdapter.GetBoardBodyThickness() / 2.0f,
m_boardAdapter.GetEpoxyThickness() ); m_boardAdapter.GetBoardBodyThickness() );
ogl_disp_list->SetItIsTransparent( true ); ogl_disp_list->SetItIsTransparent( true );
@ -1049,41 +1049,29 @@ void RENDER_3D_OPENGL::freeAllLists()
delete m_platedPadsBack; delete m_platedPadsBack;
m_platedPadsBack = nullptr; m_platedPadsBack = nullptr;
for( MAP_OGL_DISP_LISTS::const_iterator ii = m_outerLayerHoles.begin();
ii != m_outerLayerHoles.end(); for( const std::pair<const PCB_LAYER_ID, OPENGL_RENDER_LIST*> entry : m_outerLayerHoles )
++ii ) delete entry.second;
{
OPENGL_RENDER_LIST* pLayerDispList = static_cast<OPENGL_RENDER_LIST*>( ii->second );
delete pLayerDispList;
}
m_outerLayerHoles.clear(); m_outerLayerHoles.clear();
for( MAP_OGL_DISP_LISTS::const_iterator ii = m_innerLayerHoles.begin(); for( const std::pair<const PCB_LAYER_ID, OPENGL_RENDER_LIST*> entry : m_innerLayerHoles )
ii != m_innerLayerHoles.end(); delete entry.second;
++ii )
{
OPENGL_RENDER_LIST* pLayerDispList = static_cast<OPENGL_RENDER_LIST*>( ii->second );
delete pLayerDispList;
}
m_innerLayerHoles.clear(); m_innerLayerHoles.clear();
for( LIST_TRIANGLES::const_iterator ii = m_triangles.begin(); ii != m_triangles.end(); ++ii ) for( LIST_TRIANGLES::const_iterator ii = m_triangles.begin(); ii != m_triangles.end(); ++ii )
{
delete *ii; delete *ii;
}
m_triangles.clear(); m_triangles.clear();
for( MAP_3DMODEL::const_iterator ii = m_3dModelMap.begin(); ii != m_3dModelMap.end(); ++ii ) for( const std::pair<const wxString&, MODEL_3D*>& entry : m_3dModelMap )
{ delete entry.second;
MODEL_3D* pointer = static_cast<MODEL_3D*>(ii->second);
delete pointer;
}
m_3dModelMap.clear(); m_3dModelMap.clear();
m_3dModelMatrixMap.clear();
delete m_board; delete m_board;
m_board = nullptr; m_board = nullptr;
@ -1267,18 +1255,29 @@ void RENDER_3D_OPENGL::renderFootprint( const FOOTPRINT* aFootprint, bool aRende
{ {
glPushMatrix(); glPushMatrix();
// FIXME: don't do this over and over again unless the std::vector<double> key = { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z,
// values have changed. cache the matrix somewhere. sM.m_Rotation.x, sM.m_Rotation.y, sM.m_Rotation.z,
glm::mat4 mtx( 1 ); sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z };
mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.z ), auto it = m_3dModelMatrixMap.find( key );
{ 0.0f, 0.0f, 1.0f } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.y ), if( it != m_3dModelMatrixMap.end() )
{ 0.0f, 1.0f, 0.0f } ); {
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.x ), glMultMatrixf( glm::value_ptr( it->second ) );
{ 1.0f, 0.0f, 0.0f } ); }
mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } ); else
glMultMatrixf( glm::value_ptr( mtx ) ); {
glm::mat4 mtx( 1 );
mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.z ), { 0.0f, 0.0f, 1.0f } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.y ), { 0.0f, 1.0f, 0.0f } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.x ), { 1.0f, 0.0f, 0.0f } );
mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } );
m_3dModelMatrixMap[ key ] = mtx;
glMultMatrixf( glm::value_ptr( mtx ) );
}
if( aRenderTransparentOnly ) if( aRenderTransparentOnly )
{ {

View File

@ -41,10 +41,8 @@
#include <map> #include <map>
typedef std::map< PCB_LAYER_ID, OPENGL_RENDER_LIST* > MAP_OGL_DISP_LISTS; typedef std::map< PCB_LAYER_ID, OPENGL_RENDER_LIST* > MAP_OGL_DISP_LISTS;
typedef std::list<TRIANGLE_DISPLAY_LIST* > LIST_TRIANGLES; typedef std::list<TRIANGLE_DISPLAY_LIST* > LIST_TRIANGLES;
typedef std::map< wxString, MODEL_3D* > MAP_3DMODEL;
#define SIZE_OF_CIRCLE_TEXTURE 1024 #define SIZE_OF_CIRCLE_TEXTURE 1024
@ -208,7 +206,9 @@ private:
OPENGL_RENDER_LIST* m_vias; OPENGL_RENDER_LIST* m_vias;
OPENGL_RENDER_LIST* m_padHoles; OPENGL_RENDER_LIST* m_padHoles;
MAP_3DMODEL m_3dModelMap; // Caches
std::map< wxString, MODEL_3D* > m_3dModelMap;
std::map< std::vector<double>, glm::mat4 > m_3dModelMatrixMap;
BOARD_ITEM* m_currentRollOverItem; BOARD_ITEM* m_currentRollOverItem;

View File

@ -654,11 +654,11 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
{ {
createItemsFromContainer( m_boardAdapter.GetPlatedPadsFront(), F_Cu, &m_materials.m_Copper, createItemsFromContainer( m_boardAdapter.GetPlatedPadsFront(), F_Cu, &m_materials.m_Copper,
m_boardAdapter.m_CopperColor, m_boardAdapter.m_CopperColor,
m_boardAdapter.GetCopperThickness() * 0.1f ); m_boardAdapter.GetFrontCopperThickness() * 0.1f );
createItemsFromContainer( m_boardAdapter.GetPlatedPadsBack(), B_Cu, &m_materials.m_Copper, createItemsFromContainer( m_boardAdapter.GetPlatedPadsBack(), B_Cu, &m_materials.m_Copper,
m_boardAdapter.m_CopperColor, m_boardAdapter.m_CopperColor,
-m_boardAdapter.GetCopperThickness() * 0.1f ); -m_boardAdapter.GetBackCopperThickness() * 0.1f );
} }
if( !aOnlyLoadCopperAndShapes ) if( !aOnlyLoadCopperAndShapes )
@ -952,10 +952,10 @@ void RENDER_3D_RAYTRACE::insertHole( const PCB_VIA* aVia )
aVia->LayerPair( &top_layer, &bottom_layer ); aVia->LayerPair( &top_layer, &bottom_layer );
float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer ) float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
+ m_boardAdapter.GetCopperThickness(); + m_boardAdapter.GetFrontCopperThickness();
float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer ) float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
- m_boardAdapter.GetCopperThickness(); - m_boardAdapter.GetBackCopperThickness();
const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(), const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
-aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() ); -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
@ -1003,10 +1003,10 @@ void RENDER_3D_RAYTRACE::insertHole( const PAD* aPad )
CONST_LIST_OBJECT2D antiOutlineIntersectionList; CONST_LIST_OBJECT2D antiOutlineIntersectionList;
const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu ) const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
+ m_boardAdapter.GetCopperThickness() * 0.99f; + m_boardAdapter.GetFrontCopperThickness() * 0.99f;
const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu ) const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
- m_boardAdapter.GetCopperThickness() * 0.99f; - m_boardAdapter.GetBackCopperThickness() * 0.99f;
if( drillsize.x == drillsize.y ) // usual round hole if( drillsize.x == drillsize.y ) // usual round hole
{ {

View File

@ -603,6 +603,10 @@ public:
*/ */
void SetCopperLayerCount( int aNewLayerCount ); void SetCopperLayerCount( int aNewLayerCount );
/**
* The full thickness of the board including copper and masks.
* @return
*/
inline int GetBoardThickness() const { return m_boardThickness; } inline int GetBoardThickness() const { return m_boardThickness; }
inline void SetBoardThickness( int aThickness ) { m_boardThickness = aThickness; } inline void SetBoardThickness( int aThickness ) { m_boardThickness = aThickness; }

View File

@ -1386,6 +1386,7 @@ unsigned int DIALOG_NET_INSPECTOR::calculateViaLength( const PCB_TRACK* aTrack )
else else
{ {
int dielectricLayers = bds.GetCopperLayerCount() - 1; int dielectricLayers = bds.GetCopperLayerCount() - 1;
// FIXME: not all dielectric layers are the same thickness!
int layerThickness = bds.GetBoardThickness() / dielectricLayers; int layerThickness = bds.GetBoardThickness() / dielectricLayers;
int effectiveBottomLayer; int effectiveBottomLayer;