From 1ab968e72fcc15ca504bd4fa0aeb12473684193e Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Sun, 6 Sep 2020 20:09:43 +0100 Subject: [PATCH] 3D-Viewer: render different materials plated and non plated copper implement on OpenGL --- 3d-viewer/3d_canvas/board_adapter.cpp | 6 + 3d-viewer/3d_canvas/board_adapter.h | 30 +++- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 13 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 64 ++++++- .../c3d_render_createscene_ogl_legacy.cpp | 164 ++++++++++-------- .../c3d_render_ogl_legacy.cpp | 93 +++++++++- .../c3d_render_ogl_legacy.h | 15 +- ...board_items_to_polygon_shape_transform.cpp | 13 +- pcbnew/class_module.h | 8 +- 9 files changed, 323 insertions(+), 83 deletions(-) diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index b29a052c21..cfe297215a 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -119,6 +119,12 @@ BOARD_ADAPTER::BOARD_ADAPTER() : m_SilkScreenColorTop = SFVEC4F( 0.9, 0.9, 0.9, 1.0 ); m_SilkScreenColorBot = SFVEC4F( 0.9, 0.9, 0.9, 1.0 ); m_CopperColor = SFVEC4F( 0.75, 0.61, 0.23, 1.0 ); + + m_platedpads_container2D_F_Cu = nullptr; + m_platedpads_container2D_B_Cu = nullptr; + + m_F_Cu_PlatedPads_poly = nullptr; + m_B_Cu_PlatedPads_poly = nullptr; } diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index 66bc29cec0..49096378dd 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -362,6 +362,16 @@ class BOARD_ADAPTER return m_layers_container2D; } + const CBVHCONTAINER2D* GetPlatedPads_Front() const noexcept + { + return m_platedpads_container2D_F_Cu; + } + + const CBVHCONTAINER2D* GetPlatedPads_Back() const noexcept + { + return m_platedpads_container2D_B_Cu; + } + /** * @brief GetMapLayersHoles -Get the map of container that have the holes per layer * @return the map containers of holes from this board @@ -536,6 +546,16 @@ class BOARD_ADAPTER return m_layers_poly; } + const SHAPE_POLY_SET *GetPolyPlatedPads_Front() + { + return m_F_Cu_PlatedPads_poly; + } + + const SHAPE_POLY_SET *GetPolyPlatedPads_Back() + { + return m_B_Cu_PlatedPads_poly; + } + const MAP_POLY &GetPolyMapHoles_Inner() const noexcept { return m_layers_inner_holes_poly; @@ -571,7 +591,9 @@ class BOARD_ADAPTER CGENERICCONTAINER2D *aDstContainer, PCB_LAYER_ID aLayerId, int aInflateValue, - bool aSkipNPTHPadsWihNoCopper ); + bool aSkipNPTHPadsWihNoCopper, + bool aSkipPlatedPads, + bool aSkipNonPlatedPads ); void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule, CGENERICCONTAINER2D *aDstContainer, @@ -685,6 +707,9 @@ private: /// It contains polygon contours for each layer MAP_POLY m_layers_poly; + SHAPE_POLY_SET* m_F_Cu_PlatedPads_poly; + SHAPE_POLY_SET* m_B_Cu_PlatedPads_poly; + /// It contains polygon contours for holes of each layer (outer holes) MAP_POLY m_layers_outer_holes_poly; @@ -712,6 +737,9 @@ private: /// It contains the 2d elements of each layer MAP_CONTAINER_2D m_layers_container2D; + CBVHCONTAINER2D* m_platedpads_container2D_F_Cu; + CBVHCONTAINER2D* m_platedpads_container2D_B_Cu; + /// It contains the holes per each layer MAP_CONTAINER_2D m_layers_holes2D; diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index f390c78c26..72f48e81ec 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -459,7 +459,9 @@ void BOARD_ADAPTER::AddPadsShapesWithClearanceToContainer( const MODULE* aModule CGENERICCONTAINER2D *aDstContainer, PCB_LAYER_ID aLayerId, int aInflateValue, - bool aSkipNPTHPadsWihNoCopper ) + bool aSkipNPTHPadsWihNoCopper, + bool aSkipPlatedPads, + bool aSkipNonPlatedPads ) { for( D_PAD* pad : aModule->Pads() ) { @@ -495,6 +497,15 @@ void BOARD_ADAPTER::AddPadsShapesWithClearanceToContainer( const MODULE* aModule } } + const bool isPlated = ( ( aLayerId == F_Cu ) && pad->IsPadOnLayer( F_Mask ) ) || + ( ( aLayerId == B_Cu ) && pad->IsPadOnLayer( B_Mask ) ); + + if( aSkipPlatedPads && isPlated ) + continue; + + if( aSkipNonPlatedPads && !isPlated ) + continue; + wxSize margin( aInflateValue, aInflateValue ); switch( aLayerId ) diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 3fef3c0dbb..abdfb6d60f 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -63,6 +63,9 @@ void BOARD_ADAPTER::destroyLayers() m_layers_poly.clear(); } + delete m_F_Cu_PlatedPads_poly; + delete m_B_Cu_PlatedPads_poly; + if( !m_layers_inner_holes_poly.empty() ) { for( auto& poly : m_layers_inner_holes_poly ) @@ -87,6 +90,9 @@ void BOARD_ADAPTER::destroyLayers() m_layers_container2D.clear(); } + delete m_platedpads_container2D_F_Cu; + delete m_platedpads_container2D_B_Cu; + if( !m_layers_holes2D.empty() ) { for( auto& poly : m_layers_holes2D ) @@ -197,6 +203,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) } } + m_F_Cu_PlatedPads_poly = new SHAPE_POLY_SET; + m_B_Cu_PlatedPads_poly = new SHAPE_POLY_SET; + + m_platedpads_container2D_F_Cu = new CBVHCONTAINER2D; + m_platedpads_container2D_B_Cu = new CBVHCONTAINER2D; + if( aStatusReporter ) aStatusReporter->Report( _( "Create tracks and vias" ) ); @@ -512,7 +524,9 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) layerContainer, curr_layer_id, 0, - true ); + true, + true, + false ); // Micro-wave modules may have items on copper layers AddGraphicsShapesWithClearanceToContainer( module, @@ -522,6 +536,26 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) } } + // ADD PLATED PADS + for( MODULE* module : m_board->Modules() ) + { + AddPadsShapesWithClearanceToContainer( module, + m_platedpads_container2D_F_Cu, + F_Cu, + 0, + true, + false, + true ); + + AddPadsShapesWithClearanceToContainer( module, + m_platedpads_container2D_B_Cu, + B_Cu, + 0, + true, + false, + true ); + } + // Add modules PADs poly contourns (vertical outlines) if( GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) && ( m_render_engine == RENDER_ENGINE::OPENGL_LEGACY ) ) @@ -538,13 +572,31 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) // Note: NPTH pads are not drawn on copper layers when the pad // has same shape as its hole module->TransformPadsShapesWithClearanceToPolygon( curr_layer_id, *layerPoly, - 0, ARC_HIGH_DEF, true ); + 0, ARC_HIGH_DEF, true, + true, false ); transformGraphicModuleEdgeToPolygonSet( module, curr_layer_id, *layerPoly ); } } + + // ADD PLATED PADS contourns + for( auto module : m_board->Modules() ) + { + module->TransformPadsShapesWithClearanceToPolygon( F_Cu, *m_F_Cu_PlatedPads_poly, + 0, ARC_HIGH_DEF, true, + false, true ); + + //transformGraphicModuleEdgeToPolygonSet( module, F_Cu, *m_F_Cu_PlatedPads_poly ); + + module->TransformPadsShapesWithClearanceToPolygon( B_Cu, *m_B_Cu_PlatedPads_poly, + 0, ARC_HIGH_DEF, true, + false, true ); + + //transformGraphicModuleEdgeToPolygonSet( module, B_Cu, *m_B_Cu_PlatedPads_poly ); + } } + // Add graphic item on copper layers to object containers for( PCB_LAYER_ID curr_layer_id : layer_id ) { @@ -735,6 +787,12 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) while( threadsFinished < parallelThreadCount ) std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) ); + + if( m_F_Cu_PlatedPads_poly ) + m_F_Cu_PlatedPads_poly->Simplify( SHAPE_POLY_SET::PM_FAST ); + + if( m_B_Cu_PlatedPads_poly ) + m_B_Cu_PlatedPads_poly->Simplify( SHAPE_POLY_SET::PM_FAST ); } // Simplify holes polygon contours @@ -884,6 +942,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) else { AddPadsShapesWithClearanceToContainer( module, layerContainer, curr_layer_id, 0, + false, + false, false ); } diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp index a3d7716c09..4805c85726 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp @@ -334,6 +334,84 @@ CLAYERS_OGL_DISP_LISTS *C3D_RENDER_OGL_LEGACY::generate_holes_display_list( } +CLAYERS_OGL_DISP_LISTS* C3D_RENDER_OGL_LEGACY::generateLayerListFromContainer( const CBVHCONTAINER2D *aContainer, + const SHAPE_POLY_SET *aPolyList, + PCB_LAYER_ID aLayerId ) +{ + if( aContainer == nullptr ) + return nullptr; + + const LIST_OBJECT2D &listObject2d = aContainer->GetList(); + + if( listObject2d.size() == 0 ) + return nullptr; + + float layer_z_bot = 0.0f; + float layer_z_top = 0.0f; + + get_layer_z_pos( aLayerId, layer_z_top, layer_z_bot ); + + // Calculate an estimation for the nr of triangles based on the nr of objects + unsigned int nrTrianglesEstimation = listObject2d.size() * 8; + + CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation ); + + // store in a list so it will be latter deleted + m_triangles.push_back( layerTriangles ); + + // Load the 2D (X,Y axis) component of shapes + for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin(); + itemOnLayer != listObject2d.end(); + ++itemOnLayer ) + { + const COBJECT2D *object2d_A = static_cast(*itemOnLayer); + + switch( object2d_A->GetObjectType() ) + { + case OBJECT2D_TYPE::FILLED_CIRCLE: + add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A, + layerTriangles, layer_z_top, layer_z_bot ); + break; + + case OBJECT2D_TYPE::POLYGON4PT: + add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A, + layerTriangles, layer_z_top, layer_z_bot ); + break; + + case OBJECT2D_TYPE::RING: + add_object_to_triangle_layer( (const CRING2D *)object2d_A, + layerTriangles, layer_z_top, layer_z_bot ); + break; + + case OBJECT2D_TYPE::TRIANGLE: + add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A, + layerTriangles, layer_z_top, layer_z_bot ); + break; + + case OBJECT2D_TYPE::ROUNDSEG: + add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A, + layerTriangles, layer_z_top, layer_z_bot ); + break; + + default: + wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented"); + break; + } + } + + if( aPolyList ) + if( aPolyList->OutlineCount() > 0 ) + layerTriangles->AddToMiddleContourns( *aPolyList, layer_z_bot, layer_z_top, + m_boardAdapter.BiuTo3Dunits(), false ); + // Create display list + // ///////////////////////////////////////////////////////////////////// + return new CLAYERS_OGL_DISP_LISTS( *layerTriangles, + m_ogl_circle_texture, + layer_z_bot, + layer_z_top ); +} + + void C3D_RENDER_OGL_LEGACY::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter ) { m_reloadRequested = false; @@ -516,6 +594,8 @@ void C3D_RENDER_OGL_LEGACY::reload( REPORTER* aStatusReporter, REPORTER* aWarnin if( aStatusReporter ) aStatusReporter->Report( _( "Load OpenGL: layers" ) ); + const MAP_POLY &map_poly = m_boardAdapter.GetPolyMap(); + for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin(); ii != m_boardAdapter.GetMapLayers().end(); ++ii ) @@ -526,82 +606,26 @@ void C3D_RENDER_OGL_LEGACY::reload( REPORTER* aStatusReporter, REPORTER* aWarnin continue; const CBVHCONTAINER2D *container2d = static_cast(ii->second); - const LIST_OBJECT2D &listObject2d = container2d->GetList(); - if( listObject2d.size() == 0 ) - continue; + // Load the vertical (Z axis) component of shapes + const SHAPE_POLY_SET *aPolyList = nullptr; - float layer_z_bot = 0.0f; - float layer_z_top = 0.0f; - - get_layer_z_pos( layer_id, layer_z_top, layer_z_bot ); - - // Calculate an estimation for the nr of triangles based on the nr of objects - unsigned int nrTrianglesEstimation = listObject2d.size() * 8; - - CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation ); - - m_triangles[layer_id] = layerTriangles; - - // Load the 2D (X,Y axis) component of shapes - for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin(); - itemOnLayer != listObject2d.end(); - ++itemOnLayer ) - { - const COBJECT2D *object2d_A = static_cast(*itemOnLayer); - - switch( object2d_A->GetObjectType() ) - { - case OBJECT2D_TYPE::FILLED_CIRCLE: - add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A, - layerTriangles, layer_z_top, layer_z_bot ); - break; - - case OBJECT2D_TYPE::POLYGON4PT: - add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A, - layerTriangles, layer_z_top, layer_z_bot ); - break; - - case OBJECT2D_TYPE::RING: - add_object_to_triangle_layer( (const CRING2D *)object2d_A, - layerTriangles, layer_z_top, layer_z_bot ); - break; - - case OBJECT2D_TYPE::TRIANGLE: - add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A, - layerTriangles, layer_z_top, layer_z_bot ); - break; - - case OBJECT2D_TYPE::ROUNDSEG: - add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A, - layerTriangles, layer_z_top, layer_z_bot ); - break; - - default: - wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented"); - break; - } - } - - const MAP_POLY &map_poly = m_boardAdapter.GetPolyMap(); - - // Load the vertical (Z axis) component of shapes if( map_poly.find( layer_id ) != map_poly.end() ) { - const SHAPE_POLY_SET *polyList = map_poly.at( layer_id ); - - if( polyList->OutlineCount() > 0 ) - layerTriangles->AddToMiddleContourns( *polyList, layer_z_bot, layer_z_top, - m_boardAdapter.BiuTo3Dunits(), false ); + aPolyList = map_poly.at( layer_id ); } - // Create display list - // ///////////////////////////////////////////////////////////////////// - m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles, - m_ogl_circle_texture, - layer_z_bot, - layer_z_top ); - }// for each layer on map + CLAYERS_OGL_DISP_LISTS* oglList = generateLayerListFromContainer( container2d, aPolyList, layer_id ); + + if( oglList != nullptr ) + m_ogl_disp_lists_layers[layer_id] = oglList; + + }// for each layer on + + m_ogl_disp_lists_platedPads_F_Cu = generateLayerListFromContainer( m_boardAdapter.GetPlatedPads_Front(), + m_boardAdapter.GetPolyPlatedPads_Front(), F_Cu ); + m_ogl_disp_lists_platedPads_B_Cu = generateLayerListFromContainer( m_boardAdapter.GetPlatedPads_Back(), + m_boardAdapter.GetPolyPlatedPads_Back(), B_Cu ); // Load 3D models // ///////////////////////////////////////////////////////////////////////// diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp index e7c3df9a95..b3dacf3173 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp @@ -60,6 +60,9 @@ C3D_RENDER_OGL_LEGACY::C3D_RENDER_OGL_LEGACY( BOARD_ADAPTER& aAdapter, CCAMERA& m_triangles.clear(); m_ogl_disp_list_board = NULL; + m_ogl_disp_lists_platedPads_F_Cu = nullptr; + m_ogl_disp_lists_platedPads_B_Cu = nullptr; + m_ogl_disp_list_through_holes_outer_with_npth = NULL; m_ogl_disp_list_through_holes_outer = NULL; m_ogl_disp_list_through_holes_vias_outer = NULL; @@ -186,6 +189,7 @@ void C3D_RENDER_OGL_LEGACY::setupMaterials() { // http://devernay.free.fr/cours/opengl/materials.html + // Plated copper // Copper material mixed with the copper color m_materials.m_Copper.m_Ambient = SFVEC3F( m_boardAdapter.m_CopperColor.r * 0.1f, m_boardAdapter.m_CopperColor.g * 0.1f, @@ -206,6 +210,13 @@ void C3D_RENDER_OGL_LEGACY::setupMaterials() m_materials.m_Copper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f ); + // Non plated copper (raw copper) + m_materials.m_NonPlatedCopper.m_Ambient = SFVEC3F( 0.191f, 0.073f, 0.022f ); + m_materials.m_NonPlatedCopper.m_Diffuse = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f ); + m_materials.m_NonPlatedCopper.m_Specular = SFVEC3F( 0.256f, 0.137f, 0.086f ); + m_materials.m_NonPlatedCopper.m_Shininess = 0.1f * 128.0f; + m_materials.m_NonPlatedCopper.m_Emissive = SFVEC3F( 0.0f, 0.0f, 0.0f ); + // Paste material mixed with paste color m_materials.m_Paste.m_Ambient = SFVEC3F( m_boardAdapter.m_SolderPasteColor.r, m_boardAdapter.m_SolderPasteColor.g, @@ -496,6 +507,22 @@ void init_lights(void) glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); } +void C3D_RENDER_OGL_LEGACY::setCopperMaterial() +{ + OGL_SetMaterial( m_materials.m_NonPlatedCopper, 1.0f ); +} + +void C3D_RENDER_OGL_LEGACY::setPlatedCopperAndDepthOffset( PCB_LAYER_ID aLayer_id ) +{ + glEnable( GL_POLYGON_OFFSET_FILL ); + glPolygonOffset( -1.0f, -1.0f ); + set_layer_material( aLayer_id ); +} + +void C3D_RENDER_OGL_LEGACY::unsetDepthOffset() +{ + glDisable( GL_POLYGON_OFFSET_FILL ); +} void C3D_RENDER_OGL_LEGACY::render_board_body( bool aSkipRenderHoles ) { @@ -703,13 +730,28 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast(ii->second); - set_layer_material( layer_id ); if( (layer_id >= F_Cu) && (layer_id <= B_Cu) ) { + setCopperMaterial(); + if( skipRenderHoles ) { pLayerDispList->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments ); + + // Draw copper plated pads + + if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) && + ( m_ogl_disp_lists_platedPads_F_Cu || m_ogl_disp_lists_platedPads_B_Cu ) ) + setPlatedCopperAndDepthOffset( layer_id ); + + if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu ) + m_ogl_disp_lists_platedPads_F_Cu->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments ); + else + if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu ) + m_ogl_disp_lists_platedPads_B_Cu->DrawAllCameraCulled( m_camera.GetPos().z, drawMiddleSegments ); + + unsetDepthOffset(); } else { @@ -732,6 +774,26 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( m_ogl_disp_list_through_holes_outer, viasHolesLayer, drawMiddleSegments ); + + // Draw copper plated pads + + if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) && + ( m_ogl_disp_lists_platedPads_F_Cu || m_ogl_disp_lists_platedPads_B_Cu ) ) + setPlatedCopperAndDepthOffset( layer_id ); + + if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu ) + m_ogl_disp_lists_platedPads_F_Cu->DrawAllCameraCulledSubtractLayer( + m_ogl_disp_list_through_holes_outer, + viasHolesLayer, + drawMiddleSegments ); + else + if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu ) + m_ogl_disp_lists_platedPads_B_Cu->DrawAllCameraCulledSubtractLayer( + m_ogl_disp_list_through_holes_outer, + viasHolesLayer, + drawMiddleSegments ); + + unsetDepthOffset(); } } else @@ -740,11 +802,33 @@ bool C3D_RENDER_OGL_LEGACY::Redraw( m_ogl_disp_list_through_holes_outer, NULL, drawMiddleSegments ); + + // Draw copper plated pads + + if( ( ( layer_id == F_Cu ) || ( layer_id == B_Cu ) ) && + ( m_ogl_disp_lists_platedPads_F_Cu || m_ogl_disp_lists_platedPads_B_Cu ) ) + setPlatedCopperAndDepthOffset( layer_id ); + + if( ( layer_id == F_Cu ) && m_ogl_disp_lists_platedPads_F_Cu ) + m_ogl_disp_lists_platedPads_F_Cu->DrawAllCameraCulledSubtractLayer( + m_ogl_disp_list_through_holes_outer, + NULL, + drawMiddleSegments ); + else + if( ( layer_id == B_Cu ) && m_ogl_disp_lists_platedPads_B_Cu ) + m_ogl_disp_lists_platedPads_B_Cu->DrawAllCameraCulledSubtractLayer( + m_ogl_disp_list_through_holes_outer, + NULL, + drawMiddleSegments ); + + unsetDepthOffset(); } } } else { + set_layer_material( layer_id ); + CLAYERS_OGL_DISP_LISTS* dispListThoughHolesOuter = ( m_boardAdapter.GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) && ( ( layer_id == B_SilkS ) || ( layer_id == F_SilkS ) ) ) ? @@ -997,6 +1081,8 @@ void C3D_RENDER_OGL_LEGACY::ogl_free_all_display_lists() m_ogl_disp_lists_layers.clear(); + delete m_ogl_disp_lists_platedPads_F_Cu; + delete m_ogl_disp_lists_platedPads_B_Cu; for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers_holes_outer.begin(); ii != m_ogl_disp_lists_layers_holes_outer.end(); @@ -1019,12 +1105,11 @@ void C3D_RENDER_OGL_LEGACY::ogl_free_all_display_lists() m_ogl_disp_lists_layers_holes_inner.clear(); - for( MAP_TRIANGLES::const_iterator ii = m_triangles.begin(); + for( LIST_TRIANGLES::const_iterator ii = m_triangles.begin(); ii != m_triangles.end(); ++ii ) { - CLAYER_TRIANGLES *pointer = static_cast(ii->second); - delete pointer; + delete *ii; } m_triangles.clear(); diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h index f49ad51117..01cbac4063 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h @@ -48,7 +48,7 @@ typedef std::map< PCB_LAYER_ID, CLAYERS_OGL_DISP_LISTS* > MAP_OGL_DISP_LISTS; -typedef std::map< PCB_LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES; +typedef std::list LIST_TRIANGLES; typedef std::map< wxString, C_OGL_3DMODEL * > MAP_3DMODEL; #define SIZE_OF_CIRCLE_TEXTURE 1024 @@ -77,6 +77,8 @@ private: void ogl_free_all_display_lists(); MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers; + CLAYERS_OGL_DISP_LISTS* m_ogl_disp_lists_platedPads_F_Cu; + CLAYERS_OGL_DISP_LISTS* m_ogl_disp_lists_platedPads_B_Cu; MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer; MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_inner; CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_board; @@ -93,7 +95,7 @@ private: //CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_inner_contourn_and_caps; CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_vias_and_pad_holes_outer_contourn_and_caps; - MAP_TRIANGLES m_triangles; + LIST_TRIANGLES m_triangles; // store pointers so can be deleted latter GLuint m_ogl_circle_texture; @@ -113,6 +115,10 @@ private: float aZbot, bool aInvertFaces ); + CLAYERS_OGL_DISP_LISTS* generateLayerListFromContainer( const CBVHCONTAINER2D *aContainer, + const SHAPE_POLY_SET *aPolyList, + PCB_LAYER_ID aLayerId ); + void add_triangle_top_bot( CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, @@ -197,6 +203,10 @@ private: // Materials void setupMaterials(); + void setCopperMaterial(); + void setPlatedCopperAndDepthOffset( PCB_LAYER_ID aLayer_id ); + void unsetDepthOffset(); + struct { SMATERIAL m_Paste; @@ -204,6 +214,7 @@ private: SMATERIAL m_SilkSTop; SMATERIAL m_SolderMask; SMATERIAL m_EpoxyBoard; + SMATERIAL m_NonPlatedCopper; // raw copper SMATERIAL m_Copper; SMATERIAL m_Plastic; SMATERIAL m_GrayMaterial; diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 45efc7d66b..cc5a84babb 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -118,7 +118,9 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError, - bool aSkipNPTHPadsWihNoCopper ) const + bool aSkipNPTHPadsWihNoCopper, + bool aSkipPlatedPads, + bool aSkipNonPlatedPads ) const { for( D_PAD* pad : m_pads ) { @@ -152,6 +154,15 @@ void MODULE::TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, } } + const bool isPlated = ( ( aLayer == F_Cu ) && pad->IsPadOnLayer( F_Mask ) ) || + ( ( aLayer == B_Cu ) && pad->IsPadOnLayer( B_Mask ) ); + + if( aSkipPlatedPads && isPlated ) + continue; + + if( aSkipNonPlatedPads && !isPlated ) + continue; + wxSize clearance( aInflateValue, aInflateValue ); switch( aLayer ) diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index d0680332c1..d072a78930 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -369,10 +369,14 @@ public: * Due to diff between layers and holes, these pads must be skipped to be sure * there is no copper left on the board (for instance when creating Gerber Files or * 3D shapes). Defaults to false. + * @param aSkipPlatedPads = used on 3D-Viewer to extract plated and nontplated pads. + * @param aSkipNonPlatedPads = used on 3D-Viewer to extract plated and plated pads. */ - void TransformPadsShapesWithClearanceToPolygon( PCB_LAYER_ID aLayer, + void TransformPadsShapesWithClearanceToPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, int aMaxError = ARC_HIGH_DEF, - bool aSkipNPTHPadsWihNoCopper = false ) const; + bool aSkipNPTHPadsWihNoCopper = false, + bool aSkipPlatedPads = false, + bool aSkipNonPlatedPads = false ) const; /** * function TransformGraphicShapesWithClearanceToPolygonSet