diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index cd93a30012..81222c6ee3 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -39,6 +39,15 @@ #include +#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; + 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; - // !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_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. diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index 68095ec10c..fce13e9b3e 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -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 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; diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp index 3bc36468c3..4b3e3ba5f3 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp @@ -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( ii->second ); - delete pLayerDispList; - } + + for( const std::pair 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( ii->second ); - delete pLayerDispList; - } + for( const std::pair 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(ii->second); - delete pointer; - } + for( const std::pair& 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. - 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 } ); - glMultMatrixf( glm::value_ptr( mtx ) ); + std::vector 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::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 ) { diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.h b/3d-viewer/3d_rendering/opengl/render_3d_opengl.h index 183eebbeef..a9bd38b1c0 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.h +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.h @@ -41,10 +41,8 @@ #include - typedef std::map< PCB_LAYER_ID, OPENGL_RENDER_LIST* > MAP_OGL_DISP_LISTS; typedef std::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, glm::mat4 > m_3dModelMatrixMap; BOARD_ITEM* m_currentRollOverItem; diff --git a/3d-viewer/3d_rendering/raytracing/create_scene.cpp b/3d-viewer/3d_rendering/raytracing/create_scene.cpp index 128b3ce4e2..ac639651d1 100644 --- a/3d-viewer/3d_rendering/raytracing/create_scene.cpp +++ b/3d-viewer/3d_rendering/raytracing/create_scene.cpp @@ -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 { diff --git a/include/board_design_settings.h b/include/board_design_settings.h index f1da3763ca..ebc70eb526 100644 --- a/include/board_design_settings.h +++ b/include/board_design_settings.h @@ -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; } diff --git a/pcbnew/dialogs/dialog_net_inspector.cpp b/pcbnew/dialogs/dialog_net_inspector.cpp index 97c9a17303..a849d94efc 100644 --- a/pcbnew/dialogs/dialog_net_inspector.cpp +++ b/pcbnew/dialogs/dialog_net_inspector.cpp @@ -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;