From 6bc19dbfe93629f924142bb99a8c5b3a43ba15a8 Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Fri, 4 Sep 2020 01:00:56 +0100 Subject: [PATCH] 3D-Viewer: intercect modules and cooper items show module and net information. highlight shapes when selected. --- 3d-viewer/3d_canvas/board_adapter.cpp | 11 +- 3d-viewer/3d_canvas/eda_3d_canvas.cpp | 146 +++- 3d-viewer/3d_canvas/eda_3d_canvas.h | 8 + .../c3d_render_ogl_legacy.cpp | 33 +- .../c3d_render_ogl_legacy.h | 6 +- .../c3d_render_createscene.cpp | 752 +++++++++--------- .../c3d_render_raytracing.cpp | 17 +- .../c3d_render_raytracing.h | 13 +- .../3d_render_raytracing/shapes3D/cobject.cpp | 1 + .../3d_render_raytracing/shapes3D/cobject.h | 6 + 3d-viewer/3d_rendering/ccamera.cpp | 10 +- 3d-viewer/3d_viewer/eda_3d_viewer.cpp | 2 +- 12 files changed, 613 insertions(+), 392 deletions(-) diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index 9099e3b269..2527d45586 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -425,10 +425,13 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR wxString msg; - if( !createBoardPolygon( &msg ) ) - aWarningReporter->Report( _( "Board outline is not closed: " ) + msg, RPT_SEVERITY_WARNING ); - else - aWarningReporter->Report( wxEmptyString ); + if( aWarningReporter ) + { + if( !createBoardPolygon( &msg ) ) + aWarningReporter->Report( _( "Board outline is not closed: " ) + msg, RPT_SEVERITY_WARNING ); + else + aWarningReporter->Report( wxEmptyString ); + } if( aStatusReporter ) aStatusReporter->Report( _( "Create layers" ) ); diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp index af846da9da..ecba8f3a4c 100644 --- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp +++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp @@ -36,6 +36,7 @@ #include #include <3d_rendering/3d_render_raytracing/c3d_render_raytracing.h> #include <3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h> +#include <3d_rendering/3d_render_raytracing/accelerators/cbvh_pbrt.h> #include <3d_viewer_id.h> #include #include @@ -112,7 +113,9 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow* aParent, const int* aAttribList, BOARD* m_camera( aCamera ), m_3d_render( nullptr ), m_opengl_supports_raytracing( false ), - m_render_raytracing_was_requested( false ) + m_render_raytracing_was_requested( false ), + m_accelerator3DShapes( nullptr ), + m_currentIntersectedBoardItem( nullptr ) { wxLogTrace( m_logTrace, "EDA_3D_CANVAS::EDA_3D_CANVAS" ); @@ -176,6 +179,9 @@ EDA_3D_CANVAS::~EDA_3D_CANVAS() { wxLogTrace( m_logTrace, "EDA_3D_CANVAS::~EDA_3D_CANVAS" ); + delete m_accelerator3DShapes; + m_accelerator3DShapes = NULL; + releaseOpenGL(); } @@ -462,8 +468,17 @@ void EDA_3D_CANVAS::DoRePaint() { m_3d_render->SetCurWindowSize( clientSize ); + bool reloadRaytracingForIntersectionCalculations = false; + + if( ( m_boardAdapter.RenderEngineGet() == RENDER_ENGINE::OPENGL_LEGACY ) && + m_3d_render_ogl_legacy->IsReloadRequestPending() ) + reloadRaytracingForIntersectionCalculations = true; + requested_redraw = m_3d_render->Redraw( m_mouse_was_moved || m_camera_is_moving, &activityReporter, &warningReporter ); + + if( reloadRaytracingForIntersectionCalculations ) + m_3d_render_raytracing->Reload( nullptr, nullptr, true ); } if( m_render_pivot ) @@ -659,6 +674,102 @@ void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent &event ) const wxPoint eventPosition = event.GetPosition(); m_camera.SetCurMousePosition( eventPosition ); + + if( !event.Dragging() ) + { + STATUSBAR_REPORTER activityReporter( + m_parentStatusBar, static_cast( EDA_3D_VIEWER_STATUSBAR::STATUS_TEXT ) ); + + RAY mouseRay = getRayAtCurrrentMousePosition(); + + BOARD_ITEM *intersectedBoardItem = m_3d_render_raytracing->IntersectBoardItem( mouseRay ); + + if( intersectedBoardItem ) + { + if( intersectedBoardItem != m_currentIntersectedBoardItem ) + { + m_3d_render_ogl_legacy->SetCurrentIntersectedBoardItem( intersectedBoardItem ); + m_currentIntersectedBoardItem = intersectedBoardItem; + + if( m_boardAdapter.RenderEngineGet() == RENDER_ENGINE::OPENGL_LEGACY ) + Request_refresh(); + } + + switch( intersectedBoardItem->Type() ) + { + case PCB_PAD_T: + { + D_PAD* item = dynamic_cast( intersectedBoardItem ); + + if( item ) + { + if( item->IsOnCopperLayer() ) + activityReporter.Report( wxString::Format( _( "Net %s\tNetClass %s\tPadName %s" ), + item->GetNet()->GetNetname(), + item->GetNet()->GetClassName(), + item->GetName() ) ); + } + } + break; + + case PCB_MODULE_T: + { + MODULE* module = dynamic_cast( intersectedBoardItem ); + + if( module ) + { + activityReporter.Report( module->GetReference() ); + } + } + break; + + case PCB_TRACE_T: + case PCB_VIA_T: + case PCB_ARC_T: + { + TRACK* item = dynamic_cast( intersectedBoardItem ); + + if( item ) + { + activityReporter.Report( wxString::Format( _( "Net %s\tNetClass %s" ), + item->GetNet()->GetNetname(), + item->GetNet()->GetClassName() ) ); + } + } + break; + + case PCB_ZONE_AREA_T: + { + ZONE_CONTAINER* item = dynamic_cast( intersectedBoardItem ); + + if( item ) + { + if( item->IsOnCopperLayer() ) + activityReporter.Report( wxString::Format( _( "Net %s\tNetClass %s" ), + item->GetNet()->GetNetname(), + item->GetNet()->GetClassName() ) ); + } + } + break; + + default: + break; + } + } + else + { + if( ( m_currentIntersectedBoardItem != nullptr ) && + ( m_boardAdapter.RenderEngineGet() == RENDER_ENGINE::OPENGL_LEGACY ) ) + { + m_3d_render_ogl_legacy->SetCurrentIntersectedBoardItem( nullptr ); + Request_refresh(); + + activityReporter.Report( "" ); + } + + m_currentIntersectedBoardItem = nullptr; + } + } } @@ -666,6 +777,15 @@ void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent &event ) { SetFocus(); stop_editingTimeOut_Timer(); + + if( !event.Dragging() && ( m_3d_render_raytracing != nullptr ) ) + { + RAY mouseRay = getRayAtCurrrentMousePosition(); + + BOARD_ITEM *intersectedBoardItem = m_3d_render_raytracing->IntersectBoardItem( mouseRay ); + + // !TODO: send a selection item to pcbnew, eg: via kiway? + } } @@ -793,14 +913,7 @@ void EDA_3D_CANVAS::request_start_moving_camera( float aMovingSpeed, bool aRende void EDA_3D_CANVAS::move_pivot_based_on_cur_mouse_position() { - SFVEC3F rayOrigin; - SFVEC3F rayDir; - - // Generate a ray origin and direction based on current mouser position and camera - m_camera.MakeRayAtCurrrentMousePosition( rayOrigin, rayDir ); - - RAY mouseRay; - mouseRay.Init( rayOrigin, rayDir ); + RAY mouseRay = getRayAtCurrrentMousePosition(); float hit_t; @@ -994,3 +1107,18 @@ void EDA_3D_CANVAS::RenderEngineChanged() Request_refresh(); } + + +RAY EDA_3D_CANVAS::getRayAtCurrrentMousePosition() +{ + SFVEC3F rayOrigin; + SFVEC3F rayDir; + + // Generate a ray origin and direction based on current mouser position and camera + m_camera.MakeRayAtCurrrentMousePosition( rayOrigin, rayDir ); + + RAY mouseRay; + mouseRay.Init( rayOrigin, rayDir ); + + return mouseRay; +} diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.h b/3d-viewer/3d_canvas/eda_3d_canvas.h index 53b9fde151..be748aaad5 100644 --- a/3d-viewer/3d_canvas/eda_3d_canvas.h +++ b/3d-viewer/3d_canvas/eda_3d_canvas.h @@ -27,6 +27,7 @@ #include "board_adapter.h" +#include "3d_rendering/3d_render_raytracing/accelerators/caccelerator.h" #include "3d_rendering/c3d_render_base.h" #include "3d_cache/3d_cache.h" #include @@ -233,6 +234,8 @@ private: */ void releaseOpenGL(); + RAY getRayAtCurrrentMousePosition(); + private: TOOL_DISPATCHER* m_eventDispatcher; @@ -267,6 +270,11 @@ private: bool m_opengl_supports_raytracing; bool m_render_raytracing_was_requested; + CCONTAINER m_3DShapes_container; // Holds 3D shapes from modules + CGENERICACCELERATOR *m_accelerator3DShapes; // used for mouse over searching + + BOARD_ITEM* m_currentIntersectedBoardItem; + /** * Trace mask used to enable or disable the trace output of this class. * The debug output can be turned on by setting the WXTRACE environment variable to diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp index 8304458fa3..f58e2e72f1 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp @@ -75,6 +75,7 @@ C3D_RENDER_OGL_LEGACY::C3D_RENDER_OGL_LEGACY( BOARD_ADAPTER& aAdapter, CCAMERA& m_ogl_circle_texture = 0; m_ogl_disp_list_grid = 0; m_last_grid_type = GRID3D_TYPE::NONE; + m_currentIntersectedBoardItem = nullptr; m_3dmodel_map.clear(); } @@ -1241,15 +1242,34 @@ void C3D_RENDER_OGL_LEGACY::render_3D_models_selected( bool aRenderTopOrBot, boo // Go for all modules for( auto module : m_boardAdapter.GetBoard()->Modules() ) { - if( ( aRenderSelectedOnly && !module->IsSelected() ) || - ( !aRenderSelectedOnly && module->IsSelected() ) ) + const bool isIntersected = ( module == m_currentIntersectedBoardItem ); + + if( !isIntersected && + ( ( aRenderSelectedOnly && !module->IsSelected() ) || + ( !aRenderSelectedOnly && module->IsSelected() ) ) ) continue; + if( isIntersected && aRenderSelectedOnly ) + { + glEnable( GL_POLYGON_OFFSET_LINE ); + glPolygonOffset( 8.0, 1.0 ); + + glPolygonMode( GL_FRONT, GL_LINE ); + glLineWidth( 6 ); + } + if( !module->Models().empty() ) if( m_boardAdapter.ShouldModuleBeDisplayed((MODULE_ATTR_T) module->GetAttributes() ) ) if( ( aRenderTopOrBot && !module->IsFlipped() ) || ( !aRenderTopOrBot && module->IsFlipped() ) ) - render_3D_module( module, aRenderTransparentOnly ); + render_3D_module( module, aRenderTransparentOnly, isIntersected ); + + if( isIntersected && aRenderSelectedOnly ) + { + // Restore + glDisable( GL_POLYGON_OFFSET_LINE ); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } } C_OGL_3DMODEL::EndDrawMulti(); @@ -1264,7 +1284,8 @@ void C3D_RENDER_OGL_LEGACY::render_3D_models( bool aRenderTopOrBot, void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module, - bool aRenderTransparentOnly ) + bool aRenderTransparentOnly, + bool aIsSelected ) { if( !module->Models().empty() ) { @@ -1328,9 +1349,9 @@ void C3D_RENDER_OGL_LEGACY::render_3D_module( const MODULE* module, glMultMatrixf( glm::value_ptr( mtx ) ); if( aRenderTransparentOnly ) - modelPtr->Draw_transparent( sM.m_Opacity, module->IsSelected() ); + modelPtr->Draw_transparent( sM.m_Opacity, module->IsSelected() || aIsSelected ); else - modelPtr->Draw_opaque( module->IsSelected() ); + modelPtr->Draw_opaque( module->IsSelected() || aIsSelected ); if( m_boardAdapter.GetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX ) ) { diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h index e7dec0ad7e..517c22f300 100644 --- a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h @@ -69,6 +69,8 @@ public: int GetWaitForEditingTimeOut() override; + void SetCurrentIntersectedBoardItem( BOARD_ITEM* aCurrentIntersectedBoardItem ) { m_currentIntersectedBoardItem = aCurrentIntersectedBoardItem; } + private: bool initializeOpenGL(); void reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter ); @@ -108,6 +110,8 @@ private: MAP_3DMODEL m_3dmodel_map; + BOARD_ITEM* m_currentIntersectedBoardItem; + private: CLAYERS_OGL_DISP_LISTS *generate_holes_display_list( const LIST_OBJECT2D &aListHolesObject2d, const SHAPE_POLY_SET &aPoly, @@ -192,7 +196,7 @@ private: void render_3D_models_selected( bool aRenderTopOrBot, bool aRenderTransparentOnly, bool aRenderSelectedOnly ); - void render_3D_module( const MODULE* module, bool aRenderTransparentOnly ); + void render_3D_module( const MODULE* module, bool aRenderTransparentOnly, bool aIsSelected ); void setLight_Front( bool enabled ); void setLight_Top( bool enabled ); 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 c6b2b9f1ef..c5772fa716 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 @@ -440,7 +440,9 @@ void C3D_RENDER_RAYTRACING::createItemsFromContainer( const CBVHCONTAINER2D *aCo } } -void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter ) +void C3D_RENDER_RAYTRACING::Reload( REPORTER* aStatusReporter, + REPORTER* aWarningReporter, + bool aOnlyLoadCopperAndShapes ) { m_reloadRequested = false; @@ -451,10 +453,13 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin unsigned stats_startReloadTime = GetRunningMicroSecs(); - m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter ); + if( !aOnlyLoadCopperAndShapes ) + { + m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter ); - SFVEC3F camera_pos = m_boardAdapter.GetBoardCenter3DU(); - m_camera.SetBoardLookAtPos( camera_pos ); + SFVEC3F camera_pos = m_boardAdapter.GetBoardCenter3DU(); + m_camera.SetBoardLookAtPos( camera_pos ); + } m_object_container.Clear(); m_containerWithObjectsToDelete.Clear(); @@ -468,153 +473,156 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin m_outlineBoard2dObjects = new CCONTAINER2D; - const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount(); - - if( outlineCount > 0 ) + if( !aOnlyLoadCopperAndShapes ) { - float divFactor = 0.0f; + const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount(); - if( m_boardAdapter.GetStats_Nr_Vias() ) - divFactor = m_boardAdapter.GetStats_Med_Via_Hole_Diameter3DU() * 18.0f; - else - if( m_boardAdapter.GetStats_Nr_Holes() ) - divFactor = m_boardAdapter.GetStats_Med_Hole_Diameter3DU() * 8.0f; - - SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly(); - boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST ); - - for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ ) + if( outlineCount > 0 ) { - Convert_path_polygon_to_polygon_blocks_and_dummy_blocks( - boardPolyCopy, - *m_outlineBoard2dObjects, - m_boardAdapter.BiuTo3Dunits(), - divFactor, - *dynamic_cast( m_boardAdapter.GetBoard() ), - iOutlinePolyIdx ); - } + float divFactor = 0.0f; - if( m_boardAdapter.GetFlag( FL_SHOW_BOARD_BODY ) ) - { - const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList(); + if( m_boardAdapter.GetStats_Nr_Vias() ) + divFactor = m_boardAdapter.GetStats_Med_Via_Hole_Diameter3DU() * 18.0f; + else + if( m_boardAdapter.GetStats_Nr_Holes() ) + divFactor = m_boardAdapter.GetStats_Med_Hole_Diameter3DU() * 8.0f; - for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin(); - object2d_iterator != listObjects.end(); - ++object2d_iterator ) + SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly(); + boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST ); + + for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ ) { - const COBJECT2D *object2d_A = static_cast(*object2d_iterator); - - std::vector *object2d_B = new std::vector(); - - // Check if there are any THT that intersects this outline object part - if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) - { - - CONST_LIST_OBJECT2D intersectionList; - m_boardAdapter.GetThroughHole_Outer().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 ); - } - } - } - - if( object2d_B->empty() ) - { - delete object2d_B; - object2d_B = CSGITEM_EMPTY; - } - - 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 ) ); - - objPtr->SetMaterial( &m_materials.m_EpoxyBoard ); - objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) ); - m_object_container.Add( objPtr ); - #endif - } - else - { - - CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( - object2d_A, - object2d_B, - CSGITEM_FULL, - (const BOARD_ITEM &)*m_boardAdapter.GetBoard() ); - - m_containerWithObjectsToDelete.Add( itemCSG2d ); - - CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, - m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ), - m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) ); - - objPtr->SetMaterial( &m_materials.m_EpoxyBoard ); - objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) ); - m_object_container.Add( objPtr ); - - } + Convert_path_polygon_to_polygon_blocks_and_dummy_blocks( + boardPolyCopy, + *m_outlineBoard2dObjects, + m_boardAdapter.BiuTo3Dunits(), + divFactor, + *dynamic_cast( m_boardAdapter.GetBoard() ), + iOutlinePolyIdx ); } - // Add cylinders of the board body to container - // Note: This is actually a workarround for the holes in the board. - // The issue is because if a hole is in a border of a divided polygon ( ex - // a polygon or dummyblock) it will cut also the render of the hole. - // So this will add a full hole. - // In fact, that is not need if the hole have copper. - // ///////////////////////////////////////////////////////////////////////// - if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) + if( m_boardAdapter.GetFlag( FL_SHOW_BOARD_BODY ) ) { - const LIST_OBJECT2D &holeList = m_boardAdapter.GetThroughHole_Outer().GetList(); + const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList(); - for( LIST_OBJECT2D::const_iterator hole = holeList.begin(); - hole != holeList.end(); - ++hole ) + for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin(); + object2d_iterator != listObjects.end(); + ++object2d_iterator ) { - const COBJECT2D *hole2d = static_cast(*hole); + const COBJECT2D *object2d_A = static_cast(*object2d_iterator); - switch( hole2d->GetObjectType() ) - { - case OBJECT2D_TYPE::FILLED_CIRCLE: - { - const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f; + std::vector *object2d_B = new std::vector(); - CVCYLINDER *objPtr = new CVCYLINDER( - hole2d->GetCentroid(), - NextFloatDown( m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) ), - NextFloatUp( m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) ), - radius ); + // Check if there are any THT that intersects this outline object part + if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) + { + + CONST_LIST_OBJECT2D intersectionList; + m_boardAdapter.GetThroughHole_Outer().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 ); + } + } + } + + if( object2d_B->empty() ) + { + delete object2d_B; + object2d_B = CSGITEM_EMPTY; + } + + 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 ) ); objPtr->SetMaterial( &m_materials.m_EpoxyBoard ); objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) ); - m_object_container.Add( objPtr ); + #endif } - break; + else + { - default: + CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( + object2d_A, + object2d_B, + CSGITEM_FULL, + (const BOARD_ITEM &)*m_boardAdapter.GetBoard() ); + + m_containerWithObjectsToDelete.Add( itemCSG2d ); + + CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, + m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ), + m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) ); + + objPtr->SetMaterial( &m_materials.m_EpoxyBoard ); + objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) ); + m_object_container.Add( objPtr ); + + } + } + + // Add cylinders of the board body to container + // Note: This is actually a workarround for the holes in the board. + // The issue is because if a hole is in a border of a divided polygon ( ex + // a polygon or dummyblock) it will cut also the render of the hole. + // So this will add a full hole. + // In fact, that is not need if the hole have copper. + // ///////////////////////////////////////////////////////////////////////// + if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) + { + const LIST_OBJECT2D &holeList = m_boardAdapter.GetThroughHole_Outer().GetList(); + + for( LIST_OBJECT2D::const_iterator hole = holeList.begin(); + hole != holeList.end(); + ++hole ) + { + const COBJECT2D *hole2d = static_cast(*hole); + + switch( hole2d->GetObjectType() ) + { + case OBJECT2D_TYPE::FILLED_CIRCLE: + { + const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f; + + CVCYLINDER *objPtr = new CVCYLINDER( + hole2d->GetCentroid(), + NextFloatDown( m_boardAdapter.GetLayerBottomZpos3DU( F_Cu ) ), + NextFloatUp( m_boardAdapter.GetLayerBottomZpos3DU( B_Cu ) ), + radius ); + + objPtr->SetMaterial( &m_materials.m_EpoxyBoard ); + objPtr->SetColor( ConvertSRGBToLinear( (SFVEC3F)m_boardAdapter.m_BoardBodyColor ) ); + + m_object_container.Add( objPtr ); + } break; + + default: + break; + } } } } @@ -631,6 +639,9 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin { PCB_LAYER_ID layer_id = static_cast(ii->first); + if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) ) + continue; + // Mask kayers are not processed here because they are a special case if( (layer_id == B_Mask) || (layer_id == F_Mask) ) continue; @@ -718,152 +729,155 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin 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 - // (in the container) should remove the board outline. - // We will check for all objects in the outline if it intersects any object - // in the layer container and also any hole. - // ///////////////////////////////////////////////////////////////////////// - if( m_boardAdapter.GetFlag( FL_SOLDERMASK ) && - (m_outlineBoard2dObjects->GetList().size() >= 1) ) + if( !aOnlyLoadCopperAndShapes ) { - const CMATERIAL *materialLayer = &m_materials.m_SolderMask; - - for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin(); - ii != m_boardAdapter.GetMapLayers().end(); - ++ii ) + // Add Mask layer + // Solder mask layers are "negative" layers so the elements that we have + // (in the container) should remove the board outline. + // We will check for all objects in the outline if it intersects any object + // in the layer container and also any hole. + // ///////////////////////////////////////////////////////////////////////// + if( m_boardAdapter.GetFlag( FL_SOLDERMASK ) && + (m_outlineBoard2dObjects->GetList().size() >= 1) ) { - PCB_LAYER_ID layer_id = static_cast(ii->first); + const CMATERIAL *materialLayer = &m_materials.m_SolderMask; - const CBVHCONTAINER2D *containerLayer2d = - static_cast(ii->second); - - // Only get the Solder mask layers - if( !((layer_id == B_Mask) || (layer_id == F_Mask)) ) - continue; - - SFVEC3F layerColor; - if( m_boardAdapter.GetFlag( FL_USE_REALISTIC_MODE ) ) + for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin(); + ii != m_boardAdapter.GetMapLayers().end(); + ++ii ) { - if( layer_id == B_Mask ) - layerColor = m_boardAdapter.m_SolderMaskColorBot; - else - layerColor = m_boardAdapter.m_SolderMaskColorTop; - } - else - layerColor = m_boardAdapter.GetLayerColor( layer_id ); + PCB_LAYER_ID layer_id = static_cast(ii->first); - const float zLayerMin = m_boardAdapter.GetLayerBottomZpos3DU( layer_id ); - const float zLayerMax = m_boardAdapter.GetLayerTopZpos3DU( layer_id ); + const CBVHCONTAINER2D *containerLayer2d = + static_cast(ii->second); - // Get the outline board objects - const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList(); + // Only get the Solder mask layers + if( !((layer_id == B_Mask) || (layer_id == F_Mask)) ) + continue; - for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin(); - object2d_iterator != listObjects.end(); - ++object2d_iterator ) - { - const COBJECT2D *object2d_A = static_cast(*object2d_iterator); - - std::vector *object2d_B = new std::vector(); - - // Check if there are any THT that intersects this outline object part - if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) + SFVEC3F layerColor; + if( m_boardAdapter.GetFlag( FL_USE_REALISTIC_MODE ) ) { - - CONST_LIST_OBJECT2D intersectionList; - - m_boardAdapter.GetThroughHole_Outer().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 ); - } - } - } - - // Check if there are any objects in the layer to subtract with the - // corrent object - if( !containerLayer2d->GetList().empty() ) - { - CONST_LIST_OBJECT2D intersectionList; - - containerLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(), - intersectionList ); - - if( !intersectionList.empty() ) - { - for( CONST_LIST_OBJECT2D::const_iterator obj = intersectionList.begin(); - obj != intersectionList.end(); - ++obj ) - { - const COBJECT2D *obj2d = static_cast(*obj); - - //if( object2d_A->Intersects( obj2d->GetBBox() ) ) - //if( object2d_A->GetBBox().Intersects( obj2d->GetBBox() ) ) - object2d_B->push_back( obj2d ); - } - } - } - - if( object2d_B->empty() ) - { - delete object2d_B; - object2d_B = CSGITEM_EMPTY; - } - - if( object2d_B == CSGITEM_EMPTY ) - { - #if 0 - create_3d_object_from( m_object_container, - object2d_A, - zLayerMin, - zLayerMax, - materialLayer, - layerColor ); - #else - CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, - zLayerMin, - zLayerMax ); - - objPtr->SetMaterial( materialLayer ); - objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); - - m_object_container.Add( objPtr ); - #endif + if( layer_id == B_Mask ) + layerColor = m_boardAdapter.m_SolderMaskColorBot; + else + layerColor = m_boardAdapter.m_SolderMaskColorTop; } else + layerColor = m_boardAdapter.GetLayerColor( layer_id ); + + const float zLayerMin = m_boardAdapter.GetLayerBottomZpos3DU( layer_id ); + const float zLayerMax = m_boardAdapter.GetLayerTopZpos3DU( layer_id ); + + // Get the outline board objects + const LIST_OBJECT2D &listObjects = m_outlineBoard2dObjects->GetList(); + + for( LIST_OBJECT2D::const_iterator object2d_iterator = listObjects.begin(); + object2d_iterator != listObjects.end(); + ++object2d_iterator ) { - CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, - object2d_B, - CSGITEM_FULL, - object2d_A->GetBoardItem() ); + const COBJECT2D *object2d_A = static_cast(*object2d_iterator); - m_containerWithObjectsToDelete.Add( itemCSG2d ); + std::vector *object2d_B = new std::vector(); - CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, - zLayerMin, - zLayerMax ); - objPtr->SetMaterial( materialLayer ); - objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); + // Check if there are any THT that intersects this outline object part + if( !m_boardAdapter.GetThroughHole_Outer().GetList().empty() ) + { - m_object_container.Add( objPtr ); + CONST_LIST_OBJECT2D intersectionList; + + m_boardAdapter.GetThroughHole_Outer().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 ); + } + } + } + + // Check if there are any objects in the layer to subtract with the + // corrent object + if( !containerLayer2d->GetList().empty() ) + { + CONST_LIST_OBJECT2D intersectionList; + + containerLayer2d->GetListObjectsIntersects( object2d_A->GetBBox(), + intersectionList ); + + if( !intersectionList.empty() ) + { + for( CONST_LIST_OBJECT2D::const_iterator obj = intersectionList.begin(); + obj != intersectionList.end(); + ++obj ) + { + const COBJECT2D *obj2d = static_cast(*obj); + + //if( object2d_A->Intersects( obj2d->GetBBox() ) ) + //if( object2d_A->GetBBox().Intersects( obj2d->GetBBox() ) ) + object2d_B->push_back( obj2d ); + } + } + } + + if( object2d_B->empty() ) + { + delete object2d_B; + object2d_B = CSGITEM_EMPTY; + } + + if( object2d_B == CSGITEM_EMPTY ) + { + #if 0 + create_3d_object_from( m_object_container, + object2d_A, + zLayerMin, + zLayerMax, + materialLayer, + layerColor ); + #else + CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, + zLayerMin, + zLayerMax ); + + objPtr->SetMaterial( materialLayer ); + objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); + + m_object_container.Add( objPtr ); + #endif + } + else + { + CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, + object2d_B, + CSGITEM_FULL, + object2d_A->GetBoardItem() ); + + m_containerWithObjectsToDelete.Add( itemCSG2d ); + + CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, + zLayerMin, + zLayerMax ); + objPtr->SetMaterial( materialLayer ); + objPtr->SetColor( ConvertSRGBToLinear( layerColor ) ); + + m_object_container.Add( objPtr ); + } } } } - } - add_3D_vias_and_pads_to_container(); + add_3D_vias_and_pads_to_container(); + } #ifdef PRINT_STATISTICS_3D_VIEWER unsigned stats_endConvertTime = GetRunningMicroSecs(); @@ -871,136 +885,138 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER* aStatusReporter, REPORTER* aWarnin #endif - load_3D_models( false ); + load_3D_models( m_object_container, aOnlyLoadCopperAndShapes ); #ifdef PRINT_STATISTICS_3D_VIEWER unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs(); #endif - // Add floor - // ///////////////////////////////////////////////////////////////////////// - if( m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_BACKFLOOR ) ) + if( !aOnlyLoadCopperAndShapes ) { - CBBOX boardBBox = m_boardAdapter.GetBBox3DU(); - - if( boardBBox.IsInitialized() ) + // Add floor + // ///////////////////////////////////////////////////////////////////////// + if( m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_BACKFLOOR ) ) { - boardBBox.Scale( 3.0f ); + CBBOX boardBBox = m_boardAdapter.GetBBox3DU(); - if( m_object_container.GetList().size() > 0 ) + if( boardBBox.IsInitialized() ) { - CBBOX containerBBox = m_object_container.GetBBox(); + boardBBox.Scale( 3.0f ); - containerBBox.Scale( 1.3f ); + if( m_object_container.GetList().size() > 0 ) + { + CBBOX containerBBox = m_object_container.GetBBox(); - const SFVEC3F centerBBox = containerBBox.GetCenter(); + containerBBox.Scale( 1.3f ); - // Floor triangles - const float minZ = glm::min( containerBBox.Min().z, - boardBBox.Min().z ); + const SFVEC3F centerBBox = containerBBox.GetCenter(); - const SFVEC3F v1 = SFVEC3F( -RANGE_SCALE_3D * 4.0f, - -RANGE_SCALE_3D * 4.0f, - minZ ) + - SFVEC3F( centerBBox.x, - centerBBox.y, - 0.0f ); + // Floor triangles + const float minZ = glm::min( containerBBox.Min().z, + boardBBox.Min().z ); - const SFVEC3F v3 = SFVEC3F( +RANGE_SCALE_3D * 4.0f, - +RANGE_SCALE_3D * 4.0f, - minZ ) + - SFVEC3F( centerBBox.x, - centerBBox.y, - 0.0f ); + const SFVEC3F v1 = SFVEC3F( -RANGE_SCALE_3D * 4.0f, + -RANGE_SCALE_3D * 4.0f, + minZ ) + + SFVEC3F( centerBBox.x, + centerBBox.y, + 0.0f ); - const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z ); - const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z ); + const SFVEC3F v3 = SFVEC3F( +RANGE_SCALE_3D * 4.0f, + +RANGE_SCALE_3D * 4.0f, + minZ ) + + SFVEC3F( centerBBox.x, + centerBBox.y, + 0.0f ); - SFVEC3F backgroundColor = - ConvertSRGBToLinear( static_cast( m_boardAdapter.m_BgColorTop ) ); + const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z ); + const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z ); - CTRIANGLE *newTriangle1 = new CTRIANGLE( v1, v2, v3 ); - CTRIANGLE *newTriangle2 = new CTRIANGLE( v3, v4, v1 ); + SFVEC3F backgroundColor = + ConvertSRGBToLinear( static_cast( m_boardAdapter.m_BgColorTop ) ); - m_object_container.Add( newTriangle1 ); - m_object_container.Add( newTriangle2 ); + CTRIANGLE *newTriangle1 = new CTRIANGLE( v1, v2, v3 ); + CTRIANGLE *newTriangle2 = new CTRIANGLE( v3, v4, v1 ); - newTriangle1->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); - newTriangle2->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); + m_object_container.Add( newTriangle1 ); + m_object_container.Add( newTriangle2 ); - newTriangle1->SetColor( backgroundColor ); - newTriangle2->SetColor( backgroundColor ); + newTriangle1->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); + newTriangle2->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); - // Ceiling triangles - const float maxZ = glm::max( containerBBox.Max().z, - boardBBox.Max().z ); + newTriangle1->SetColor( backgroundColor ); + newTriangle2->SetColor( backgroundColor ); - const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ ); - const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ ); - const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ ); - const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ ); + // Ceiling triangles + const float maxZ = glm::max( containerBBox.Max().z, + boardBBox.Max().z ); - CTRIANGLE *newTriangle3 = new CTRIANGLE( v7, v6, v5 ); - CTRIANGLE *newTriangle4 = new CTRIANGLE( v5, v8, v7 ); + const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ ); + const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ ); + const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ ); + const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ ); - m_object_container.Add( newTriangle3 ); - m_object_container.Add( newTriangle4 ); + CTRIANGLE *newTriangle3 = new CTRIANGLE( v7, v6, v5 ); + CTRIANGLE *newTriangle4 = new CTRIANGLE( v5, v8, v7 ); - newTriangle3->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); - newTriangle4->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); + m_object_container.Add( newTriangle3 ); + m_object_container.Add( newTriangle4 ); - newTriangle3->SetColor( backgroundColor ); - newTriangle4->SetColor( backgroundColor ); + newTriangle3->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); + newTriangle4->SetMaterial( (const CMATERIAL *)&m_materials.m_Floor ); + + newTriangle3->SetColor( backgroundColor ); + newTriangle4->SetColor( backgroundColor ); + } + } + } + + + // Init initial lights + // ///////////////////////////////////////////////////////////////////////// + m_lights.Clear(); + + auto IsColorZero = [] ( const SFVEC3F& aSource ) + { + return ( ( aSource.r < ( 1.0f / 255.0f ) ) && + ( aSource.g < ( 1.0f / 255.0f ) ) && + ( aSource.b < ( 1.0f / 255.0f ) ) ); + }; + + m_camera_light = new CDIRECTIONALLIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), + m_boardAdapter.m_raytrace_lightColorCamera ); + m_camera_light->SetCastShadows( false ); + + if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorCamera ) ) + m_lights.Add( m_camera_light ); + + const SFVEC3F& boardCenter = m_boardAdapter.GetBBox3DU().GetCenter(); + + if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorTop ) ) + m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, +RANGE_SCALE_3D * 2.0f ), + m_boardAdapter.m_raytrace_lightColorTop ) ); + + if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorBottom ) ) + m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, -RANGE_SCALE_3D * 2.0f ), + m_boardAdapter.m_raytrace_lightColorBottom ) ); + + wxASSERT( m_boardAdapter.m_raytrace_lightColor.size() + == m_boardAdapter.m_raytrace_lightSphericalCoords.size() ); + + for( size_t i = 0; i < m_boardAdapter.m_raytrace_lightColor.size(); ++i ) + { + if( !IsColorZero( m_boardAdapter.m_raytrace_lightColor[i] ) ) + { + const SFVEC2F sc = m_boardAdapter.m_raytrace_lightSphericalCoords[i]; + + m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi() * sc.x, + glm::pi() * sc.y ), + m_boardAdapter.m_raytrace_lightColor[i] ) ); } } } - - // Init initial lights - // ///////////////////////////////////////////////////////////////////////// - m_lights.Clear(); - - auto IsColorZero = [] ( const SFVEC3F& aSource ) - { - return ( ( aSource.r < ( 1.0f / 255.0f ) ) && - ( aSource.g < ( 1.0f / 255.0f ) ) && - ( aSource.b < ( 1.0f / 255.0f ) ) ); - }; - - m_camera_light = new CDIRECTIONALLIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ), - m_boardAdapter.m_raytrace_lightColorCamera ); - m_camera_light->SetCastShadows( false ); - - if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorCamera ) ) - m_lights.Add( m_camera_light ); - - const SFVEC3F& boardCenter = m_boardAdapter.GetBBox3DU().GetCenter(); - - if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorTop ) ) - m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, +RANGE_SCALE_3D * 2.0f ), - m_boardAdapter.m_raytrace_lightColorTop ) ); - - if( !IsColorZero( m_boardAdapter.m_raytrace_lightColorBottom ) ) - m_lights.Add( new CPOINTLIGHT( SFVEC3F( boardCenter.x, boardCenter.y, -RANGE_SCALE_3D * 2.0f ), - m_boardAdapter.m_raytrace_lightColorBottom ) ); - - wxASSERT( m_boardAdapter.m_raytrace_lightColor.size() - == m_boardAdapter.m_raytrace_lightSphericalCoords.size() ); - - for( size_t i = 0; i < m_boardAdapter.m_raytrace_lightColor.size(); ++i ) - { - if( !IsColorZero( m_boardAdapter.m_raytrace_lightColor[i] ) ) - { - const SFVEC2F sc = m_boardAdapter.m_raytrace_lightSphericalCoords[i]; - - m_lights.Add( new CDIRECTIONALLIGHT( SphericalToCartesian( glm::pi() * sc.x, - glm::pi() * sc.y ), - m_boardAdapter.m_raytrace_lightColor[i] ) ); - } - } - - // Create an accelerator // ///////////////////////////////////////////////////////////////////////// if( m_accelerator ) @@ -1250,7 +1266,7 @@ void C3D_RENDER_RAYTRACING::add_3D_vias_and_pads_to_container() } -void C3D_RENDER_RAYTRACING::load_3D_models( bool aSkipMaterialInformation ) +void C3D_RENDER_RAYTRACING::load_3D_models( CCONTAINER &aDstContainer, bool aSkipMaterialInformation ) { // Go for all modules for( auto module : m_boardAdapter.GetBoard()->Modules() ) @@ -1297,6 +1313,7 @@ void C3D_RENDER_RAYTRACING::load_3D_models( bool aSkipMaterialInformation ) modelunit_to_3d_units_factor, modelunit_to_3d_units_factor ) ); + BOARD_ITEM* boardItem = dynamic_cast( module ); // Get the list of model files for this model S3D_CACHE* cacheMgr = m_boardAdapter.Get3DCacheManager(); @@ -1341,7 +1358,12 @@ void C3D_RENDER_RAYTRACING::load_3D_models( bool aSkipMaterialInformation ) sM->m_Scale.y, sM->m_Scale.z ) ); - add_3D_models( modelPtr, modelMatrix, (float)sM->m_Opacity, aSkipMaterialInformation ); + add_3D_models( aDstContainer, + modelPtr, + modelMatrix, + (float)sM->m_Opacity, + aSkipMaterialInformation, + boardItem ); } } @@ -1462,10 +1484,12 @@ MODEL_MATERIALS *C3D_RENDER_RAYTRACING::get_3D_model_material( const S3DMODEL *a return materialVector; } -void C3D_RENDER_RAYTRACING::add_3D_models( const S3DMODEL *a3DModel, +void C3D_RENDER_RAYTRACING::add_3D_models( CCONTAINER &aDstContainer, + const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aModuleOpacity, - bool aSkipMaterialInformation ) + bool aSkipMaterialInformation, + BOARD_ITEM *aBoardItem ) { // Validate a3DModel pointers @@ -1562,7 +1586,9 @@ void C3D_RENDER_RAYTRACING::add_3D_models( const S3DMODEL *a3DModel, CTRIANGLE *newTriangle = new CTRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 ); - m_object_container.Add( newTriangle ); + newTriangle->SetBoardItem( aBoardItem ); + + aDstContainer.Add( newTriangle ); if( !aSkipMaterialInformation ) { diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp index 6da71fa5a2..24912997e3 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/c3d_render_raytracing.cpp @@ -179,7 +179,7 @@ bool C3D_RENDER_RAYTRACING::Redraw( //aIsMoving = true; requestRedraw = true; - reload( aStatusReporter, aWarningReporter ); + Reload( aStatusReporter, aWarningReporter, false ); } @@ -2079,3 +2079,18 @@ void C3D_RENDER_RAYTRACING::initialize_block_positions() opengl_init_pbo(); } + +BOARD_ITEM *C3D_RENDER_RAYTRACING::IntersectBoardItem( const RAY &aRay ) +{ + HITINFO hitInfo; + hitInfo.m_tHit = std::numeric_limits::infinity(); + + if( m_accelerator ) + if( m_accelerator->Intersect( aRay, hitInfo ) ) + { + if( hitInfo.pHitObject ) + return hitInfo.pHitObject->GetBoardItem(); + } + + return nullptr; +} 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 5d91e23434..40e330b50b 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 @@ -69,12 +69,15 @@ public: int GetWaitForEditingTimeOut() override; + void Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter, bool aOnlyLoadCopperAndShapes ); + + BOARD_ITEM *IntersectBoardItem( const RAY &aRay ); + private: bool initializeOpenGL(); void initializeNewWindowSize(); 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, @@ -201,11 +204,13 @@ private: void add_3D_vias_and_pads_to_container(); void insert3DViaHole( const VIA* aVia ); void insert3DPadHole( const D_PAD* aPad ); - void load_3D_models( bool aSkipMaterialInformation ); - void add_3D_models( const S3DMODEL *a3DModel, + void load_3D_models( CCONTAINER &aDstContainer, bool aSkipMaterialInformation ); + void add_3D_models( CCONTAINER &aDstContainer, + const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aModuleOpacity, - bool aSkipMaterialInformation ); + bool aSkipMaterialInformation, + BOARD_ITEM *aBoardItem ); MODEL_MATERIALS *get_3D_model_material( const S3DMODEL *a3DModel ); diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.cpp index 9d2827ced9..dcd5775a22 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.cpp +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.cpp @@ -42,6 +42,7 @@ COBJECT::COBJECT( OBJECT3D_TYPE aObjType ) COBJECT3D_STATS::Instance().AddOne( aObjType ); m_material = &s_defaultMaterial; m_modelTransparency = 0.0f; + m_boardItem = nullptr; } diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h index db64bc2bb2..afebe2cbb7 100644 --- a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h @@ -34,6 +34,7 @@ #include "../hitinfo.h" #include "../cmaterial.h" +#include enum class OBJECT3D_TYPE { @@ -55,6 +56,8 @@ protected: OBJECT3D_TYPE m_obj_type; const CMATERIAL *m_material; + BOARD_ITEM *m_boardItem; + // m_modelTransparency combines the material and model opacity // 0.0 full opaque, 1.0 full transparent. float m_modelTransparency; @@ -63,6 +66,9 @@ public: explicit COBJECT( OBJECT3D_TYPE aObjType ); + const void SetBoardItem( BOARD_ITEM *aBoardItem ) { m_boardItem = aBoardItem; } + BOARD_ITEM *GetBoardItem() const { return m_boardItem; } + void SetMaterial( const CMATERIAL *aMaterial ) { m_material = aMaterial; diff --git a/3d-viewer/3d_rendering/ccamera.cpp b/3d-viewer/3d_rendering/ccamera.cpp index 2006a82131..c7467c4441 100644 --- a/3d-viewer/3d_rendering/ccamera.cpp +++ b/3d-viewer/3d_rendering/ccamera.cpp @@ -380,9 +380,13 @@ void CCAMERA::MakeRay( const SFVEC2F &aWindowPos, SFVEC3F &aOutOrigin, SFVEC3F & void CCAMERA::MakeRayAtCurrrentMousePosition( SFVEC3F &aOutOrigin, SFVEC3F &aOutDirection ) const { - MakeRay( SFVEC2I( m_lastPosition.x, - m_windowSize.y - m_lastPosition.y ), - aOutOrigin, aOutDirection ); + const SFVEC2I windowPos = SFVEC2I( m_lastPosition.x, + m_windowSize.y - m_lastPosition.y ); + + if( ( windowPos.x < m_windowSize.x ) && + ( windowPos.y < m_windowSize.y ) ) + MakeRay( windowPos, + aOutOrigin, aOutDirection ); } diff --git a/3d-viewer/3d_viewer/eda_3d_viewer.cpp b/3d-viewer/3d_viewer/eda_3d_viewer.cpp index fe321d6ae0..cde7d039e0 100644 --- a/3d-viewer/3d_viewer/eda_3d_viewer.cpp +++ b/3d-viewer/3d_viewer/eda_3d_viewer.cpp @@ -275,7 +275,7 @@ void EDA_3D_VIEWER::Redraw() { // Only update in OpenGL for an interactive interaction if( m_boardAdapter.RenderEngineGet() == RENDER_ENGINE::OPENGL_LEGACY ) - m_canvas->Refresh(); + m_canvas->Request_refresh( true ); } void EDA_3D_VIEWER::Exit3DFrame( wxCommandEvent &event )