Browse Source

3D viewer: Display of missing/not loadable 3D models

fork/Issue_3453_extruded_3d_body
Damjan 3 months ago
parent
commit
59cae111dc
  1. 2
      3d-viewer/3d_cache/3d_cache.h
  2. 116
      3d-viewer/3d_rendering/3d_placeholder_utils.cpp
  3. 39
      3d-viewer/3d_rendering/3d_placeholder_utils.h
  4. 1
      3d-viewer/3d_rendering/opengl/create_scene.cpp
  5. 183
      3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp
  6. 6
      3d-viewer/3d_rendering/opengl/render_3d_opengl.h
  7. 59
      3d-viewer/3d_rendering/raytracing/create_scene.cpp
  8. 2
      3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.h
  9. 17
      3d-viewer/3d_rendering/raytracing/shapes3D/dummy_block_3d.cpp
  10. 2
      3d-viewer/3d_viewer/3d_menubar.cpp
  11. 6
      3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp
  12. 1
      3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp
  13. 1
      3d-viewer/3d_viewer/eda_3d_viewer_settings.h
  14. 7
      3d-viewer/3d_viewer/tools/eda_3d_actions.cpp
  15. 1
      3d-viewer/3d_viewer/tools/eda_3d_actions.h
  16. 10
      3d-viewer/3d_viewer/tools/eda_3d_controller.cpp
  17. 1
      3d-viewer/3d_viewer/tools/eda_3d_controller.h
  18. 1
      3d-viewer/CMakeLists.txt
  19. 4
      3d-viewer/dialogs/panel_preview_3d_model.cpp

2
3d-viewer/3d_cache/3d_cache.h

@ -190,7 +190,7 @@ private:
PROJECT* m_project;
wxString m_CacheDir;
wxString m_ConfigDir; ///< base configuration path for 3D items.
wxString m_ConfigDir; ///< base configuration path for 3D items.
};
#endif // CACHE_3D_H

116
3d-viewer/3d_rendering/3d_placeholder_utils.cpp

@ -0,0 +1,116 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "3d_placeholder_utils.h"
#include <footprint.h>
#include <pad.h>
#include <board_item.h>
#include <layer_ids.h>
#include <geometry/eda_angle.h>
BOX2I CalcPlaceholderLocalBox( const FOOTPRINT* aFootprint )
{
BOX2I localBox;
bool hasLocalBounds = false;
for( PAD* pad : aFootprint->Pads() )
{
VECTOR2I padPos = pad->GetFPRelativePosition();
VECTOR2I padSize = pad->GetSize( PADSTACK::ALL_LAYERS );
BOX2I padBox;
padBox.SetOrigin( padPos - padSize / 2 );
padBox.SetSize( padSize );
if( !hasLocalBounds )
{
localBox = padBox;
hasLocalBounds = true;
}
else
{
localBox.Merge( padBox );
}
}
if( !hasLocalBounds )
{
VECTOR2I fpPos = aFootprint->GetPosition();
EDA_ANGLE fpAngle = aFootprint->GetOrientation();
for( BOARD_ITEM* item : aFootprint->GraphicalItems() )
{
PCB_LAYER_ID layer = item->GetLayer();
if( layer == F_Fab || layer == B_Fab || layer == F_CrtYd || layer == B_CrtYd || layer == F_SilkS
|| layer == B_SilkS )
{
BOX2I itemBox = item->GetBoundingBox();
VECTOR2I corners[4] = { itemBox.GetOrigin() - fpPos,
VECTOR2I( itemBox.GetRight(), itemBox.GetTop() ) - fpPos,
VECTOR2I( itemBox.GetRight(), itemBox.GetBottom() ) - fpPos,
VECTOR2I( itemBox.GetLeft(), itemBox.GetBottom() ) - fpPos };
BOX2I localItemBox;
for( int ci = 0; ci < 4; ++ci )
{
RotatePoint( corners[ci], -fpAngle );
if( ci == 0 )
{
localItemBox.SetOrigin( corners[ci] );
localItemBox.SetSize( VECTOR2I( 0, 0 ) );
}
else
{
localItemBox.Merge( BOX2I( corners[ci], VECTOR2I( 0, 0 ) ) );
}
}
if( !hasLocalBounds )
{
localBox = localItemBox;
hasLocalBounds = true;
}
else
{
localBox.Merge( localItemBox );
}
}
}
}
if( !hasLocalBounds )
{
BOX2I fpBox = aFootprint->GetBoundingBox( false );
int size = std::min( fpBox.GetWidth(), fpBox.GetHeight() );
localBox.SetOrigin( VECTOR2I( -size / 2, -size / 2 ) );
localBox.SetSize( VECTOR2I( size, size ) );
}
return localBox;
}

39
3d-viewer/3d_rendering/3d_placeholder_utils.h

@ -0,0 +1,39 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef PLACEHOLDER_3D_UTILS_H
#define PLACEHOLDER_3D_UTILS_H
#include <math/box2.h>
class FOOTPRINT;
/**
* Calculate a local space bounding box for a placeholder 3D model.
*
* Attempts pads first, then graphical items on fab/courtyard/silk layers,
* then falls back to the footprint bounding box.
*/
BOX2I CalcPlaceholderLocalBox( const FOOTPRINT* aFootprint );
#endif // PLACEHOLDER_3D_UTILS_H

1
3d-viewer/3d_rendering/opengl/create_scene.cpp

@ -690,6 +690,7 @@ void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningRepo
m_reloadRequested = false;
freeAllLists();
createPlaceholderModel();
OBJECT_2D_STATS::Instance().ResetStats();

183
3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp

@ -30,6 +30,7 @@
#include "render_3d_opengl.h"
#include "opengl_utils.h"
#include "common_ogl/ogl_utils.h"
#include "../3d_placeholder_utils.h"
#include <board.h>
#include <footprint.h>
#include <kicad_gl/gl_context_mgr.h>
@ -116,6 +117,8 @@ RENDER_3D_OPENGL::~RENDER_3D_OPENGL()
freeAllLists();
delete m_placeholderModel;
glDeleteTextures( 1, &m_circleTexture );
delete m_spheres_gizmo;
@ -1001,6 +1004,7 @@ void RENDER_3D_OPENGL::freeAllLists()
DELETE_AND_FREE( m_padHoles )
DELETE_AND_FREE( m_viaFrontCover )
DELETE_AND_FREE( m_viaBackCover )
DELETE_AND_FREE( m_placeholderModel )
}
@ -1065,7 +1069,10 @@ void RENDER_3D_OPENGL::get3dModelsSelected( std::list<MODELTORENDER> &aDstRender
continue;
}
if( !fp->Models().empty() )
bool hasModels = !fp->Models().empty();
bool showMissing = m_boardAdapter.m_Cfg->m_Render.show_missing_models;
if( hasModels || showMissing )
{
if( m_boardAdapter.IsFootprintShown( fp ) )
{
@ -1093,8 +1100,7 @@ void RENDER_3D_OPENGL::get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstR
glm::mat4 fpMatrix( 1.0f );
fpMatrix = glm::translate( fpMatrix, SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
-pos.y * m_boardAdapter.BiuTo3dUnits(),
zpos ) );
-pos.y * m_boardAdapter.BiuTo3dUnits(), zpos ) );
if( !aFootprint->GetOrientation().IsZero() )
{
@ -1122,7 +1128,11 @@ void RENDER_3D_OPENGL::get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstR
auto cache_i = m_3dModelMap.find( sM.m_Filename );
if( cache_i == m_3dModelMap.end() )
{
renderPlaceholderForFootprint( aDstRenderList, fpMatrix, aFootprint, aRenderTransparentOnly,
aIsSelected, aRenderTransparentOnly ? sM.m_Opacity : 1.0f );
continue;
}
if( const MODEL_3D* modelPtr = cache_i->second )
{
@ -1169,6 +1179,75 @@ void RENDER_3D_OPENGL::get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstR
}
}
}
else
{
const double zpos = m_boardAdapter.GetFootprintZPos( aFootprint->IsFlipped() );
VECTOR2I pos = aFootprint->GetPosition();
glm::mat4 fpMatrix( 1.0f );
fpMatrix = glm::translate( fpMatrix, SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
-pos.y * m_boardAdapter.BiuTo3dUnits(), zpos ) );
if( !aFootprint->GetOrientation().IsZero() )
{
fpMatrix = glm::rotate( fpMatrix, (float) aFootprint->GetOrientation().AsRadians(),
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
}
if( aFootprint->IsFlipped() )
{
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
}
double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3dUnits() * UNITS3D_TO_UNITSPCB;
fpMatrix = glm::scale( fpMatrix, SFVEC3F( modelunit_to_3d_units_factor ) );
renderPlaceholderForFootprint( aDstRenderList, fpMatrix, aFootprint, aRenderTransparentOnly, aIsSelected,
1.0f );
}
}
void RENDER_3D_OPENGL::renderPlaceholderForFootprint( std::list<MODELTORENDER>& aDstRenderList,
const glm::mat4& aFpMatrix, const FOOTPRINT* aFootprint,
bool aRenderTransparentOnly, bool aIsSelected, float aOpacity )
{
if( !m_boardAdapter.m_Cfg->m_Render.show_missing_models || !m_placeholderModel )
return;
BOX2I localBox = CalcPlaceholderLocalBox( aFootprint );
float bboxW = std::abs( localBox.GetWidth() ) / pcbIUScale.IU_PER_MM * 0.9f;
float bboxH = std::abs( localBox.GetHeight() ) / pcbIUScale.IU_PER_MM * 0.9f;
float scaleX = bboxW;
float scaleY = bboxH;
float scaleZ = std::min( bboxW, bboxH ) * 0.5f;
VECTOR2I localCenter = localBox.GetCenter();
float offsetX = localCenter.x / pcbIUScale.IU_PER_MM;
float offsetY = -localCenter.y / pcbIUScale.IU_PER_MM;
float offsetZ = scaleZ * 0.5f;
if( aFootprint->IsFlipped() )
offsetY = -offsetY;
glm::mat4 mtx = aFpMatrix;
mtx = glm::translate( mtx, SFVEC3F( offsetX, offsetY, offsetZ ) );
mtx = glm::scale( mtx, SFVEC3F( scaleX, scaleY, scaleZ ) );
bool placeholderOpaque = aOpacity >= 1.0;
if( ( !aRenderTransparentOnly && m_placeholderModel->HasOpaqueMeshes() && placeholderOpaque )
|| ( aRenderTransparentOnly && ( m_placeholderModel->HasTransparentMeshes() || !placeholderOpaque ) ) )
{
aDstRenderList.emplace_back( mtx, m_placeholderModel, aOpacity, aRenderTransparentOnly,
aFootprint->IsSelected() || aIsSelected );
}
}
@ -1530,3 +1609,101 @@ void RENDER_3D_OPENGL::generate3dGrid( GRID3D_TYPE aGridType )
glEndList();
}
void RENDER_3D_OPENGL::createPlaceholderModel()
{
// Unit cube: 1mm × 1mm × 1mm, centered at origin
static SFVEC3F positions[24] = { // +Z (top)
{ -0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
// -Z (bottom)
{ -0.5f, 0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
// +X
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
// -X
{ -0.5f, -0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
// +Y
{ -0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, -0.5f },
{ -0.5f, 0.5f, -0.5f },
// -Y
{ -0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, 0.5f },
{ -0.5f, -0.5f, 0.5f }
};
static SFVEC3F normals[24] = { // +Z
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
{ 0, 0, 1 },
// -Z
{ 0, 0, -1 },
{ 0, 0, -1 },
{ 0, 0, -1 },
{ 0, 0, -1 },
// +X
{ 1, 0, 0 },
{ 1, 0, 0 },
{ 1, 0, 0 },
{ 1, 0, 0 },
// -X
{ -1, 0, 0 },
{ -1, 0, 0 },
{ -1, 0, 0 },
{ -1, 0, 0 },
// +Y
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 },
{ 0, 1, 0 },
// -Y
{ 0, -1, 0 },
{ 0, -1, 0 },
{ 0, -1, 0 },
{ 0, -1, 0 }
};
static unsigned int indices[36] = {
0, 1, 2, 0, 2, 3, // +Z
4, 5, 6, 4, 6, 7, // -Z
8, 9, 10, 8, 10, 11, // +X
12, 13, 14, 12, 14, 15, // -X
16, 17, 18, 16, 18, 19, // +Y
20, 21, 22, 20, 22, 23 // -Y
};
static SMATERIAL material = {
SFVEC3F( 0.2f, 0.1f, 0.0f ), // ambient
SFVEC3F( 1.0f, 0.5f, 0.0f ), // diffuse
SFVEC3F( 0.0f, 0.0f, 0.0f ), // emissive
SFVEC3F( 0.1f, 0.1f, 0.1f ), // specular
0.1f, // shininess
0.4f // transparency
};
static SMESH mesh = { 24, positions, normals, nullptr, nullptr, 36, indices, 0 };
static S3DMODEL model = { 1, &mesh, 1, &material };
m_placeholderModel = new MODEL_3D( model, MATERIAL_MODE::NORMAL );
}

6
3d-viewer/3d_rendering/opengl/render_3d_opengl.h

@ -169,6 +169,7 @@ private:
*/
void load3dModels( REPORTER* aStatusReporter );
void createPlaceholderModel();
struct MODELTORENDER
{
glm::mat4 m_modelWorldMat;
@ -191,6 +192,10 @@ private:
}
};
void renderPlaceholderForFootprint( std::list<MODELTORENDER>& aDstRenderList, const glm::mat4& aFpMatrix,
const FOOTPRINT* aFootprint, bool aRenderTransparentOnly, bool aIsSelected,
float aOpacity );
void renderOpaqueModels( const glm::mat4 &aCameraViewMatrix );
void renderTransparentModels( const glm::mat4 &aCameraViewMatrix );
@ -292,6 +297,7 @@ private:
SHAPE_POLY_SET m_antiBoardPolys; ///< The negative polygon representation of the board
///< outline.
SPHERES_GIZMO* m_spheres_gizmo;
MODEL_3D* m_placeholderModel = nullptr;
};
#endif // RENDER_3D_OPENGL_H

59
3d-viewer/3d_rendering/raytracing/create_scene.cpp

@ -30,6 +30,7 @@
#include "shapes3D/cylinder_3d.h"
#include "shapes3D/frustum_3d.h"
#include "shapes3D/triangle_3d.h"
#include "shapes3D/dummy_block_3d.h"
#include "shapes2D/layer_item_2d.h"
#include "shapes2D/ring_2d.h"
#include "shapes2D/polygon_2d.h"
@ -38,6 +39,7 @@
#include "accelerators/bvh_pbrt.h"
#include "3d_fastmath.h"
#include "3d_math.h"
#include "../3d_placeholder_utils.h"
#include <board.h>
#include <footprint.h>
@ -1911,6 +1913,47 @@ void RENDER_3D_RAYTRACE_BASE::addPadsAndVias()
}
void RENDER_3D_RAYTRACE_BASE::addPlaceholderToRaytracer( CONTAINER_3D& aDstContainer, const FOOTPRINT* aFootprint,
const glm::mat4& aFpMatrix )
{
BOX2I localBox = CalcPlaceholderLocalBox( aFootprint );
float bboxW = std::abs( localBox.GetWidth() ) / pcbIUScale.IU_PER_MM * 0.9f;
float bboxH = std::abs( localBox.GetHeight() ) / pcbIUScale.IU_PER_MM * 0.9f;
float scaleZ = std::min( bboxW, bboxH ) * 0.5f;
VECTOR2I localCenter = localBox.GetCenter();
float offsetX = localCenter.x / pcbIUScale.IU_PER_MM;
float offsetY = -localCenter.y / pcbIUScale.IU_PER_MM;
if( aFootprint->IsFlipped() )
offsetY = -offsetY;
// Build box in model space then transform all 8 corners to world space
SFVEC3F boxMin( offsetX - bboxW * 0.5f, offsetY - bboxH * 0.5f, 0.0f );
SFVEC3F boxMax( offsetX + bboxW * 0.5f, offsetY + bboxH * 0.5f, scaleZ );
BBOX_3D worldBBox;
worldBBox.Reset();
for( int i = 0; i < 8; ++i )
{
SFVEC3F corner( ( i & 1 ) ? boxMax.x : boxMin.x, ( i & 2 ) ? boxMax.y : boxMin.y,
( i & 4 ) ? boxMax.z : boxMin.z );
glm::vec4 transformed = aFpMatrix * glm::vec4( corner, 1.0f );
worldBBox.Union( SFVEC3F( transformed ) );
}
DUMMY_BLOCK* placeholder = new DUMMY_BLOCK( worldBBox );
placeholder->SetBoardItem( const_cast<FOOTPRINT*>( aFootprint ) );
placeholder->SetMaterial( &m_materials.m_EpoxyBoard );
placeholder->SetColor( SFVEC3F( 1.0f, 0.5f, 0.0f ) );
aDstContainer.Add( placeholder );
}
void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer,
bool aSkipMaterialInformation )
{
@ -1928,8 +1971,10 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer,
// Go for all footprints
for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
{
if( !fp->Models().empty()
&& m_boardAdapter.IsFootprintShown( fp ) )
bool hasModels = !fp->Models().empty();
bool showMissing = m_boardAdapter.m_Cfg->m_Render.show_missing_models;
if( ( hasModels || showMissing ) && m_boardAdapter.IsFootprintShown( fp ) )
{
double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
@ -2026,6 +2071,16 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer,
addModels( aDstContainer, modelPtr, modelMatrix, (float) model.m_Opacity,
aSkipMaterialInformation, fp );
}
else if( showMissing )
{
addPlaceholderToRaytracer( aDstContainer, fp, fpMatrix );
}
}
// Footprint with no models assigned at all
if( !hasModels && showMissing )
{
addPlaceholderToRaytracer( aDstContainer, fp, fpMatrix );
}
}
}

2
3d-viewer/3d_rendering/raytracing/render_3d_raytrace_base.h

@ -121,6 +121,8 @@ protected:
bool aIsFront );
void backfillPostMachine();
void load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMaterialInformation );
void addPlaceholderToRaytracer( CONTAINER_3D& aDstContainer, const FOOTPRINT* aFootprint,
const glm::mat4& aFpMatrix );
void addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
const glm::mat4& aModelMatrix, float aFPOpacity,
bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem );

17
3d-viewer/3d_rendering/raytracing/shapes3D/dummy_block_3d.cpp

@ -50,10 +50,23 @@ bool DUMMY_BLOCK::Intersect( const RAY& aRay, HITINFO& aHitInfo ) const
aHitInfo.m_tHit = t;
aHitInfo.m_HitPoint = aRay.at( t );
if( aRay.m_dirIsNeg[2] )
// Determine which face was hit by checking which box face
// the hit point is closest to
const SFVEC3F hitPt = aHitInfo.m_HitPoint;
const float eps = 0.0001f;
if( std::abs( hitPt.x - m_bbox.Min().x ) < eps )
aHitInfo.m_HitNormal = SFVEC3F( -1.0f, 0.0f, 0.0f );
else if( std::abs( hitPt.x - m_bbox.Max().x ) < eps )
aHitInfo.m_HitNormal = SFVEC3F( 1.0f, 0.0f, 0.0f );
else if( std::abs( hitPt.y - m_bbox.Min().y ) < eps )
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, -1.0f, 0.0f );
else if( std::abs( hitPt.y - m_bbox.Max().y ) < eps )
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 1.0f, 0.0f );
else if( aRay.m_dirIsNeg[2] )
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f );
else
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f,-1.0f );
aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, -1.0f );
m_material->Generate( aHitInfo.m_HitNormal, aRay, aHitInfo );

2
3d-viewer/3d_viewer/3d_menubar.cpp

@ -130,6 +130,8 @@ void EDA_3D_VIEWER_FRAME::doReCreateMenuBar()
prefsMenu->Add( EDA_3D_ACTIONS::toggleRaytacing, ACTION_MENU::CHECK );
prefsMenu->Add( EDA_3D_ACTIONS::toggleShowMissingModels, ACTION_MENU::CHECK );
prefsMenu->Add( ACTIONS::openPreferences );
prefsMenu->Add( _( "Reset to Default Settings" ), ID_MENU3D_RESET_DEFAULTS, BITMAPS::tools );

6
3d-viewer/3d_viewer/eda_3d_viewer_frame.cpp

@ -245,6 +245,11 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions()
{
return m_boardAdapter.m_Cfg->m_Render.engine != RENDER_ENGINE::OPENGL;
};
auto showMissingModels =
[this]( const SELECTION& aSel )
{
return m_boardAdapter.m_Cfg->m_Render.show_missing_models;
};
auto showTH =
[this]( const SELECTION& aSel )
{
@ -293,6 +298,7 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions()
};
mgr->SetConditions( EDA_3D_ACTIONS::toggleRaytacing, ACTION_CONDITIONS().Check( raytracing ) );
mgr->SetConditions( EDA_3D_ACTIONS::toggleShowMissingModels, ACTION_CONDITIONS().Check( showMissingModels ) );
mgr->SetConditions( EDA_3D_ACTIONS::showTHT, ACTION_CONDITIONS().Check( showTH ) );
mgr->SetConditions( EDA_3D_ACTIONS::showSMD, ACTION_CONDITIONS().Check( showSMD ) );

1
3d-viewer/3d_viewer/eda_3d_viewer_settings.cpp

@ -408,6 +408,7 @@ EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() :
&m_Render.use_board_editor_copper_colors, false ) );
m_params.emplace_back( new PARAM<bool>( "render.preview_show_board_body",
&m_Render.preview_show_board_body, true ) );
m_params.emplace_back( new PARAM<bool>( "render.show_missing_models", &m_Render.show_missing_models, false ) );
m_params.emplace_back( new PARAM<bool>( "camera.animation_enabled",
&m_Camera.animation_enabled, true ) );
m_params.emplace_back( new PARAM<int>( "camera.moving_speed_multiplier",

1
3d-viewer/3d_viewer/eda_3d_viewer_settings.h

@ -155,6 +155,7 @@ public:
bool differentiate_plated_copper;
bool use_board_editor_copper_colors; // OpenGL only
bool preview_show_board_body;
bool show_missing_models; // Show placeholder for missing 3D models
/**
* return true if platted copper aeras and non platted copper areas must be drawn

7
3d-viewer/3d_viewer/tools/eda_3d_actions.cpp

@ -57,6 +57,13 @@ TOOL_ACTION EDA_3D_ACTIONS::toggleRaytacing( TOOL_ACTION_ARGS()
.Icon( BITMAPS::ray_tracing )
.ToolbarState( TOOLBAR_STATE::TOGGLE) );
TOOL_ACTION EDA_3D_ACTIONS::toggleShowMissingModels( TOOL_ACTION_ARGS()
.Name( "3DViewer.Control.toggleShowMissingModels" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Show parts without 3D model" ) )
.Tooltip( _( "Display a placeholder for footprints with missing 3D models" ) )
.ToolbarState( TOOLBAR_STATE::TOGGLE ) );
TOOL_ACTION EDA_3D_ACTIONS::copyToClipboard( TOOL_ACTION_ARGS()
.Name( "3DViewer.Control.copyToClipboard" )
.Scope( AS_GLOBAL )

1
3d-viewer/3d_viewer/tools/eda_3d_actions.h

@ -44,6 +44,7 @@ public:
static TOOL_ACTION reloadBoard;
static TOOL_ACTION toggleRaytacing;
static TOOL_ACTION toggleShowMissingModels;
static TOOL_ACTION copyToClipboard;
static TOOL_ACTION exportImage;

10
3d-viewer/3d_viewer/tools/eda_3d_controller.cpp

@ -384,6 +384,15 @@ int EDA_3D_CONTROLLER::ToggleRaytracing( const TOOL_EVENT& aEvent )
}
int EDA_3D_CONTROLLER::ToggleShowMissingModels( const TOOL_EVENT& aEvent )
{
m_boardAdapter->m_Cfg->m_Render.show_missing_models = !m_boardAdapter->m_Cfg->m_Render.show_missing_models;
m_canvas->ReloadRequest();
m_canvas->Request_refresh();
return 0;
}
int EDA_3D_CONTROLLER::ExportImage( const TOOL_EVENT& aEvent )
{
EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_toolMgr->GetToolHolder() );
@ -421,6 +430,7 @@ void EDA_3D_CONTROLLER::setTransitions()
// Miscellaneous control
Go( &EDA_3D_CONTROLLER::ReloadBoard, EDA_3D_ACTIONS::reloadBoard.MakeEvent() );
Go( &EDA_3D_CONTROLLER::ToggleRaytracing, EDA_3D_ACTIONS::toggleRaytacing.MakeEvent() );
Go( &EDA_3D_CONTROLLER::ToggleShowMissingModels, EDA_3D_ACTIONS::toggleShowMissingModels.MakeEvent() );
Go( &EDA_3D_CONTROLLER::ExportImage, EDA_3D_ACTIONS::copyToClipboard.MakeEvent() );
Go( &EDA_3D_CONTROLLER::ExportImage, EDA_3D_ACTIONS::exportImage.MakeEvent() );

1
3d-viewer/3d_viewer/tools/eda_3d_controller.h

@ -85,6 +85,7 @@ public:
int ReloadBoard( const TOOL_EVENT& aEvent );
int ToggleRaytracing( const TOOL_EVENT& aEvent );
int ToggleShowMissingModels( const TOOL_EVENT& aEvent );
int ExportImage( const TOOL_EVENT& aEvent );
private:

1
3d-viewer/CMakeLists.txt

@ -73,6 +73,7 @@ set(3D-VIEWER_SRCS
${DIR_RAY_3D}/round_segment_3d.cpp
${DIR_RAY_3D}/triangle_3d.cpp
3d_rendering/buffers_debug.cpp
3d_rendering/3d_placeholder_utils.cpp
3d_rendering/render_3d_base.cpp
3d_rendering/color_rgba.cpp
3d_rendering/image.cpp

4
3d-viewer/dialogs/panel_preview_3d_model.cpp

@ -221,6 +221,10 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
loadSettings();
// Don't show placeholder models in the footprint properties 3D preview
if( m_boardAdapter.m_Cfg )
m_boardAdapter.m_Cfg->m_Render.show_missing_models = false;
// Create the manager
m_toolManager = new TOOL_MANAGER;
m_toolManager->SetEnvironment( m_dummyBoard, nullptr, nullptr, nullptr, this );

Loading…
Cancel
Save