3D-Viewer: add antiboard as a single object

improves ray transversal,
fixes previous csg operation issues.

Fixes https://gitlab.com/kicad/code/kicad/issues/6097
This commit is contained in:
Mario Luzeiro 2020-10-31 23:31:55 +00:00 committed by Wayne Stambaugh
parent b06db80151
commit 386a0bbe4a
4 changed files with 32 additions and 45 deletions

View File

@ -523,7 +523,7 @@ void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter,
antiboardPoly, antiboardPoly,
*m_antioutlineBoard2dObjects, *m_antioutlineBoard2dObjects,
m_boardAdapter.BiuTo3Dunits(), m_boardAdapter.BiuTo3Dunits(),
divFactor, -1.0f,
*dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ), *dynamic_cast<const BOARD_ITEM*>( m_boardAdapter.GetBoard() ),
iOutlinePolyIdx ); iOutlinePolyIdx );
} }
@ -1167,10 +1167,10 @@ void C3D_RENDER_RAYTRACING::insert3DPadHole( const D_PAD* aPad )
CONST_LIST_OBJECT2D antiOutlineIntersectionList; CONST_LIST_OBJECT2D antiOutlineIntersectionList;
const float topZ = m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) + const float topZ = m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) +
m_boardAdapter.GetCopperThickness3DU(); m_boardAdapter.GetCopperThickness3DU() * 0.99f;
const float botZ = m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) - const float botZ = m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) -
m_boardAdapter.GetCopperThickness3DU(); m_boardAdapter.GetCopperThickness3DU() * 0.99f;
if( drillsize.x == drillsize.y ) // usual round hole if( drillsize.x == drillsize.y ) // usual round hole
{ {

View File

@ -87,39 +87,31 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
if( m_objectA->GetObjectType() == OBJECT2D_TYPE::DUMMYBLOCK ) if( m_objectA->GetObjectType() == OBJECT2D_TYPE::DUMMYBLOCK )
return false; return false;
float currentRayDist; SFVEC2F currentRayPos = aSegRay.m_Start;
SFVEC2F currentRayPos;
SFVEC2F currentNormal; SFVEC2F currentNormal;
RAYSEG2D currentRay = aSegRay; RAYSEG2D currentRay = aSegRay;
if( m_objectA->IsPointInside( aSegRay.m_Start ) ) if( !m_objectA->IsPointInside( aSegRay.m_Start ) )
{
// start ray point off where it is now (at the origin)
currentRayDist = 0.0f;
currentRayPos = aSegRay.m_Start;
}
else
{ {
//move ray point to start of main object //move ray point to start of main object
if( !m_objectA->Intersect( aSegRay, &currentRayDist, &currentNormal ) ) float tmpRayDist;
if( !m_objectA->Intersect( aSegRay, &tmpRayDist, &currentNormal ) )
return false; return false;
currentRayPos = aSegRay.atNormalized( currentRayDist + 0.01f ); currentRayPos = aSegRay.atNormalized( tmpRayDist + 0.003f );
currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End ); currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End );
} }
currentRayDist = 0.0f;
//wxASSERT( (currentRayDist >= 0.0f) && (currentRayDist <= 1.0f) ); //wxASSERT( (currentRayDist >= 0.0f) && (currentRayDist <= 1.0f) );
// move through the union of subtracted regions // move through the union of subtracted regions
if( m_objectB ) if( m_objectB )
{ {
for( unsigned int l = 0; l < 4; ++l ) for( unsigned int l = 0; l < ( m_objectB->size() * 2 ); ++l )
{ {
bool wasInsideSubVol = false; bool wasCrossedSubVol = false;
//check against all subbed objects //check against all subbed objects
for( unsigned int i = 0; i < m_objectB->size(); ++i ) for( unsigned int i = 0; i < m_objectB->size(); ++i )
@ -137,14 +129,12 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
wxASSERT( hitDist <= 1.0f ); wxASSERT( hitDist <= 1.0f );
if( hitDist > currentRayDist ) if( hitDist > FLT_EPSILON )
{ {
wasInsideSubVol = true; wasCrossedSubVol = true;
currentRayPos = currentRay.atNormalized( glm::min( hitDist + 0.0001f, 1.0f ) ); currentRayPos = currentRay.atNormalized( glm::min( hitDist + 0.0001f, 1.0f ) );
currentRayDist = 0.0001f;
currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End ); currentRay = RAYSEG2D( currentRayPos, aSegRay.m_End );
currentNormal = tmpNormal * -1.0f; currentNormal = tmpNormal * -1.0f;
@ -152,15 +142,13 @@ bool CITEMLAYERCSG2D::Intersect( const RAYSEG2D &aSegRay,
} }
} }
if( !wasInsideSubVol ) if( !wasCrossedSubVol )
{
break; break;
}
} }
} }
*aNormalOut = currentNormal; *aNormalOut = currentNormal;
*aOutT = glm::min( glm::max( 1.0f - glm::length( currentRayPos - aSegRay.m_End ) / aSegRay.m_Length, 0.0f ), 1.0f ); *aOutT = glm::min( glm::max( glm::length( currentRayPos - aSegRay.m_Start ) / aSegRay.m_Length, 0.0f ), 1.0f );
return true; return true;
} }

View File

@ -539,16 +539,25 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
glm::normalize( (normalAfterSeg * dotAfter ) + normalSeg ); glm::normalize( (normalAfterSeg * dotAfter ) + normalSeg );
} }
if( aDivFactor == 0.0f )
aDivFactor = medOfTheSquaresSegmentLength;
SFVEC2UI grid_divisions; SFVEC2UI grid_divisions;
grid_divisions.x = (unsigned int)( (bbox.GetExtent().x / aDivFactor) );
grid_divisions.y = (unsigned int)( (bbox.GetExtent().y / aDivFactor) );
grid_divisions = glm::clamp( grid_divisions , if( aDivFactor < 0.0f)
SFVEC2UI( 1, 1 ), {
SFVEC2UI( MAX_NR_DIVISIONS, MAX_NR_DIVISIONS ) ); grid_divisions = SFVEC2UI( 1 );
}
else
{
if( aDivFactor <= FLT_EPSILON )
aDivFactor = medOfTheSquaresSegmentLength;
grid_divisions.x = (unsigned int)( (bbox.GetExtent().x / aDivFactor) );
grid_divisions.y = (unsigned int)( (bbox.GetExtent().y / aDivFactor) );
grid_divisions = glm::clamp( grid_divisions ,
SFVEC2UI( 1, 1 ),
SFVEC2UI( MAX_NR_DIVISIONS, MAX_NR_DIVISIONS ) );
}
// Calculate the steps advance of the grid // Calculate the steps advance of the grid
SFVEC2F blockAdvance; SFVEC2F blockAdvance;

View File

@ -64,7 +64,7 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
if( tBBoxStart >= aHitInfo.m_tHit ) if( tBBoxStart >= aHitInfo.m_tHit )
return false; return false;
if( fabs(tBBoxStart - tBBoxEnd) < FLT_EPSILON ) if( fabs(tBBoxStart - tBBoxEnd) <= FLT_EPSILON )
return false; return false;
const bool startedInside = m_bbox.Inside( aRay.m_Origin ); const bool startedInside = m_bbox.Inside( aRay.m_Origin );
@ -96,9 +96,6 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
} }
} }
tBBoxStart = NextFloatDown( tBBoxStart );
tBBoxEnd = NextFloatUp( tBBoxEnd );
SFVEC2F topHitPoint2d; SFVEC2F topHitPoint2d;
SFVEC2F botHitPoint2d; SFVEC2F botHitPoint2d;
@ -213,8 +210,6 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
SFVEC3F boxHitPointEnd = aRay.at( tBBoxEnd ); SFVEC3F boxHitPointEnd = aRay.at( tBBoxEnd );
SFVEC2F boxHitPointStart2D( boxHitPointStart.x, boxHitPointStart.y ); SFVEC2F boxHitPointStart2D( boxHitPointStart.x, boxHitPointStart.y );
//SFVEC2F boxHitPointStart2D( m_bbox.GetCenter().x, m_bbox.GetCenter().y );
SFVEC2F boxHitPointEnd2D( boxHitPointEnd.x, boxHitPointEnd.y ); SFVEC2F boxHitPointEnd2D( boxHitPointEnd.x, boxHitPointEnd.y );
float tOut; float tOut;
@ -223,11 +218,6 @@ bool CLAYERITEM::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const
if( m_object2d->Intersect( raySeg, &tOut, &outNormal ) ) if( m_object2d->Intersect( raySeg, &tOut, &outNormal ) )
{ {
if( tOut > 0.99f ) // Workarround for refraction artifacts on board sides
{
return false;
}
// The hitT is a hit value for the segment length 'start' - 'end', // The hitT is a hit value for the segment length 'start' - 'end',
// so it ranges from 0.0 - 1.0. We now convert it to a 3D hit position // so it ranges from 0.0 - 1.0. We now convert it to a 3D hit position
// and calculate the real hitT of the ray. // and calculate the real hitT of the ray.