From ef4f0b49fc0ee347338aaf77db557a1be53f6fdd Mon Sep 17 00:00:00 2001 From: Mario Luzeiro Date: Sun, 15 May 2022 09:38:46 +0100 Subject: [PATCH] 3D-Viewer, raytracing: implement bevel edges on item layers --- 3d-viewer/3d_canvas/board_adapter.cpp | 8 ++- .../raytracing/shapes3D/layer_item_3d.cpp | 51 ++++++++++++++++--- common/advanced_config.cpp | 28 ++++++++++ include/advanced_config.h | 13 +++++ 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/3d-viewer/3d_canvas/board_adapter.cpp b/3d-viewer/3d_canvas/board_adapter.cpp index 951104f7a3..b020fd9de9 100644 --- a/3d-viewer/3d_canvas/board_adapter.cpp +++ b/3d-viewer/3d_canvas/board_adapter.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015-2016 Mario Luzeiro + * Copyright (C) 2015-2022 Mario Luzeiro * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or @@ -37,6 +37,7 @@ #include #include #include +#include #define DEFAULT_BOARD_THICKNESS Millimeter2iu( 1.6 ) @@ -62,6 +63,9 @@ KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSolderPaste; KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultSurfaceFinish; KIGFX::COLOR4D BOARD_ADAPTER::g_DefaultBoardBody; +// To be used in Raytracing render to create bevels on layer items +float g_BevelThickness3DU = 0.0f; + static bool g_ColorsLoaded = false; /** @@ -349,6 +353,8 @@ void BOARD_ADAPTER::InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningR m_nonCopperLayerThickness3DU = DEFAULT_TECH_LAYER_THICKNESS * m_biuTo3Dunits; m_solderPasteLayerThickness3DU = SOLDERPASTE_LAYER_THICKNESS * m_biuTo3Dunits; + g_BevelThickness3DU = Millimeter2iu( ADVANCED_CFG::GetCfg().m_3DRT_BevelHeight_um / 1000.0 ) * m_biuTo3Dunits; + if( m_board ) { const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); diff --git a/3d-viewer/3d_rendering/raytracing/shapes3D/layer_item_3d.cpp b/3d-viewer/3d_rendering/raytracing/shapes3D/layer_item_3d.cpp index 1072298b79..e5185c94aa 100644 --- a/3d-viewer/3d_rendering/raytracing/shapes3D/layer_item_3d.cpp +++ b/3d-viewer/3d_rendering/raytracing/shapes3D/layer_item_3d.cpp @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015-2016 Mario Luzeiro - * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2015-2022 Mario Luzeiro + * Copyright (C) 1992-2022 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 @@ -25,6 +25,10 @@ #include "layer_item_3d.h" #include "3d_fastmath.h" #include +#include + + +extern float g_BevelThickness3DU; LAYER_ITEM::LAYER_ITEM( const OBJECT_2D* aObject2D, float aZMin, float aZMax ) : @@ -223,17 +227,52 @@ bool LAYER_ITEM::Intersect( const RAY& aRay, HITINFO& aHitInfo ) const { aHitInfo.m_tHit = t; aHitInfo.m_HitPoint = hitPoint; + aHitInfo.pHitObject = this; + + const float zNormalDir = hit_top?1.0f:hit_bot?-1.0f:0.0f; if( ( outNormal.x == 0.0f ) && ( outNormal.y == 0.0f ) ) { - aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, 1.0f ); + aHitInfo.m_HitNormal = SFVEC3F( 0.0f, 0.0f, zNormalDir ); } else { - aHitInfo.m_HitNormal = SFVEC3F( outNormal.x, outNormal.y, 0.0f ); - } + // Calculate smooth bevel normal + float zBend = 0.0f; - aHitInfo.pHitObject = this; + if( hit_top || hit_bot ) + { + float zDistanceToTopOrBot; + + // Calculate the distance from hitpoint z to the Max/Min z of the layer + if( hit_top ) + { + zDistanceToTopOrBot = ( m_bbox.Max().z - hitPoint.z ); + } + else + { + zDistanceToTopOrBot = ( hitPoint.z - m_bbox.Min().z ); + } + + // For items that are > than g_BevelThickness3DU + // (eg on board vias / plated holeS) use a factor based on m_bbox.GetExtent().z + const float bevelThickness = glm::max( g_BevelThickness3DU, + m_bbox.GetExtent().z * + (float)ADVANCED_CFG::GetCfg().m_3DRT_BevelExtentFactor ); + + if( ( zDistanceToTopOrBot > 0.0f ) && ( zDistanceToTopOrBot < bevelThickness ) ) + { + // Invert and Normalize the distance 0..1 + zBend = ( bevelThickness - zDistanceToTopOrBot ) / bevelThickness; + } + } + + const SFVEC3F normalLateral = SFVEC3F( outNormal.x, outNormal.y, 0.0f ); + const SFVEC3F normalTopBot = SFVEC3F( 0.0f, 0.0f, zNormalDir ); + + // Interpolate between the regular lateral normal and the top/bot normal + aHitInfo.m_HitNormal = glm::mix( normalLateral, normalTopBot, zBend ); + } m_material->Generate( aHitInfo.m_HitNormal, aRay, aHitInfo ); diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index cea0e66e55..4067065d96 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -192,9 +192,22 @@ static const wxChar AllowManualCanvasScale[] = wxT( "AllowManualCanvasScale" ); static const wxChar UpdateUIEventInterval[] = wxT( "UpdateUIEventInterval" ); static const wxChar AllowTeardrops[] = wxT( "AllowTeardrops" ); + +static const wxChar V3DRT_BevelHeight_um[] = wxT( "V3DRT_BevelHeight_um" ); + +static const wxChar V3DRT_BevelExtentFactor[] = wxT( "V3DRT_BevelExtentFactor" ); } // namespace KEYS +/** + * List of known groups for advanced configuration options. + * + */ +namespace AC_GROUPS +{ +static const wxChar V3D_RayTracing[] = wxT( "G_3DV_RayTracing" ); +} + /* * Get a simple string for common parameters. * @@ -308,6 +321,9 @@ ADVANCED_CFG::ADVANCED_CFG() m_AllowTeardrops = false; m_ShowRepairSchematic = false; + m_3DRT_BevelHeight_um = 30; + m_3DRT_BevelExtentFactor = 1.0 / 16.0; + loadFromConfigFile(); } @@ -440,6 +456,18 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowTeardrops, &m_AllowTeardrops, m_AllowTeardrops ) ); + configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::V3DRT_BevelHeight_um, + &m_3DRT_BevelHeight_um, m_3DRT_BevelHeight_um, + 0, std::numeric_limits::max(), + AC_GROUPS::V3D_RayTracing ) ); + + configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::V3DRT_BevelExtentFactor, + &m_3DRT_BevelExtentFactor, m_3DRT_BevelExtentFactor, + 0.0, 100.0, + AC_GROUPS::V3D_RayTracing ) ); + + + // Special case for trace mask setting...we just grab them and set them immediately // Because we even use wxLogTrace inside of advanced config wxString traceMasks = ""; diff --git a/include/advanced_config.h b/include/advanced_config.h index 561f5cb29f..7006a7ee1f 100644 --- a/include/advanced_config.h +++ b/include/advanced_config.h @@ -225,6 +225,19 @@ public: */ bool m_AllowTeardrops; + /** + * 3D-Viewer, Raytracing + * Bevel height of layer items. Controls the start of curvature normal on the edge. + * Value is in micrometre. Good values should be arround or less than the copper thickness. + */ + int m_3DRT_BevelHeight_um; + + /** + * 3D-Viewer, Raytracing + * Factor applied to Extent.z of the item layer, used on calculation of the bevel's height. + */ + double m_3DRT_BevelExtentFactor; + private: ADVANCED_CFG();