From d7a95951e1fb7ab3328218f11dbe206172f89957 Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Mon, 7 Sep 2020 12:38:05 +0100 Subject: [PATCH] 3D-Viewer: implement nonplated copper on raytracing --- .../c3d_render_createscene.cpp | 364 ++++++++++-------- .../c3d_render_raytracing.h | 6 + 2 files changed, 200 insertions(+), 170 deletions(-) diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp index 6edb19292d..953e07a599 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_createscene.cpp @@ -113,8 +113,16 @@ void C3D_RENDER_RAYTRACING::setupMaterials() 0.0f, // transparency 0.0f ); + m_materials.m_NonPlatedCopper = CBLINN_PHONG_MATERIAL( + ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ),// ambient + SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive + SFVEC3F( 0.256f, 0.137f, 0.086f ), // specular + 0.1f * 128.0f, // shiness + 0.0f, // transparency + 0.0f ); + if( m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES ) ) - m_materials.m_Copper.SetNormalPerturbator( &m_copper_normal_perturbator ); + m_materials.m_NonPlatedCopper.SetNormalPerturbator( &m_copper_normal_perturbator ); m_materials.m_Paste = CBLINN_PHONG_MATERIAL( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_SolderPasteColor ) * @@ -263,6 +271,173 @@ void C3D_RENDER_RAYTRACING::create_3d_object_from( CCONTAINER& aDstContainer, } } +void C3D_RENDER_RAYTRACING::createItemsFromContainer( const CBVHCONTAINER2D *aContainer2d, + PCB_LAYER_ID aLayer_id, + const CMATERIAL *aMaterialLayer, + const SFVEC3F &aLayerColor, + float aLayerZOffset ) +{ + if( aContainer2d == nullptr ) + return; + + const LIST_OBJECT2D &listObject2d = aContainer2d->GetList(); + + if( listObject2d.size() == 0 ) + return; + + for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin(); + itemOnLayer != listObject2d.end(); + ++itemOnLayer ) + { + const COBJECT2D *object2d_A = static_cast(*itemOnLayer); + + // not yet used / implemented (can be used in future to clip the objects in the board borders + COBJECT2D *object2d_C = CSGITEM_FULL; + + std::vector *object2d_B = CSGITEM_EMPTY; + + object2d_B = new std::vector(); + + // Subtract holes but not in SolderPaste + // (can be added as an option in future) + if( !( ( aLayer_id == B_Paste ) || ( aLayer_id == F_Paste ) ) ) + { + // Check if there are any layerhole that intersects this object + // Eg: a segment is cutted by a via hole or THT hole. + // ///////////////////////////////////////////////////////////// + const MAP_CONTAINER_2D &layerHolesMap = m_boardAdapter.GetMapLayersHoles(); + + if( layerHolesMap.find(aLayer_id) != layerHolesMap.end() ) + { + MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(aLayer_id); + + const CBVHCONTAINER2D *containerLayerHoles2d = + static_cast(ii_hole->second); + + CONST_LIST_OBJECT2D intersectionList; + containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(), + intersectionList ); + + if( !intersectionList.empty() ) + { + for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer = + intersectionList.begin(); + holeOnLayer != intersectionList.end(); + ++holeOnLayer ) + { + const COBJECT2D *hole2d = static_cast(*holeOnLayer); + + //if( object2d_A->Intersects( hole2d->GetBBox() ) ) + //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) + object2d_B->push_back( hole2d ); + } + } + } + + // Check if there are any THT that intersects this object + // ///////////////////////////////////////////////////////////// + + // If we're processing a silk screen layer and the flag is set, then + // clip the silk screening at the outer edge of the annular ring, rather + // than the at the outer edge of the copper plating. + const CBVHCONTAINER2D& throughHoleOuter = + ( m_boardAdapter.GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) + && ( ( aLayer_id == B_SilkS ) || ( aLayer_id == F_SilkS ) ) ) ? + m_boardAdapter.GetThroughHole_Outer_Ring() : + m_boardAdapter.GetThroughHole_Outer(); + + if( !throughHoleOuter.GetList().empty() ) + { + CONST_LIST_OBJECT2D intersectionList; + + throughHoleOuter.GetListObjectsIntersects( + object2d_A->GetBBox(), intersectionList ); + + if( !intersectionList.empty() ) + { + for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin(); + hole != intersectionList.end(); + ++hole ) + { + const COBJECT2D *hole2d = static_cast(*hole); + + //if( object2d_A->Intersects( hole2d->GetBBox() ) ) + //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) + object2d_B->push_back( hole2d ); + } + } + } + } + + + const MAP_CONTAINER_2D& mapLayers = m_boardAdapter.GetMapLayers(); + + if( m_boardAdapter.GetFlag( FL_SUBTRACT_MASK_FROM_SILK ) && + ( ( ( aLayer_id == B_SilkS ) && + ( mapLayers.find( B_Mask ) != mapLayers.end() ) ) || + ( ( aLayer_id == F_SilkS ) && + ( mapLayers.find( F_Mask ) != mapLayers.end() ) ) ) ) + { + const PCB_LAYER_ID layerMask_id = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask; + + const CBVHCONTAINER2D *containerMaskLayer2d = + static_cast( mapLayers.at( layerMask_id ) ); + + CONST_LIST_OBJECT2D intersectionList; + + if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown + containerMaskLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(), + intersectionList ); + + if( !intersectionList.empty() ) + { + for( CONST_LIST_OBJECT2D::const_iterator objOnLayer = + intersectionList.begin(); + objOnLayer != intersectionList.end(); + ++objOnLayer ) + { + const COBJECT2D* obj2d = static_cast( *objOnLayer ); + + object2d_B->push_back( obj2d ); + } + } + } + + if( object2d_B->empty() ) + { + delete object2d_B; + object2d_B = CSGITEM_EMPTY; + } + + if( (object2d_B == CSGITEM_EMPTY) && + (object2d_C == CSGITEM_FULL) ) + { + CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, + m_boardAdapter.GetLayerBottomZpos3DU( aLayer_id ) - aLayerZOffset, + m_boardAdapter.GetLayerTopZpos3DU( aLayer_id ) + aLayerZOffset ); + objPtr->SetMaterial( aMaterialLayer ); + objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) ); + m_object_container.Add( objPtr ); + } + else + { + CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, + object2d_B, + object2d_C, + object2d_A->GetBoardItem() ); + m_containerWithObjectsToDelete.Add( itemCSG2d ); + + CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, + m_boardAdapter.GetLayerBottomZpos3DU( aLayer_id ) - aLayerZOffset, + m_boardAdapter.GetLayerTopZpos3DU( aLayer_id ) + aLayerZOffset ); + + objPtr->SetMaterial( aMaterialLayer ); + objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) ); + + m_object_container.Add( objPtr ); + } + } +} void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter ) { @@ -512,184 +687,33 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin break; default: - materialLayer = &m_materials.m_Copper; + layerColor = m_boardAdapter.GetLayerColor( layer_id ); if( m_boardAdapter.GetFlag( FL_USE_REALISTIC_MODE ) ) - layerColor = m_boardAdapter.m_CopperColor; - else - layerColor = m_boardAdapter.GetLayerColor( layer_id ); + layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f ); + + materialLayer = &m_materials.m_NonPlatedCopper; break; } - const CBVHCONTAINER2D *container2d = static_cast(ii->second); - const LIST_OBJECT2D &listObject2d = container2d->GetList(); + const CBVHCONTAINER2D* container2d = static_cast(ii->second); - for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin(); - itemOnLayer != listObject2d.end(); - ++itemOnLayer ) - { - const COBJECT2D *object2d_A = static_cast(*itemOnLayer); - - // not yet used / implemented (can be used in future to clip the objects in the board borders - COBJECT2D *object2d_C = CSGITEM_FULL; - - std::vector *object2d_B = CSGITEM_EMPTY; - - object2d_B = new std::vector(); - - // Subtract holes but not in SolderPaste - // (can be added as an option in future) - if( !( ( layer_id == B_Paste ) || ( layer_id == F_Paste ) ) ) - { - // Check if there are any layerhole that intersects this object - // Eg: a segment is cutted by a via hole or THT hole. - // ///////////////////////////////////////////////////////////// - const MAP_CONTAINER_2D &layerHolesMap = m_boardAdapter.GetMapLayersHoles(); - - if( layerHolesMap.find(layer_id) != layerHolesMap.end() ) - { - MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(layer_id); - - const CBVHCONTAINER2D *containerLayerHoles2d = - static_cast(ii_hole->second); - - CONST_LIST_OBJECT2D intersectionList; - containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(), - intersectionList ); - - if( !intersectionList.empty() ) - { - for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer = - intersectionList.begin(); - holeOnLayer != intersectionList.end(); - ++holeOnLayer ) - { - const COBJECT2D *hole2d = static_cast(*holeOnLayer); - - //if( object2d_A->Intersects( hole2d->GetBBox() ) ) - //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) - object2d_B->push_back( hole2d ); - } - } - } - - // Check if there are any THT that intersects this object - // ///////////////////////////////////////////////////////////// - - // If we're processing a silk screen layer and the flag is set, then - // clip the silk screening at the outer edge of the annular ring, rather - // than the at the outer edge of the copper plating. - const CBVHCONTAINER2D& throughHoleOuter = - ( m_boardAdapter.GetFlag( FL_CLIP_SILK_ON_VIA_ANNULUS ) - && ( ( layer_id == B_SilkS ) || ( layer_id == F_SilkS ) ) ) ? - m_boardAdapter.GetThroughHole_Outer_Ring() : - m_boardAdapter.GetThroughHole_Outer(); - - if( !throughHoleOuter.GetList().empty() ) - { - CONST_LIST_OBJECT2D intersectionList; - - throughHoleOuter.GetListObjectsIntersects( - object2d_A->GetBBox(), intersectionList ); - - if( !intersectionList.empty() ) - { - for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin(); - hole != intersectionList.end(); - ++hole ) - { - const COBJECT2D *hole2d = static_cast(*hole); - - //if( object2d_A->Intersects( hole2d->GetBBox() ) ) - //if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) ) - object2d_B->push_back( hole2d ); - } - } - } - } - - - const MAP_CONTAINER_2D& mapLayers = m_boardAdapter.GetMapLayers(); - - if( m_boardAdapter.GetFlag( FL_SUBTRACT_MASK_FROM_SILK ) && - ( ( ( layer_id == B_SilkS ) && - ( mapLayers.find( B_Mask ) != mapLayers.end() ) ) || - ( ( layer_id == F_SilkS ) && - ( mapLayers.find( F_Mask ) != mapLayers.end() ) ) ) ) - { - const PCB_LAYER_ID layerMask_id = ( layer_id == B_SilkS ) ? B_Mask : F_Mask; - - const CBVHCONTAINER2D *containerMaskLayer2d = - static_cast( mapLayers.at( layerMask_id ) ); - - CONST_LIST_OBJECT2D intersectionList; - - if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown - containerMaskLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(), - intersectionList ); - - if( !intersectionList.empty() ) - { - for( CONST_LIST_OBJECT2D::const_iterator objOnLayer = - intersectionList.begin(); - objOnLayer != intersectionList.end(); - ++objOnLayer ) - { - const COBJECT2D* obj2d = static_cast( *objOnLayer ); - - object2d_B->push_back( obj2d ); - } - } - } - - if( object2d_B->empty() ) - { - delete object2d_B; - object2d_B = CSGITEM_EMPTY; - } - - if( (object2d_B == CSGITEM_EMPTY) && - (object2d_C == CSGITEM_FULL) ) - { -#if 0 - create_3d_object_from( m_object_container, - object2d_A, - m_boardAdapter.GetLayerBottomZpos3DU( layer_id ), - m_boardAdapter.GetLayerTopZpos3DU( layer_id ), - materialLayer, - layerColor ); -#else - CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, - m_boardAdapter.GetLayerBottomZpos3DU( layer_id ), - m_boardAdapter.GetLayerTopZpos3DU( layer_id ) ); - objPtr->SetMaterial( materialLayer ); - objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); - m_object_container.Add( objPtr ); -#endif - } - else - { -#if 1 - CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, - object2d_B, - object2d_C, - object2d_A->GetBoardItem() ); - m_containerWithObjectsToDelete.Add( itemCSG2d ); - - CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, - m_boardAdapter.GetLayerBottomZpos3DU( layer_id ), - m_boardAdapter.GetLayerTopZpos3DU( layer_id ) ); - - objPtr->SetMaterial( materialLayer ); - objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); - - m_object_container.Add( objPtr ); -#endif - } - } + createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f ); }// for each layer on map + // Create plated copper + SFVEC3F layerColor_F_Cu = m_boardAdapter.GetLayerColor( F_Cu ); + SFVEC3F layerColor_B_Cu = m_boardAdapter.GetLayerColor( B_Cu ); + + if( m_boardAdapter.GetFlag( FL_USE_REALISTIC_MODE ) ) + { + layerColor_F_Cu = m_boardAdapter.m_CopperColor;; + layerColor_B_Cu = layerColor_F_Cu; + } + + createItemsFromContainer( m_boardAdapter.GetPlatedPads_Front(), F_Cu, &m_materials.m_Copper, layerColor_F_Cu, +m_boardAdapter.GetCopperThickness3DU() * 0.1f ); + createItemsFromContainer( m_boardAdapter.GetPlatedPads_Back(), B_Cu, &m_materials.m_Copper, layerColor_B_Cu, -m_boardAdapter.GetCopperThickness3DU() * 0.1f ); // Add Mask layer // Solder mask layers are "negative" layers so the elements that we have diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h index b53fe02aea..8ab3f4cb5a 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.h @@ -75,6 +75,11 @@ private: void opengl_init_pbo(); void opengl_delete_pbo(); void reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter ); + void createItemsFromContainer( const CBVHCONTAINER2D *aContainer2d, + PCB_LAYER_ID aLayer_id, + const CMATERIAL *aMaterialLayer, + const SFVEC3F &aLayerColor, + float aLayerZOffset ); void restart_render_state(); void rt_render_tracing( GLubyte* ptrPBO, REPORTER* aStatusReporter ); @@ -105,6 +110,7 @@ private: CBLINN_PHONG_MATERIAL m_SolderMask; CBLINN_PHONG_MATERIAL m_EpoxyBoard; CBLINN_PHONG_MATERIAL m_Copper; + CBLINN_PHONG_MATERIAL m_NonPlatedCopper; CBLINN_PHONG_MATERIAL m_Floor; }m_materials;