61 const float aaa = aTransparency * aTransparency * aTransparency;
64 float ca = 1.0f - aTransparency;
65 ca = 1.00f - 1.05f * ca * ca * ca;
67 return glm::max( glm::min( aGrayColorValue * ca + aaa, 1.0f ), 0.0f );
73#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
84 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_refractions );
86 m_boardAdapter.m_Cfg->m_Render.raytrace_recursivelevel_reflections );
104 const SFVEC3F copperSpecularLinear =
110 SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
117 SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
129 0.10f * 128.0f, 0.0f, 0.0f );
135 SFVEC3F( 0.0f ),
SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
141 const float solderMask_gray =
151 const float minSolderMaskShininess = 0.85f * 128.0f;
152 const float maxSolderMaskShininess = 512.0f;
153 const float solderMaskShininess = minSolderMaskShininess
154 + ( maxSolderMaskShininess - minSolderMaskShininess ) * ( 1.0f - solderMask_gray );
157 const float solderMaskReflection = glm::clamp( solderMask_gray * 0.3f, 0.02f, 0.16f );
162 SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.30f, 1.0f ) ), solderMaskShininess,
163 solderMask_transparency, solderMaskReflection );
166 m_materials.m_SolderMask.SetRefractionRayCount( 1 );
187 (
SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
188 0.10f * 128.0f, 1.0f, 0.50f );
190 m_materials.m_Floor.SetReflectionRecursionCount( 1 );
195 float aZMin,
float aZMax,
const MATERIAL* aMaterial,
210 aDstContainer.
Add( objPtr );
217 aDstContainer.
Add( objPtr );
229 aDstContainer.
Add( objPtr );
238 aDstContainer.
Add( objPtr );
249 float aLayerZOffset )
251 if( aContainer2d ==
nullptr )
258 if( listObject2d.size() == 0 )
261 for(
const OBJECT_2D* object2d_A : listObject2d )
269 object2d_B =
new std::vector<const OBJECT_2D*>();
279 if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
287 for(
const OBJECT_2D* hole2d : intersecting )
288 object2d_B->push_back( hole2d );
298 if( !throughHoleOuter.
GetList().empty() )
304 for(
const OBJECT_2D* hole2d : intersecting )
305 object2d_B->push_back( hole2d );
310 auto clipCutouts = [
this, &object2d_A, &object2d_B](
const BVH_CONTAINER_2D& cutouts )
312 if( !cutouts.GetList().empty() )
315 cutouts.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
317 for(
const OBJECT_2D* cutout : intersecting )
318 object2d_B->push_back( cutout );
322 if( aLayer_id ==
F_Cu )
328 else if( aLayer_id ==
B_Cu )
343 for(
const OBJECT_2D* obj : intersecting )
344 object2d_B->push_back( obj );
350 && ( ( aLayer_id ==
B_SilkS && mapLayers.find(
B_Mask ) != mapLayers.end() )
351 || ( aLayer_id ==
F_SilkS && mapLayers.find(
F_Mask ) != mapLayers.end() ) ) )
359 if( containerMaskLayer2d )
362 for(
const OBJECT_2D* obj2d : intersecting )
363 object2d_B->push_back( obj2d );
366 if( object2d_B->empty() )
414 if( !aOnlyLoadCopperAndShapes )
420 m_camera.SetBoardLookAtPos( camera_pos );
435 if( aStop.stop_requested() )
440 if( aOnlyLoadCopperAndShapes )
453 std::bitset<LAYER_3D_END> layerFlags =
m_boardAdapter.GetVisibleLayers();
455 if( !aOnlyLoadCopperAndShapes )
457 const int outlineCount =
m_boardAdapter.GetBoardPoly().OutlineCount();
459 if( outlineCount > 0 )
461 float divFactor = 0.0f;
478 for(
int ii = 0; ii < antiboardPoly.
OutlineCount(); ii++ )
489 for(
int ii = 0; ii < boardPolyCopy.
OutlineCount(); ii++ )
500 for(
const OBJECT_2D* object2d_A : listObjects )
502 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
512 for(
const OBJECT_2D* hole : intersecting )
514 if( object2d_A->Intersects( hole->GetBBox() ) )
515 object2d_B->push_back( hole );
520 auto addCutoutsFromContainer =
523 if( !aContainer.GetList().empty() )
526 aContainer.GetIntersectingObjects( object2d_A->GetBBox(),
529 for(
const OBJECT_2D* cutout : intersecting )
531 if( object2d_A->Intersects( cutout->GetBBox() ) )
532 object2d_B->push_back( cutout );
537 addCutoutsFromContainer(
m_boardAdapter.GetFrontCounterboreCutouts() );
538 addCutoutsFromContainer(
m_boardAdapter.GetBackCounterboreCutouts() );
539 addCutoutsFromContainer(
m_boardAdapter.GetFrontCountersinkCutouts() );
540 addCutoutsFromContainer(
m_boardAdapter.GetBackCountersinkCutouts() );
545 if( layerHolesMap.find(
F_Cu ) != layerHolesMap.end() )
552 for(
const OBJECT_2D* hole2d : intersecting )
554 if( object2d_A->Intersects( hole2d->GetBBox() ) )
555 object2d_B->push_back( hole2d );
559 if( layerHolesMap.find(
B_Cu ) != layerHolesMap.end() )
566 for(
const OBJECT_2D* hole2d : intersecting )
568 if( object2d_A->Intersects( hole2d->GetBBox() ) )
569 object2d_B->push_back( hole2d );
580 for(
const OBJECT_2D* obj : intersecting )
581 object2d_B->push_back( obj );
584 if( object2d_B->empty() )
629 for(
const OBJECT_2D* hole2d : holeList )
639 if( !intersecting.empty() )
643 switch( hole2d->GetObjectType() )
647 const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
676 if( aOnlyLoadCopperAndShapes )
683 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
766 else if(
m_boardAdapter.m_Cfg->m_Render.differentiate_plated_copper )
768 layerColor =
SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
783 if( aStop.stop_requested() )
799 if( !aOnlyLoadCopperAndShapes )
811 for(
const std::pair<const PCB_LAYER_ID, BVH_CONTAINER_2D*>& entry :
839 const float zLayerMin =
m_boardAdapter.GetLayerBottomZPos( layer_id );
840 const float zLayerMax =
m_boardAdapter.GetLayerTopZPos( layer_id );
845 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
855 for(
const OBJECT_2D* hole : intersecting )
857 if( object2d_A->Intersects( hole->GetBBox() ) )
858 object2d_B->push_back( hole );
864 if( !container2d->
GetList().empty() )
870 for(
const OBJECT_2D* obj : intersecting )
871 object2d_B->push_back( obj );
874 if( object2d_B->empty() )
884 materialLayer, layerColor );
898 object2d_A->GetBoardItem() );
915#ifdef PRINT_STATISTICS_3D_VIEWER
917 int64_t stats_startLoad3DmodelsTime = stats_endConvertTime;
922 if( aOnlyLoadCopperAndShapes )
930 if( aStop.stop_requested() )
933#ifdef PRINT_STATISTICS_3D_VIEWER
937 if( !aOnlyLoadCopperAndShapes )
946 boardBBox.
Scale( 3.0f );
952 containerBBox.
Scale( 1.3f );
957 const float minZ = glm::min( containerBBox.
Min().z, boardBBox.
Min().z );
961 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
965 +
SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
981 newTriangle1->
SetColor( floorColor );
982 newTriangle2->
SetColor( floorColor );
985 const float maxZ = glm::max( containerBBox.
Max().z, boardBBox.
Max().z );
1001 newTriangle3->
SetColor( floorColor );
1002 newTriangle4->
SetColor( floorColor );
1016 return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
1017 && ( aSource.b < ( 1.0f / 255.0f ) ) );
1030 if( !IsColorZero( cameraLightColor ) )
1035 if( !IsColorZero( topLightColor ) )
1042 if( !IsColorZero( bottomLightColor ) )
1046 bottomLightColor ) );
1049 for(
size_t i = 0; i <
m_boardAdapter.m_Cfg->m_Render.raytrace_lightColor.size(); ++i )
1054 if( !IsColorZero( lightColor ) )
1075 / -
m_camera.GetCameraInitPos().z );
1077 if( min_zoom > max_zoom )
1078 std::swap( min_zoom, max_zoom );
1080 float zoom_ratio = max_zoom / min_zoom;
1084 steps -=
static_cast<int>( ceil( log( zoom_ratio ) / log( 1.26f ) ) );
1085 steps = std::max( steps, 0 );
1088 float increased_zoom = pow( 1.26f, steps / 2 );
1089 max_zoom *= increased_zoom;
1090 min_zoom /= increased_zoom;
1095 min_zoom = std::min( min_zoom, 1.0f );
1101 if( aStop.stop_requested() )
1105 std::unique_ptr<ACCELERATOR_3D> accelerator =
1116 double calculation_time = (double) (
GetRunningMicroSecs() - stats_startReloadTime ) / 1e6;
1118 if( aOnlyLoadCopperAndShapes )
1120 m_activityReporter->Report( wxString::Format(
_(
"Hit-test scene ready in %.3f s" ), calculation_time ) );
1124 m_activityReporter->Report( wxString::Format(
_(
"Reload time %.3f s" ), calculation_time ) );
1132 float aInnerRadius,
float aDepth,
1133 float aSurfaceZ,
bool aIsFront )
1135 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1138 if( platingThickness <= 0.0f || aInnerRadius <= 0.0f || aDepth <= 0.0f )
1141 const float outerRadius = aInnerRadius + platingThickness;
1142 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1143 const float zMin = std::min( aSurfaceZ, zOther );
1144 const float zMax = std::max( aSurfaceZ, zOther );
1146 RING_2D* ring =
new RING_2D( aCenter, aInnerRadius, outerRadius, aSource );
1158 float aTopInnerRadius,
1159 float aBottomInnerRadius,
1160 float aSurfaceZ,
float aDepth,
1163 const float platingThickness =
m_boardAdapter.GetHolePlatingThickness()
1166 if( platingThickness <= 0.0f || aTopInnerRadius <= 0.0f || aBottomInnerRadius <= 0.0f
1172 const float topOuterRadius = aTopInnerRadius + platingThickness;
1173 const float bottomOuterRadius = aBottomInnerRadius + platingThickness;
1175 const float zOther = aIsFront ? ( aSurfaceZ - aDepth ) : ( aSurfaceZ + aDepth );
1176 const float zTop = std::max( aSurfaceZ, zOther );
1177 const float zBot = std::min( aSurfaceZ, zOther );
1179 if( topOuterRadius <= 0.0f || bottomOuterRadius <= 0.0f )
1182 const float largestDiameter = 2.0f * std::max( aTopInnerRadius, aBottomInnerRadius );
1183 unsigned int segments = std::max( 12u,
m_boardAdapter.GetCircleSegmentCount( largestDiameter ) );
1202 auto makePoint = [&](
float radius,
float angle,
float z )
1205 aCenter.y + sinf( angle ) *
radius,
1209 const float step = 2.0f * glm::pi<float>() / (float) segments;
1211 SFVEC3F innerTopPrev = makePoint( aTopInnerRadius, 0.0f, zTop );
1212 SFVEC3F innerBotPrev = makePoint( aBottomInnerRadius, 0.0f, zBot );
1213 SFVEC3F outerTopPrev = makePoint( topOuterRadius, 0.0f, zTop );
1214 SFVEC3F outerBotPrev = makePoint( bottomOuterRadius, 0.0f, zBot );
1216 const SFVEC3F innerTopFirst = innerTopPrev;
1217 const SFVEC3F innerBotFirst = innerBotPrev;
1218 const SFVEC3F outerTopFirst = outerTopPrev;
1219 const SFVEC3F outerBotFirst = outerBotPrev;
1221 for(
unsigned int i = 1; i <= segments; ++i )
1223 const float angle = ( i == segments ) ? 0.0f : step * i;
1225 const SFVEC3F innerTopCurr = ( i == segments ) ? innerTopFirst
1226 : makePoint( aTopInnerRadius, angle, zTop );
1227 const SFVEC3F innerBotCurr = ( i == segments ) ? innerBotFirst
1228 : makePoint( aBottomInnerRadius, angle, zBot );
1229 const SFVEC3F outerTopCurr = ( i == segments ) ? outerTopFirst
1230 : makePoint( topOuterRadius, angle, zTop );
1231 const SFVEC3F outerBotCurr = ( i == segments ) ? outerBotFirst
1232 : makePoint( bottomOuterRadius, angle, zBot );
1235 addQuad( innerTopPrev, innerTopCurr, innerBotCurr, innerBotPrev );
1238 addQuad( outerTopPrev, outerBotPrev, outerBotCurr, outerTopCurr );
1241 addQuad( outerTopPrev, outerTopCurr, innerTopCurr, innerTopPrev );
1244 addQuad( outerBotPrev, innerBotPrev, innerBotCurr, outerBotCurr );
1246 innerTopPrev = innerTopCurr;
1247 innerBotPrev = innerBotCurr;
1248 outerTopPrev = outerTopCurr;
1249 outerBotPrev = outerBotCurr;
1260 const int platingThickness =
m_boardAdapter.GetHolePlatingThickness();
1261 const float platingThickness3d = platingThickness * unitScale;
1275 const float holeDiameter =
via->GetDrillValue() * unitScale;
1276 const float holeInnerRadius = holeDiameter / 2.0f;
1277 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1281 via->LayerPair( &topLayer, &bottomLayer );
1283 const float viaZTop =
m_boardAdapter.GetLayerBottomZPos( topLayer );
1284 const float viaZBot =
m_boardAdapter.GetLayerBottomZPos( bottomLayer );
1287 const auto secondaryDrillSize =
via->GetSecondaryDrillSize();
1289 if( secondaryDrillSize.has_value() && secondaryDrillSize.value() > 0 )
1291 const float backdrillRadius = secondaryDrillSize.value() * 0.5f * unitScale;
1293 if( backdrillRadius > holeOuterRadius )
1299 const float secEndZ =
m_boardAdapter.GetLayerBottomZPos( secEnd );
1301 float plugZTop, plugZBot;
1303 if( secStart ==
F_Cu )
1316 if( plugZTop > plugZBot )
1331 const auto frontMode =
via->GetFrontPostMachining();
1333 if( frontMode.has_value()
1337 const float frontRadius =
via->GetFrontPostMachiningSize() * 0.5f * unitScale;
1338 const float frontDepth =
via->GetFrontPostMachiningDepth() * unitScale;
1340 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1343 const float pmBottomZ = viaZTop - frontDepth;
1344 const float plugZBot = viaZBot;
1346 if( pmBottomZ > plugZBot )
1353 if( angleRad < 0.01f )
1356 float radialDiff = frontRadius - holeOuterRadius;
1357 float innerHeight = radialDiff / tanf( angleRad );
1358 float totalHeight = pmBottomZ - plugZBot;
1360 if( innerHeight > totalHeight )
1361 innerHeight = totalHeight;
1363 float zInnerTop = plugZBot + innerHeight;
1367 holeOuterRadius, frontRadius );
1373 if( zInnerTop > plugZBot )
1399 const auto backMode =
via->GetBackPostMachining();
1401 if( backMode.has_value()
1405 const float backRadius =
via->GetBackPostMachiningSize() * 0.5f * unitScale;
1406 const float backDepth =
via->GetBackPostMachiningDepth() * unitScale;
1408 if( backRadius > holeOuterRadius && backDepth > 0 )
1411 const float plugZTop = viaZTop;
1412 const float pmTopZ = viaZBot + backDepth;
1414 if( plugZTop > pmTopZ )
1421 if( angleRad < 0.01f )
1424 float radialDiff = backRadius - holeOuterRadius;
1425 float innerHeight = radialDiff / tanf( angleRad );
1426 float totalHeight = plugZTop - pmTopZ;
1428 if( innerHeight > totalHeight )
1429 innerHeight = totalHeight;
1431 float zInnerBot = plugZTop - innerHeight;
1435 backRadius, holeOuterRadius );
1441 if( zInnerBot < plugZTop )
1470 for(
const PAD*
pad : footprint->Pads() )
1475 if( !
pad->HasHole() )
1481 const SFVEC2F padCenter(
pad->GetPosition().x * unitScale,
1482 -
pad->GetPosition().y * unitScale );
1483 const float holeInnerRadius =
pad->GetDrillSize().x * 0.5f * unitScale;
1484 const float holeOuterRadius = holeInnerRadius + platingThickness3d;
1486 const float padZTop = boardZTop;
1487 const float padZBot = boardZBot;
1490 const auto frontMode =
pad->GetFrontPostMachining();
1492 if( frontMode.has_value()
1496 const float frontRadius =
pad->GetFrontPostMachiningSize() * 0.5f * unitScale;
1497 const float frontDepth =
pad->GetFrontPostMachiningDepth() * unitScale;
1499 if( frontRadius > holeOuterRadius && frontDepth > 0 )
1501 const float pmBottomZ = padZTop - frontDepth;
1502 const float plugZBot = padZBot;
1504 if( pmBottomZ > plugZBot )
1511 if( angleRad < 0.01f )
1514 float radialDiff = frontRadius - holeOuterRadius;
1515 float innerHeight = radialDiff / tanf( angleRad );
1516 float totalHeight = pmBottomZ - plugZBot;
1518 if( innerHeight > totalHeight )
1519 innerHeight = totalHeight;
1521 float zInnerTop = plugZBot + innerHeight;
1525 holeOuterRadius, frontRadius );
1531 if( zInnerTop > plugZBot )
1557 const auto backMode =
pad->GetBackPostMachining();
1559 if( backMode.has_value()
1563 const float backRadius =
pad->GetBackPostMachiningSize() * 0.5f * unitScale;
1564 const float backDepth =
pad->GetBackPostMachiningDepth() * unitScale;
1566 if( backRadius > holeOuterRadius && backDepth > 0 )
1568 const float plugZTop = padZTop;
1569 const float pmTopZ = padZBot + backDepth;
1571 if( plugZTop > pmTopZ )
1578 if( angleRad < 0.01f )
1581 float radialDiff = backRadius - holeOuterRadius;
1582 float innerHeight = radialDiff / tanf( angleRad );
1583 float totalHeight = plugZTop - pmTopZ;
1585 if( innerHeight > totalHeight )
1586 innerHeight = totalHeight;
1588 float zInnerBot = plugZTop - innerHeight;
1592 backRadius, holeOuterRadius );
1598 if( zInnerBot < plugZTop )
1635 aVia->
LayerPair( &top_layer, &bottom_layer );
1637 float frontDepth = 0.0f;
1638 float backDepth = 0.0f;
1656 ( radiusBUI +
m_boardAdapter.GetHolePlatingThickness() ) * unitScale, *aVia );
1667 const float holeInnerRadius = radiusBUI * unitScale;
1668 const float frontSurface = topZ + frontDepth;
1669 const float backSurface = botZ - backDepth;
1675 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1692 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1716 const bool hasHole = drillsize.
x && drillsize.
y;
1718 const bool isRoundHole = drillsize.
x == drillsize.
y;
1720 float holeInnerRadius = 0.0f;
1727 float frontDepth = 0.0f;
1728 float backDepth = 0.0f;
1747 int innerRadius = drillsize.
x / 2;
1748 int outerRadius = innerRadius +
m_boardAdapter.GetHolePlatingThickness();
1749 holeInnerRadius = innerRadius * unitScale;
1751 RING_2D* ring =
new RING_2D( holeCenter, innerRadius * unitScale,
1752 outerRadius * unitScale, *aPad );
1763 antiOutlineIntersectionList );
1766 if( !antiOutlineIntersectionList.empty() )
1769 holeCenter, innerRadius * unitScale, *aPad );
1772 holeCenter, outerRadius * unitScale, *aPad );
1773 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1774 object2d_B->push_back( innerCircle );
1783 object2d_A = itemCSG2d;
1791 if( drillsize.
x > drillsize.
y )
1793 ends_offset.
x = ( drillsize.
x - drillsize.
y ) / 2;
1794 width = drillsize.
y;
1798 ends_offset.
y = ( drillsize.
y - drillsize.
x ) / 2;
1799 width = drillsize.
x;
1809 -start.
y * unitScale ),
1811 -
end.y * unitScale ),
1812 width * unitScale, *aPad );
1816 -start.
y * unitScale ),
1818 -
end.y * unitScale ),
1820 * unitScale, *aPad );
1823 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1824 object2d_B->push_back( innerSeg );
1832 object2d_A = itemCSG2d;
1837 antiOutlineIntersectionList );
1843 std::vector<const OBJECT_2D*>* object2d_B =
new std::vector<const OBJECT_2D*>();
1853 for(
const OBJECT_2D* hole2d : intersecting )
1855 if( object2d_A->
Intersects( hole2d->GetBBox() ) )
1856 object2d_B->push_back( hole2d );
1860 for(
const OBJECT_2D* obj : antiOutlineIntersectionList )
1861 object2d_B->push_back( obj );
1863 if( object2d_B->empty() )
1893 if( object2d_A && isRoundHole )
1895 const float frontSurface = topZ + frontDepth;
1896 const float backSurface = botZ - backDepth;
1902 if( frontDepth > 0.0f && frontRadius > holeInnerRadius )
1920 if( backDepth > 0.0f && backRadius > holeInnerRadius )
1957 for(
PAD*
pad : footprint->Pads() )
1967 const glm::mat4& aFpMatrix,
bool aHasExtrudedBody,
1970 if( aHasExtrudedBody )
1977 float scaleZ = std::min( bboxW, bboxH ) * 0.5f;
1980 float offsetX = localCenter.
x /
pcbIUScale.IU_PER_MM;
1981 float offsetY = -localCenter.
y /
pcbIUScale.IU_PER_MM;
1986 SFVEC3F boxMin( offsetX - bboxW * 0.5f, offsetY - bboxH * 0.5f, 0.0f );
1987 SFVEC3F boxMax( offsetX + bboxW * 0.5f, offsetY + bboxH * 0.5f, scaleZ );
1991 for(
int i = 0; i < 8; ++i )
1993 SFVEC3F corner( ( i & 1 ) ? boxMax.x : boxMin.x, ( i & 2 ) ? boxMax.y : boxMin.y,
1994 ( i & 4 ) ? boxMax.z : boxMin.z );
1996 corners[i] =
SFVEC3F( aFpMatrix * glm::vec4( corner, 1.0f ) );
1999 static const int faces[6][4] = { { 4, 5, 7, 6 }, { 0, 2, 3, 1 }, { 0, 1, 5, 4 },
2000 { 3, 2, 6, 7 }, { 0, 4, 6, 2 }, { 1, 3, 7, 5 } };
2009 aDstContainer.
Add( triangle );
2012 for(
const int* face : faces )
2014 addTriangle( corners[face[0]], corners[face[2]], corners[face[1]] );
2015 addTriangle( corners[face[0]], corners[face[3]], corners[face[2]] );
2029 if(
chain.PointCount() < 3 )
2036 for(
int i = 0; i <
chain.PointCount(); i++ )
2039 SFVEC2F pt( (
float) a.
x * aBiuTo3d, (
float) ( -a.
y ) * aBiuTo3d );
2041 if( ( i == 0 ) || ( fabs( prevPt.x - pt.x ) > FLT_EPSILON ) || ( fabs( prevPt.y - pt.y ) > FLT_EPSILON ) )
2047 segNormals.push_back( sn );
2052 if( segNormals.size() >= 3 )
2054 std::vector<SFVEC2F> tmpNormals( segNormals.size() );
2055 unsigned int j = segNormals.size() - 1;
2057 for(
unsigned int i = 0; i < segNormals.size(); j = i++ )
2059 SFVEC2F slope = segNormals[j].m_Start - segNormals[i].m_Start;
2060 segNormals[i].m_Precalc_slope = slope;
2061 tmpNormals[i] = glm::normalize(
SFVEC2F( slope.y, -slope.x ) );
2064 j = segNormals.size() - 1;
2066 for(
unsigned int i = 0; i < segNormals.size(); j = i++ )
2068 const SFVEC2F& nBefore = tmpNormals[j];
2069 const SFVEC2F& nCur = tmpNormals[i];
2070 const SFVEC2F& nAfter = tmpNormals[( i + 1 ) % segNormals.size()];
2072 float dotBefore = glm::dot( nBefore, nCur );
2073 float dotAfter = glm::dot( nAfter, nCur );
2075 segNormals[i].m_Normals.m_Start =
2076 ( dotBefore < 0.7f ) ? nCur : glm::normalize( nBefore * dotBefore + nCur );
2077 segNormals[i].m_Normals.m_End = ( dotAfter < 0.7f ) ? nCur : glm::normalize( nAfter * dotAfter + nCur );
2080 SEGMENTS capSegments( segNormals.size() );
2082 for(
unsigned int i = 0; i < segNormals.size(); i++ )
2083 capSegments[i].m_Start = segNormals[i].m_Start;
2085 j = capSegments.size() - 1;
2087 for(
unsigned int i = 0; i < capSegments.size(); j = i++ )
2089 capSegments[i].m_inv_JY_minus_IY = 1.0f / ( capSegments[j].m_Start.y - capSegments[i].m_Start.y );
2090 capSegments[i].m_JX_minus_IX = capSegments[j].m_Start.x - capSegments[i].m_Start.x;
2094 outersAndHoles.
m_Outers.push_back( capSegments );
2096 aObjContainer.
Add(
new POLYGON_2D( segNormals, outersAndHoles, aBoardItem ) );
2102 size_t prevSize = aObjContainer.
GetList().size();
2104 added += aObjContainer.
GetList().size() - prevSize;
2130 float standoff3d = body->
m_standoff * biuTo3d;
2138 zBot = boardSurfaceZ + standoff3d + zOffset3d;
2139 zTop = zBot + bodyThickness;
2143 zTop = boardSurfaceZ - standoff3d - zOffset3d;
2144 zBot = zTop - bodyThickness;
2158 size_t prevCount = objList.size();
2169 auto it = objList.begin();
2170 std::advance( it, prevCount );
2172 for( ; it != objList.end(); ++it )
2179 aDstContainer.
Add( layerItem );
2183 if( standoff3d > 0.0f )
2191 float oppositeSurfaceZ =
m_boardAdapter.GetFootprintZPos( !isBack );
2192 float protrusion = 1.0f *
pcbIUScale.IU_PER_MM * biuTo3d;
2193 float pinZBot, pinZTop;
2197 pinZBot = oppositeSurfaceZ - protrusion;
2198 pinZTop = boardSurfaceZ + standoff3d;
2202 pinZTop = oppositeSurfaceZ + protrusion;
2203 pinZBot = boardSurfaceZ - standoff3d;
2210 size_t prevPinCount = objList.size();
2215 auto pinIt = objList.begin();
2216 std::advance( pinIt, prevPinCount );
2218 for( ; pinIt != objList.end(); ++pinIt )
2224 aDstContainer.
Add( layerItem );
2234 std::stop_token aStop )
2250 if( aStop.stop_requested() )
2253 bool hasModels = !fp->Models().empty();
2254 bool showMissing =
m_boardAdapter.m_Cfg->m_Render.show_missing_models;
2257 bool hasExtrudedBody =
false;
2259 if( fp->HasExtrudedBody() && fp->GetExtrudedBody()->m_show &&
m_boardAdapter.IsFootprintShown( fp ) )
2262 if( ( hasModels || showMissing ) &&
m_boardAdapter.IsFootprintShown( fp ) )
2264 double zpos =
m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
2268 glm::mat4 fpMatrix = glm::mat4( 1.0f );
2270 fpMatrix = glm::translate( fpMatrix,
2275 if( !fp->GetOrientation().IsZero() )
2277 fpMatrix = glm::rotate( fpMatrix, (
float) fp->GetOrientation().AsRadians(),
2278 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
2281 if( fp->IsFlipped() )
2283 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
2285 fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(),
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
2288 const double modelunit_to_3d_units_factor =
2291 fpMatrix = glm::scale(
2292 fpMatrix,
SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
2293 modelunit_to_3d_units_factor ) );
2298 wxString libraryName = fp->GetFPID().GetLibNickname();
2300 wxString footprintBasePath = wxEmptyString;
2307 std::optional<LIBRARY_TABLE_ROW*> fpRow =
2320 bool placeholderAdded =
false;
2324 if( !
model.m_Show ||
model.m_Filename.empty() )
2328 std::vector<const EMBEDDED_FILES*> embeddedFilesStack;
2329 embeddedFilesStack.push_back( fp->GetEmbeddedFiles() );
2330 embeddedFilesStack.push_back(
m_boardAdapter.GetBoard()->GetEmbeddedFiles() );
2333 std::move( embeddedFilesStack ) );
2338 glm::mat4 modelMatrix = fpMatrix;
2340 modelMatrix = glm::translate( modelMatrix,
2343 modelMatrix = glm::rotate( modelMatrix,
2344 (
float) -(
model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
2345 SFVEC3F( 0.0f, 0.0f, 1.0f ) );
2347 modelMatrix = glm::rotate( modelMatrix,
2348 (
float) -(
model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
2349 SFVEC3F( 0.0f, 1.0f, 0.0f ) );
2351 modelMatrix = glm::rotate( modelMatrix,
2352 (
float) -(
model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
2353 SFVEC3F( 1.0f, 0.0f, 0.0f ) );
2355 modelMatrix = glm::scale( modelMatrix,
2358 addModels( aDstContainer, modelPtr, modelMatrix, (
float)
model.m_Opacity,
2359 aSkipMaterialInformation, fp );
2361 else if( showMissing && !placeholderAdded )
2364 placeholderAdded =
true;
2369 if( !hasModels && showMissing )
2398 for(
unsigned int imat = 0; imat < a3DModel->
m_MaterialsSize; ++imat )
2406 float reflectionFactor = 0.0f;
2408 if( ( material.
m_Shininess - 0.35f ) > FLT_EPSILON )
2410 reflectionFactor = glm::clamp(
2411 glm::sqrt( ( material.
m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
2422 if(
m_boardAdapter.m_Cfg->m_Render.raytrace_procedural_textures )
2477 return materialVector;
2482 const glm::mat4& aModelMatrix,
float aFPOpacity,
2483 bool aSkipMaterialInformation,
BOARD_ITEM* aBoardItem )
2486 wxASSERT( a3DModel !=
nullptr );
2488 if( a3DModel ==
nullptr )
2492 wxASSERT( a3DModel->
m_Meshes !=
nullptr );
2496 if( aFPOpacity > 1.0f )
2499 if( aFPOpacity < 0.0f )
2507 if( !aSkipMaterialInformation )
2512 const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
2514 for(
unsigned int mesh_i = 0; mesh_i < a3DModel->
m_MeshesSize; ++mesh_i )
2531 float fpTransparency;
2534 if( !aSkipMaterialInformation )
2543 for(
unsigned int faceIdx = 0; faceIdx < mesh.
m_FaceIdxSize; faceIdx += 3 )
2545 const unsigned int idx0 = mesh.
m_FaceIdx[faceIdx + 0];
2546 const unsigned int idx1 = mesh.
m_FaceIdx[faceIdx + 1];
2547 const unsigned int idx2 = mesh.
m_FaceIdx[faceIdx + 2];
2564 const SFVEC3F vt0 =
SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
2568 const SFVEC3F nt0 = glm::normalize(
SFVEC3F( normalMatrix * n0 ) );
2569 const SFVEC3F nt1 = glm::normalize(
SFVEC3F( normalMatrix * n1 ) );
2570 const SFVEC3F nt2 = glm::normalize(
SFVEC3F( normalMatrix * n2 ) );
2576 aDstContainer.
Add( newTriangle );
2578 if( !aSkipMaterialInformation )
@ NORMAL
Use all material properties from model file.
@ CAD_MODE
Use a gray shading based on diffuse material.
Defines math related functions.
float NextFloatDown(float v)
float NextFloatUp(float v)
Defines math related functions.
float RGBtoGray(const SFVEC3F &aColor)
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
void ApplyExtrusionTransform(SHAPE_POLY_SET &aOutline, const EXTRUDED_3D_BODY *aBody, const VECTOR2I &aFpPos)
Apply 2D extrusion transforms (rotation, scale, offset) to an outline.
EXTRUSION_MATERIAL_PROPS GetMaterialProps(EXTRUSION_MATERIAL aMaterial, const SFVEC3F &aDiffuse)
bool GetExtrusionPinOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aPinPoly)
Get the pin outline polygons for extruded THT pin rendering.
bool GetExtrusionOutline(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aOutline, PCB_LAYER_ID aLayerOverride)
Get the extrusion outline polygon for a footprint in board coordinates.
BOX2I CalcPlaceholderLocalBox(const FOOTPRINT *aFootprint)
Calculate a local space bounding box for a placeholder 3D model.
constexpr EDA_IU_SCALE pcbIUScale
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
bool IsTriangleInRange(const unsigned int *aFaceIdx, unsigned int aTriangleIdx, unsigned int aVertexCount)
Test whether the three face indices of a triangle all reference valid vertices.
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
constexpr size_type GetWidth() const
constexpr const Vec GetCenter() const
constexpr size_type GetHeight() const
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
static const float DEFAULT_MAX_ZOOM
void Add(OBJECT_2D *aObject)
const LIST_OBJECT2D & GetList() const
void Add(OBJECT_3D *aObject)
Procedural generation of the copper normals.
void SetColor(SFVEC3F aObjColor)
A light source based only on a directional vector.
static KIGFX::COLOR4D GetDefaultColor(EXTRUSION_MATERIAL aMaterial)
EXTRUSION_MATERIAL m_material
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Make solid geometry for objects on layers.
void SetColor(SFVEC3F aObjColor)
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
A base light class to derive to implement other light classes.
Base material class that can be used to derive other material implementations.
static void SetDefaultReflectionRayCount(unsigned int aCount)
static void SetDefaultRefractionRayCount(unsigned int aCount)
static void SetDefaultRefractionRecursionCount(unsigned int aCount)
void SetGenerator(const MATERIAL_GENERATOR *aGenerator)
float GetTransparency() const
static void SetDefaultReflectionRecursionCount(unsigned int aCount)
static OBJECT_2D_STATS & Instance()
virtual bool Intersects(const BBOX_2D &aBBox) const =0
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
const BBOX_2D & GetBBox() const
const BOARD_ITEM & GetBoardItem() const
OBJECT_2D_TYPE GetObjectType() const
static OBJECT_3D_STATS & Instance()
void SetMaterial(const MATERIAL *aMaterial)
void SetModelTransparency(float aModelTransparency)
void SetBoardItem(BOARD_ITEM *aBoardItem)
POST_MACHINING_PROPS & FrontPostMachining()
POST_MACHINING_PROPS & BackPostMachining()
int GetBackPostMachiningSize() const
VECTOR2I GetPosition() const override
VECTOR2I GetDrillSize() const
int GetFrontPostMachiningSize() const
int GetFrontPostMachiningDepth() const
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetFrontPostMachining() const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetBackPostMachining() const
int GetBackPostMachiningDepth() const
const VECTOR2I & GetStart() const
int GetFrontPostMachiningSize() const
const PADSTACK & Padstack() const
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetFrontPostMachining() const
int GetBackPostMachiningSize() const
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
std::optional< PAD_DRILL_POST_MACHINING_MODE > GetBackPostMachining() const
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Return the 2 layers used by the via (the via actually uses all layers between these 2 layers)
Procedural generation of the plastic normals.
Procedural generation of the shiny plastic normals.
Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20....
Represent a sub polygon block.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
std::shared_ptr< REPORTER > m_warningReporter
std::shared_ptr< REPORTER > m_activityReporter
BOARD_ADAPTER & m_boardAdapter
Settings reference in use for this render.
SILK_SCREEN_NORMAL m_silkScreenMaterial
struct RENDER_3D_RAYTRACE_BASE::@013206213056006125230376122042346155134272177300 m_materials
std::mutex m_hitTestMutex
Serializes hover BVH use.
void addCountersinkPlating(const SFVEC2F &aCenter, float aTopInnerRadius, float aBottomInnerRadius, float aSurfaceZ, float aDepth, bool aIsFront)
BOARD_NORMAL m_boardMaterial
CONTAINER_3D m_objectContainer
std::vector< std::unique_ptr< BLINN_PHONG_MATERIAL > > m_extrusionMaterials
COPPER_NORMAL m_copperMaterial
void insertHole(const PCB_VIA *aVia)
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
static constexpr float MIN_DISTANCE_IU
PLATED_COPPER_NORMAL m_platedCopperMaterial
PLASTIC_NORMAL m_plasticMaterial
void createItemsFromContainer(const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
DIRECTIONAL_LIGHT * m_cameraLight
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
unsigned int m_convertedDummyBlockCount
bool addExtrudedBodyToRaytracer(CONTAINER_3D &aDstContainer, const FOOTPRINT *aFootprint)
void backfillPostMachine()
void addCounterborePlating(const BOARD_ITEM &aSource, const SFVEC2F &aCenter, float aInnerRadius, float aDepth, float aSurfaceZ, bool aIsFront)
CONTAINER_2D * m_outlineBoard2dObjects
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation, std::stop_token aStop={})
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
CONTAINER_2D m_containerWithObjectsToDelete
Store the list of created objects special for RT that will be clear in the end.
std::unique_ptr< ACCELERATOR_3D > m_accelerator
void addPlaceholderToRaytracer(CONTAINER_3D &aDstContainer, const FOOTPRINT *aFootprint, const glm::mat4 &aFpMatrix, bool aHasExtrudedBody=false, float aOpacity=1.0f)
MODEL_MATERIALS * getModelMaterial(const S3DMODEL *a3DModel)
SOLDER_MASK_NORMAL m_solderMaskMaterial
void addModels(CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
std::list< LIGHT * > m_lights
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
void createObject(CONTAINER_3D &aDstContainer, const OBJECT_2D *aObject2D, float aZMin, float aZMax, const MATERIAL *aMaterial, const SFVEC3F &aObjColor)
Create one or more 3D objects form a 2D object and Z positions.
unsigned int m_converted2dRoundSegmentCount
void Reload(bool aOnlyLoadCopperAndShapes, std::stop_token aStop={})
void SetColor(SFVEC3F aObjColor)
Cache for storing the 3D shapes.
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Procedural generation of the solder mask.
void SetColor(const SFVEC3F &aColor)
A vertical truncated cone with different radii at top and bottom.
void SetColor(SFVEC3F aObjColor)
A plane that is parallel to XY plane.
void SetColor(SFVEC3F aObjColor)
std::list< OBJECT_2D * > LIST_OBJECT2D
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
#define UNITS3D_TO_UNITSPCB
Implements a model viewer canvas.
Declaration of the eda_3d_viewer class.
A truncated cone for raytracing, used for countersink visualization.
int MapPCBLayerTo3DLayer(PCB_LAYER_ID aLayer)
@ LAYER_3D_SOLDERMASK_TOP
@ LAYER_3D_SOLDERMASK_BOTTOM
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
PAD_DRILL_POST_MACHINING_MODE
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
static wxColor copperColor(220, 180, 30)
void ConvertPolygonToBlocks(const SHAPE_POLY_SET &aMainPath, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (PO...
std::vector< SEGMENT_WITH_NORMALS > SEGMENTS_WIDTH_NORMALS
List used to test ray2d intersections.
std::vector< POLYSEGMENT > SEGMENTS
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
static size_t addOutlineToRaytracerObjects(CONTAINER_2D &aObjContainer, const SHAPE_POLY_SET &aOutline, float aBiuTo3d, const BOARD_ITEM &aBoardItem)
static float TransparencyControl(float aGrayColorValue, float aTransparency)
Perform an interpolation step to easy control the transparency based on the gray color value and tran...
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
const SFVEC2F & Min() const
const SFVEC2F & Max() const
Manage a bounding box defined by two SFVEC3F min max points.
SFVEC3F GetCenter() const
Return the center point of the bounding box.
const SFVEC3F & Min() const
Return the minimum vertex pointer.
const SFVEC3F & Max() const
Return the maximum vertex pointer.
bool IsInitialized() const
Check if this bounding box is already initialized.
void Scale(float aScale)
Scales a bounding box by its center.
bool clip_silk_on_via_annuli
bool subtract_mask_from_silk
Handle a subset of a polygon.
std::vector< SEGMENTS > m_Outers
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
Store the a model based on meshes and materials.
SMATERIAL * m_Materials
The materials list of this model.
unsigned int m_MeshesSize
Number of meshes in the array.
SMESH * m_Meshes
The meshes list of this model.
unsigned int m_MaterialsSize
Number of materials in the material array.
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Per-vertex normal/color/texcoors structure.
unsigned int * m_FaceIdx
Triangle Face Indexes.
SFVEC3F * m_Normals
Vertex normals array.
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
unsigned int m_VertexSize
Number of vertex in the arrays.
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
SFVEC3F * m_Color
Vertex color array, can be NULL.
SFVEC3F * m_Positions
Vertex position array.
const SHAPE_LINE_CHAIN chain
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
Implement a triangle ray intersection based on article http://www.flipcode.com/archives/Raytracing_To...
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
VECTOR2< int32_t > VECTOR2I