3D-Viewer: raytracing, implement an outline board cut
it cut board items that are outside and on the edge of the board. Allows castellations render.
This commit is contained in:
parent
18fdcbe61e
commit
b06db80151
|
@ -170,7 +170,7 @@ class BOARD_ADAPTER
|
|||
|
||||
/**
|
||||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
* @return thickness in 3d units
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const noexcept
|
||||
{
|
||||
|
@ -179,7 +179,7 @@ class BOARD_ADAPTER
|
|||
|
||||
/**
|
||||
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||
* @return thickness in 3d unities of non copperlayers
|
||||
* @return thickness in 3d units of non copperlayers
|
||||
*/
|
||||
float GetNonCopperLayerThickness3DU() const noexcept
|
||||
{
|
||||
|
@ -188,7 +188,7 @@ class BOARD_ADAPTER
|
|||
|
||||
/**
|
||||
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||
* @return thickness in 3d unities of copperlayers
|
||||
* @return thickness in 3d units of copperlayers
|
||||
*/
|
||||
float GetCopperThickness3DU() const noexcept
|
||||
{
|
||||
|
@ -197,13 +197,13 @@ class BOARD_ADAPTER
|
|||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
* @return thickness in board unities
|
||||
* @return thickness in board units
|
||||
*/
|
||||
int GetHolePlatingThicknessBIU() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
* @return size in BIU units
|
||||
*/
|
||||
wxSize GetBoardSizeBIU() const noexcept
|
||||
{
|
||||
|
@ -211,8 +211,8 @@ class BOARD_ADAPTER
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
* @brief GetBoardPosBIU - Get the board center
|
||||
* @return position in BIU units
|
||||
*/
|
||||
wxPoint GetBoardPosBIU() const noexcept
|
||||
{
|
||||
|
@ -336,7 +336,7 @@ class BOARD_ADAPTER
|
|||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
* @return position in 3D units
|
||||
*/
|
||||
float GetLayerTopZpos3DU( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
|
@ -346,7 +346,7 @@ class BOARD_ADAPTER
|
|||
/**
|
||||
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
* @return position in 3D units
|
||||
*/
|
||||
float GetLayerBottomZpos3DU( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
|
|
|
@ -59,6 +59,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const CBBOX2D &GetBBox() const
|
||||
{
|
||||
return m_bbox;
|
||||
}
|
||||
|
||||
void Clear();
|
||||
|
||||
const LIST_OBJECT2D &GetList() const { return m_objects; }
|
||||
|
|
|
@ -370,6 +370,21 @@ void C3D_RENDER_RAYTRACING::createItemsFromContainer( const CBVHCONTAINER2D *aCo
|
|||
}
|
||||
}
|
||||
|
||||
if( !m_antioutlineBoard2dObjects->GetList().empty() )
|
||||
{
|
||||
CONST_LIST_OBJECT2D intersectionList;
|
||||
|
||||
m_antioutlineBoard2dObjects->GetListObjectsIntersects(
|
||||
object2d_A->GetBBox(), intersectionList );
|
||||
|
||||
if( !intersectionList.empty() )
|
||||
{
|
||||
for( const COBJECT2D *obj : intersectionList )
|
||||
{
|
||||
object2d_B->push_back( obj );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MAP_CONTAINER_2D& mapLayers = m_boardAdapter.GetMapLayers();
|
||||
|
||||
|
@ -440,6 +455,8 @@ void C3D_RENDER_RAYTRACING::createItemsFromContainer( const CBVHCONTAINER2D *aCo
|
|||
}
|
||||
}
|
||||
|
||||
extern void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline );
|
||||
|
||||
void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
||||
REPORTER* aWarningReporter,
|
||||
bool aOnlyLoadCopperAndShapes )
|
||||
|
@ -470,8 +487,10 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
delete m_outlineBoard2dObjects;
|
||||
delete m_antioutlineBoard2dObjects;
|
||||
|
||||
m_outlineBoard2dObjects = new CCONTAINER2D;
|
||||
m_antioutlineBoard2dObjects = new CBVHCONTAINER2D;
|
||||
|
||||
if( !aOnlyLoadCopperAndShapes )
|
||||
{
|
||||
|
@ -488,6 +507,29 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
divFactor = m_boardAdapter.GetStats_Med_Hole_Diameter3DU() * 8.0f;
|
||||
|
||||
SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly();
|
||||
|
||||
// Calculate an antiboard outline
|
||||
|
||||
SHAPE_POLY_SET antiboardPoly;
|
||||
|
||||
buildBoardBoundingBoxPoly( m_boardAdapter.GetBoard(), antiboardPoly );
|
||||
|
||||
antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
|
||||
antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < antiboardPoly.OutlineCount(); iOutlinePolyIdx++ )
|
||||
{
|
||||
Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
antiboardPoly,
|
||||
*m_antioutlineBoard2dObjects,
|
||||
m_boardAdapter.BiuTo3Dunits(),
|
||||
divFactor,
|
||||
*dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ),
|
||||
iOutlinePolyIdx );
|
||||
}
|
||||
|
||||
m_antioutlineBoard2dObjects->BuildBVH();
|
||||
|
||||
boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ )
|
||||
|
@ -537,6 +579,23 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
}
|
||||
}
|
||||
|
||||
if( !m_antioutlineBoard2dObjects->GetList().empty() )
|
||||
{
|
||||
CONST_LIST_OBJECT2D intersectionList;
|
||||
|
||||
m_antioutlineBoard2dObjects->GetListObjectsIntersects(
|
||||
object2d_A->GetBBox(),
|
||||
intersectionList );
|
||||
|
||||
if( !intersectionList.empty() )
|
||||
{
|
||||
for( const COBJECT2D *obj : intersectionList )
|
||||
{
|
||||
object2d_B->push_back( obj );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( object2d_B->empty() )
|
||||
{
|
||||
delete object2d_B;
|
||||
|
@ -545,14 +604,6 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
|
||||
if( object2d_B == CSGITEM_EMPTY )
|
||||
{
|
||||
#if 0
|
||||
create_3d_object_from( m_object_container, object2d_A,
|
||||
m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ),
|
||||
m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ),
|
||||
&m_materials.m_EpoxyBoard,
|
||||
g_epoxyColor );
|
||||
#else
|
||||
|
||||
CLAYERITEM *objPtr = new CLAYERITEM( object2d_A,
|
||||
m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ),
|
||||
m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) );
|
||||
|
@ -560,7 +611,6 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
|
||||
objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) );
|
||||
m_object_container.Add( objPtr );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -601,6 +651,21 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
{
|
||||
const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
|
||||
|
||||
if( !m_antioutlineBoard2dObjects->GetList().empty() )
|
||||
{
|
||||
CONST_LIST_OBJECT2D intersectionList;
|
||||
|
||||
m_antioutlineBoard2dObjects->GetListObjectsIntersects(
|
||||
hole2d->GetBBox(), intersectionList );
|
||||
|
||||
if( !intersectionList.empty() )
|
||||
{
|
||||
// Do not add cylinder if it intersects the edge of the board
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch( hole2d->GetObjectType() )
|
||||
{
|
||||
case OBJECT2D_TYPE::FILLED_CIRCLE:
|
||||
|
@ -642,7 +707,7 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
|
|||
if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
|
||||
continue;
|
||||
|
||||
// Mask kayers are not processed here because they are a special case
|
||||
// Mask layers are not processed here because they are a special case
|
||||
if( (layer_id == B_Mask) || (layer_id == F_Mask) )
|
||||
continue;
|
||||
|
||||
|
@ -1099,6 +1164,8 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
|
|||
if( !hasHole )
|
||||
return;
|
||||
|
||||
CONST_LIST_OBJECT2D antiOutlineIntersectionList;
|
||||
|
||||
const float topZ = m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) +
|
||||
m_boardAdapter.GetCopperThickness3DU();
|
||||
|
||||
|
@ -1112,6 +1179,7 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
|
|||
|
||||
int innerRadius = drillsize.x / 2;
|
||||
int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThicknessBIU();
|
||||
|
||||
CRING2D *ring = new CRING2D( center,
|
||||
innerRadius * m_boardAdapter.BiuTo3Dunits(),
|
||||
outerRadius * m_boardAdapter.BiuTo3Dunits(),
|
||||
|
@ -1120,6 +1188,40 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
|
|||
m_containerWithObjectsToDelete.Add( ring );
|
||||
|
||||
object2d_A = ring;
|
||||
|
||||
// If the object (ring) is intersected by an antioutline board,
|
||||
// it will use instease a CSG of two circles.
|
||||
if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
|
||||
{
|
||||
|
||||
m_antioutlineBoard2dObjects->GetListObjectsIntersects(
|
||||
object2d_A->GetBBox(),
|
||||
antiOutlineIntersectionList );
|
||||
}
|
||||
|
||||
if( !antiOutlineIntersectionList.empty() )
|
||||
{
|
||||
CFILLEDCIRCLE2D *innerCircle = new CFILLEDCIRCLE2D( center,
|
||||
innerRadius * m_boardAdapter.BiuTo3Dunits(),
|
||||
*aPad );
|
||||
|
||||
CFILLEDCIRCLE2D *outterCircle = new CFILLEDCIRCLE2D( center,
|
||||
outerRadius * m_boardAdapter.BiuTo3Dunits(),
|
||||
*aPad );
|
||||
std::vector<const COBJECT2D *> *object2d_B = new std::vector<const COBJECT2D *>();
|
||||
object2d_B->push_back( innerCircle );
|
||||
|
||||
CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( outterCircle,
|
||||
object2d_B,
|
||||
CSGITEM_FULL,
|
||||
*aPad );
|
||||
|
||||
m_containerWithObjectsToDelete.Add( itemCSG2d );
|
||||
m_containerWithObjectsToDelete.Add( innerCircle );
|
||||
m_containerWithObjectsToDelete.Add( outterCircle );
|
||||
|
||||
object2d_A = itemCSG2d;
|
||||
}
|
||||
}
|
||||
else // Oblong hole
|
||||
{
|
||||
|
@ -1173,6 +1275,14 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
|
|||
m_containerWithObjectsToDelete.Add( outerSeg );
|
||||
|
||||
object2d_A = itemCSG2d;
|
||||
|
||||
if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
|
||||
{
|
||||
|
||||
m_antioutlineBoard2dObjects->GetListObjectsIntersects(
|
||||
object2d_A->GetBBox(),
|
||||
antiOutlineIntersectionList );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1204,6 +1314,14 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
|
|||
}
|
||||
}
|
||||
|
||||
if( !antiOutlineIntersectionList.empty() )
|
||||
{
|
||||
for( const COBJECT2D *obj : antiOutlineIntersectionList )
|
||||
{
|
||||
object2d_B->push_back( obj );
|
||||
}
|
||||
}
|
||||
|
||||
if( object2d_B->empty() )
|
||||
{
|
||||
delete object2d_B;
|
||||
|
|
|
@ -61,6 +61,7 @@ C3D_RENDER_RAYTRACING::C3D_RENDER_RAYTRACING( BOARD_ADAPTER& aAdapter, CCAMERA&
|
|||
m_oldWindowsSize.x = 0;
|
||||
m_oldWindowsSize.y = 0;
|
||||
m_outlineBoard2dObjects = NULL;
|
||||
m_antioutlineBoard2dObjects = NULL;
|
||||
m_firstHitinfo = NULL;
|
||||
m_shaderBuffer = NULL;
|
||||
m_camera_light = NULL;
|
||||
|
@ -85,6 +86,9 @@ C3D_RENDER_RAYTRACING::~C3D_RENDER_RAYTRACING()
|
|||
delete m_outlineBoard2dObjects;
|
||||
m_outlineBoard2dObjects = NULL;
|
||||
|
||||
delete m_antioutlineBoard2dObjects;
|
||||
m_antioutlineBoard2dObjects = NULL;
|
||||
|
||||
delete[] m_shaderBuffer;
|
||||
m_shaderBuffer = NULL;
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ private:
|
|||
CCONTAINER2D m_containerWithObjectsToDelete;
|
||||
|
||||
CCONTAINER2D *m_outlineBoard2dObjects;
|
||||
CBVHCONTAINER2D *m_antioutlineBoard2dObjects;
|
||||
|
||||
CGENERICACCELERATOR *m_accelerator;
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
|
|||
float currentRayDist;
|
||||
SFVEC2F currentRayPos;
|
||||
SFVEC2F currentNormal;
|
||||
RAYSEG2D currentRay = aSegRay;
|
||||
|
||||
if( m_objectA->IsPointInside( aSegRay.m_Start ) )
|
||||
{
|
||||
|
@ -103,18 +104,20 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
|
|||
if( !m_objectA->Intersect( aSegRay, ¤tRayDist, ¤tNormal ) )
|
||||
return false;
|
||||
|
||||
currentRayPos = aSegRay.atNormalized( NextFloatDown( currentRayDist ) );
|
||||
currentRayPos = aSegRay.atNormalized( currentRayDist + 0.01f );
|
||||
|
||||
currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End );
|
||||
}
|
||||
|
||||
currentRayDist = 0.0f;
|
||||
|
||||
//wxASSERT( (currentRayDist >= 0.0f) && (currentRayDist <= 1.0f) );
|
||||
|
||||
|
||||
// move through the union of subtracted regions
|
||||
bool hitSubRegion = false;
|
||||
|
||||
if( m_objectB )
|
||||
{
|
||||
while(1)
|
||||
for( unsigned int l = 0; l < 4; ++l )
|
||||
{
|
||||
bool wasInsideSubVol = false;
|
||||
|
||||
|
@ -123,60 +126,41 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
|
|||
{
|
||||
if( ((const COBJECT2D *)(*m_objectB)[i])->IsPointInside( currentRayPos ) )
|
||||
{
|
||||
hitSubRegion = true;
|
||||
|
||||
// ray point is inside a subtracted region, so move it to the end of the
|
||||
// subtracted region
|
||||
float hitDist;
|
||||
if( !((const COBJECT2D *)(*m_objectB)[i])->Intersect( aSegRay,
|
||||
SFVEC2F tmpNormal;
|
||||
if( !((const COBJECT2D *)(*m_objectB)[i])->Intersect( currentRay,
|
||||
&hitDist,
|
||||
¤tNormal ) )
|
||||
&tmpNormal ) )
|
||||
return false; // ray hit main object but did not leave subtracted volume
|
||||
|
||||
wxASSERT( hitDist <= 1.0f );
|
||||
|
||||
if( hitDist > currentRayDist )
|
||||
currentRayDist = hitDist;
|
||||
|
||||
currentRayDist += 0.0001f;
|
||||
|
||||
// ray has left this specific subtracted object volume
|
||||
currentRayPos = aSegRay.atNormalized( currentRayDist );
|
||||
|
||||
if( m_objectA->IsPointInside( currentRayPos ) )
|
||||
{
|
||||
wasInsideSubVol = true;
|
||||
|
||||
break;
|
||||
currentRayPos = currentRay.atNormalized( glm::min( hitDist + 0.0001f, 1.0f ) );
|
||||
|
||||
currentRayDist = 0.0001f;
|
||||
|
||||
currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End );
|
||||
|
||||
currentNormal = tmpNormal * -1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !wasInsideSubVol )
|
||||
break; // ray has succesfully passed through all subtracted regions
|
||||
|
||||
if( currentRayDist >= 1.0f )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ray is not inside any of the specific subtracted regions
|
||||
|
||||
if( hitSubRegion )
|
||||
{
|
||||
//if( !m_objectA->IsPointInside( currentRayPos ) )
|
||||
// return false; // ray got right through the hole in the object!
|
||||
|
||||
currentNormal *= -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ray just hit the main object without hitting any holes
|
||||
}
|
||||
|
||||
*aNormalOut = currentNormal;
|
||||
*aOutT = currentRayDist;
|
||||
|
||||
*aOutT = glm::min( glm::max( 1.0f - glm::length( currentRayPos - aSegRay.m_End ) / aSegRay.m_Length, 0.0f ), 1.0f );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ bool CPOLYGONBLOCK2D::IsPointInside( const SFVEC2F &aPoint ) const
|
|||
// At this moment, the point is not inside a hole, so check if it is
|
||||
// inside the polygon
|
||||
for( unsigned int i = 0; i < m_outers_and_holes.m_Outers.size(); i++ )
|
||||
if( !m_outers_and_holes.m_Outers.empty() )
|
||||
if( !m_outers_and_holes.m_Outers[i].empty() )
|
||||
if( polygon_IsPointInside( m_outers_and_holes.m_Outers[i], aPoint ) )
|
||||
return true;
|
||||
|
||||
|
|
Loading…
Reference in New Issue