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>
#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_MaskColors;
CUSTOM_COLORS_LIST BOARD_ADAPTER::g_PasteColors;
@ -91,12 +100,14 @@ BOARD_ADAPTER::BOARD_ADAPTER() :
m_throughHoleOds.Clear();
m_throughHoleAnnularRings.Clear();
m_copperLayersCount = -1;
m_epoxyThickness3DU = 0.0f;
m_copperThickness3DU = 0.0f;
m_nonCopperLayerThickness3DU = 0.0f;
m_solderPasteLayerThickness3DU = 0.0f;
m_copperLayersCount = 2;
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_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
{
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.
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
m_epoxyThickness3DU = m_board
? m_board->GetDesignSettings().GetBoardThickness() * m_biuTo3Dunits
: 1.6 * PCB_IU_PER_MM * m_biuTo3Dunits;
// !TODO: use value defined by user (currently use default values by ctor
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits;
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits;
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;
if( m_board )
{
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
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
// 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 front (top layer) (layer id = 0)
// all unused copper layer z position are set to 0
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
// | | Top = Bottom + m_copperThickness
@ -360,24 +394,26 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR
for( layer = 0; layer < m_copperLayersCount; ++layer )
{
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
// This approximates internal layer positions (because we're treating all the dielectric
// 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) )
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU;
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_frontCopperThickness3DU;
else
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU;
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_backCopperThickness3DU;
}
#define layerThicknessMargin 1.1
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
// Fill remaining unused copper layers and back layer zpos
// with -m_epoxyThickness / 2.0
// Fill remaining unused copper layers and back layer zpos with -m_boardBodyThickness / 2.0
for( ; layer < MAX_CU_LAYERS; layer++ )
{
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU;
m_layerZcoordBottom[layer] = -( m_boardBodyThickness3DU / 2.0f );
m_layerZcoordTop[layer] = -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
}
// This is the top of the copper layer thickness.

View File

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

View File

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

View File

@ -41,10 +41,8 @@
#include <map>
typedef std::map< PCB_LAYER_ID, OPENGL_RENDER_LIST* > MAP_OGL_DISP_LISTS;
typedef std::list<TRIANGLE_DISPLAY_LIST* > LIST_TRIANGLES;
typedef std::map< wxString, MODEL_3D* > MAP_3DMODEL;
#define SIZE_OF_CIRCLE_TEXTURE 1024
@ -208,7 +206,9 @@ private:
OPENGL_RENDER_LIST* m_vias;
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;

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,
m_boardAdapter.m_CopperColor,
m_boardAdapter.GetCopperThickness() * 0.1f );
m_boardAdapter.GetFrontCopperThickness() * 0.1f );
createItemsFromContainer( m_boardAdapter.GetPlatedPadsBack(), B_Cu, &m_materials.m_Copper,
m_boardAdapter.m_CopperColor,
-m_boardAdapter.GetCopperThickness() * 0.1f );
-m_boardAdapter.GetBackCopperThickness() * 0.1f );
}
if( !aOnlyLoadCopperAndShapes )
@ -952,10 +952,10 @@ void RENDER_3D_RAYTRACE::insertHole( const PCB_VIA* aVia )
aVia->LayerPair( &top_layer, &bottom_layer );
float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
+ m_boardAdapter.GetCopperThickness();
+ m_boardAdapter.GetFrontCopperThickness();
float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
- m_boardAdapter.GetCopperThickness();
- m_boardAdapter.GetBackCopperThickness();
const SFVEC2F center = SFVEC2F( aVia->GetStart().x * 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 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 )
- m_boardAdapter.GetCopperThickness() * 0.99f;
- m_boardAdapter.GetBackCopperThickness() * 0.99f;
if( drillsize.x == drillsize.y ) // usual round hole
{

View File

@ -603,6 +603,10 @@ public:
*/
void SetCopperLayerCount( int aNewLayerCount );
/**
* The full thickness of the board including copper and masks.
* @return
*/
inline int GetBoardThickness() const { return m_boardThickness; }
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
{
int dielectricLayers = bds.GetCopperLayerCount() - 1;
// FIXME: not all dielectric layers are the same thickness!
int layerThickness = bds.GetBoardThickness() / dielectricLayers;
int effectiveBottomLayer;