3D-Viewer: implement nonplated copper on raytracing

This commit is contained in:
Mario Luzeiro 2020-09-07 12:38:05 +01:00 committed by Jon Evans
parent 1ab968e72f
commit d7a95951e1
2 changed files with 200 additions and 170 deletions

View File

@ -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<const COBJECT2D *>(*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<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY;
object2d_B = new std::vector<const COBJECT2D*>();
// 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<const CBVHCONTAINER2D *>(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<const COBJECT2D *>(*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<const COBJECT2D *>(*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<const CBVHCONTAINER2D*>( 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<const COBJECT2D*>( *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<const CBVHCONTAINER2D *>(ii->second);
const LIST_OBJECT2D &listObject2d = container2d->GetList();
const CBVHCONTAINER2D* container2d = static_cast<const CBVHCONTAINER2D*>(ii->second);
for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
itemOnLayer != listObject2d.end();
++itemOnLayer )
{
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*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<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY;
object2d_B = new std::vector<const COBJECT2D*>();
// 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<const CBVHCONTAINER2D *>(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<const COBJECT2D *>(*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<const COBJECT2D *>(*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<const CBVHCONTAINER2D*>( 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<const COBJECT2D*>( *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

View File

@ -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;