3D Viewer: Fix zoom limit calculations
Fixes https://gitlab.com/kicad/code/kicad/issues/9407 Fixes https://gitlab.com/kicad/code/kicad/issues/8805
This commit is contained in:
parent
363214d252
commit
cf3a979711
|
@ -483,18 +483,25 @@ void EDA_3D_CANVAS::DoRePaint()
|
|||
{
|
||||
m_3d_render->SetCurWindowSize( clientSize );
|
||||
|
||||
bool reloadRaytracingForIntersectionCalculations = false;
|
||||
bool reloadRaytracingForCalculations = false;
|
||||
|
||||
if( m_boardAdapter.GetRenderEngine() == RENDER_ENGINE::OPENGL
|
||||
&& m_3d_render_opengl->IsReloadRequestPending() )
|
||||
{
|
||||
reloadRaytracingForIntersectionCalculations = true;
|
||||
reloadRaytracingForCalculations = true;
|
||||
}
|
||||
|
||||
requested_redraw = m_3d_render->Redraw( m_mouse_was_moved || m_camera_is_moving,
|
||||
&activityReporter, &warningReporter );
|
||||
|
||||
if( reloadRaytracingForIntersectionCalculations )
|
||||
// Raytracer renderer is responsible for some features also used by the OpenGL
|
||||
// renderer.
|
||||
// FIXME: Presumably because raytracing renderer reload is called only after current
|
||||
// renderer redraw, the old zoom value stays for a single frame. This is ugly, but only
|
||||
// cosmetic, so I'm not fixing that for now: I don't know how to do this without
|
||||
// reloading twice (maybe it's not too bad of an idea?) or doing a complicated
|
||||
// refactor.
|
||||
if( reloadRaytracingForCalculations )
|
||||
m_3d_render_raytracing->Reload( nullptr, nullptr, true );
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
|
@ -510,7 +517,7 @@ void EDA_3D_CANVAS::DoRePaint()
|
|||
|
||||
if( m_render_pivot )
|
||||
{
|
||||
const float scale = glm::min( m_camera.ZoomGet(), 1.0f );
|
||||
const float scale = glm::min( m_camera.GetZoom(), 1.0f );
|
||||
render_pivot( curtime_delta_s, scale * scale );
|
||||
}
|
||||
|
||||
|
@ -584,7 +591,7 @@ void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent& event )
|
|||
if( m_camera_is_moving )
|
||||
return;
|
||||
|
||||
float delta_move = m_delta_move_step_factor * m_camera.ZoomGet();
|
||||
float delta_move = m_delta_move_step_factor * m_camera.GetZoom();
|
||||
|
||||
if( m_boardAdapter.GetFlag( FL_MOUSEWHEEL_PANNING ) )
|
||||
delta_move *= 0.01f * event.GetWheelRotation();
|
||||
|
@ -945,7 +952,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
|||
if( m_camera_is_moving )
|
||||
return false;
|
||||
|
||||
const float delta_move = m_delta_move_step_factor * m_camera.ZoomGet();
|
||||
const float delta_move = m_delta_move_step_factor * m_camera.GetZoom();
|
||||
const float arrow_moving_time_speed = 8.0f;
|
||||
bool handled = false;
|
||||
|
||||
|
@ -987,7 +994,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
|||
m_camera.SetInterpolateMode( CAMERA_INTERPOLATION::BEZIER );
|
||||
m_camera.SetT0_and_T1_current_T();
|
||||
m_camera.Reset_T1();
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.ZoomGet(), 1/1.26f ), 1.26f ) );
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.GetZoom(), 1 / 1.26f ), 1.26f ) );
|
||||
return true;
|
||||
|
||||
case WXK_END:
|
||||
|
@ -1023,7 +1030,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
|||
m_camera.SetInterpolateMode( CAMERA_INTERPOLATION::BEZIER );
|
||||
m_camera.SetT0_and_T1_current_T();
|
||||
m_camera.Reset_T1();
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.ZoomGet(), 0.5f ), 1.125f ) );
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.GetZoom(), 0.5f ), 1.125f ) );
|
||||
return true;
|
||||
|
||||
case ID_VIEW3D_RIGHT:
|
||||
|
@ -1069,7 +1076,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
|||
m_camera.SetInterpolateMode( CAMERA_INTERPOLATION::BEZIER );
|
||||
m_camera.SetT0_and_T1_current_T();
|
||||
m_camera.Reset_T1();
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.ZoomGet(), 0.5f ), 1.125f ) );
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.GetZoom(), 0.5f ), 1.125f ) );
|
||||
return true;
|
||||
|
||||
case ID_VIEW3D_BOTTOM:
|
||||
|
@ -1077,7 +1084,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
|||
m_camera.SetT0_and_T1_current_T();
|
||||
m_camera.Reset_T1();
|
||||
m_camera.RotateY_T1( glm::radians( 179.999f ) ); // Rotation = 180 - epsilon
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.ZoomGet(), 0.5f ), 1.125f ) );
|
||||
request_start_moving_camera( glm::min( glm::max( m_camera.GetZoom(), 0.5f ), 1.125f ) );
|
||||
return true;
|
||||
|
||||
case ID_VIEW3D_FLIP:
|
||||
|
|
|
@ -47,8 +47,8 @@ inline void normalise2PI( float& aAngle )
|
|||
const wxChar *CAMERA::m_logTrace = wxT( "KI_TRACE_CAMERA" );
|
||||
|
||||
|
||||
#define MIN_ZOOM 0.10f
|
||||
#define MAX_ZOOM 2.00f
|
||||
#define DEFAULT_MIN_ZOOM 0.10f
|
||||
#define DEFAULT_MAX_ZOOM 1.20f
|
||||
|
||||
|
||||
CAMERA::CAMERA( float aInitialDistance )
|
||||
|
@ -61,6 +61,9 @@ CAMERA::CAMERA( float aInitialDistance )
|
|||
m_projectionType = PROJECTION_TYPE::PERSPECTIVE;
|
||||
m_interpolation_mode = CAMERA_INTERPOLATION::BEZIER;
|
||||
|
||||
m_minZoom = DEFAULT_MIN_ZOOM;
|
||||
m_maxZoom = DEFAULT_MAX_ZOOM;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -118,6 +121,21 @@ void CAMERA::Reset_T1()
|
|||
}
|
||||
|
||||
|
||||
void CAMERA::zoomChanged()
|
||||
{
|
||||
if( m_zoom < m_minZoom )
|
||||
m_zoom = m_minZoom;
|
||||
|
||||
if( m_zoom > m_maxZoom )
|
||||
m_zoom = m_maxZoom;
|
||||
|
||||
m_camera_pos.z = m_camera_pos_init.z * m_zoom;
|
||||
|
||||
updateViewMatrix();
|
||||
rebuildProjection();
|
||||
}
|
||||
|
||||
|
||||
void CAMERA::updateViewMatrix()
|
||||
{
|
||||
m_viewMatrix = glm::translate( glm::mat4( 1.0f ), m_camera_pos ) *
|
||||
|
@ -159,9 +177,7 @@ void CAMERA::rebuildProjection()
|
|||
return;
|
||||
|
||||
m_frustum.ratio = (float) m_windowSize.x / (float)m_windowSize.y;
|
||||
|
||||
// Consider that we can render double the length multiplied by the 2/sqrt(2)
|
||||
m_frustum.farD = glm::length( m_camera_pos_init ) * 2.0f * ( 2.0f * sqrtf( 2.0f ) );
|
||||
m_frustum.farD = glm::length( m_camera_pos_init ) * m_maxZoom * 2.0f;
|
||||
|
||||
switch( m_projectionType )
|
||||
{
|
||||
|
@ -384,6 +400,12 @@ const glm::mat4& CAMERA::GetProjectionMatrixInv() const
|
|||
}
|
||||
|
||||
|
||||
float CAMERA::GetCameraMinDimension() const
|
||||
{
|
||||
return -m_camera_pos_init.z * m_frustum.tang;
|
||||
}
|
||||
|
||||
|
||||
void CAMERA::ResetXYpos()
|
||||
{
|
||||
m_parametersChanged = true;
|
||||
|
@ -459,40 +481,34 @@ void CAMERA::ZoomReset()
|
|||
|
||||
bool CAMERA::Zoom( float aFactor )
|
||||
{
|
||||
if( ( m_zoom == MIN_ZOOM && aFactor > 1 ) || ( m_zoom == MAX_ZOOM && aFactor < 1 )
|
||||
|| aFactor == 1 )
|
||||
if( ( m_zoom == m_minZoom && aFactor > 1 ) || ( m_zoom == m_maxZoom && aFactor < 1 )
|
||||
|| aFactor == 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_zoom /= aFactor;
|
||||
|
||||
if( m_zoom <= MIN_ZOOM )
|
||||
m_zoom = MIN_ZOOM;
|
||||
|
||||
if( m_zoom >= MAX_ZOOM )
|
||||
m_zoom = MAX_ZOOM;
|
||||
|
||||
m_camera_pos.z = m_camera_pos_init.z * m_zoom;
|
||||
|
||||
updateViewMatrix();
|
||||
rebuildProjection();
|
||||
|
||||
zoomChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CAMERA::Zoom_T1( float aFactor )
|
||||
{
|
||||
if( ( m_zoom == MIN_ZOOM && aFactor > 1 ) || ( m_zoom == MAX_ZOOM && aFactor < 1 )
|
||||
|| aFactor == 1 )
|
||||
if( ( m_zoom == m_minZoom && aFactor > 1 ) || ( m_zoom == m_maxZoom && aFactor < 1 )
|
||||
|| aFactor == 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_zoom_t1 = m_zoom / aFactor;
|
||||
|
||||
if( m_zoom_t1 < MIN_ZOOM )
|
||||
m_zoom_t1 = MIN_ZOOM;
|
||||
if( m_zoom_t1 < m_minZoom )
|
||||
m_zoom_t1 = m_minZoom;
|
||||
|
||||
if( m_zoom_t1 > MAX_ZOOM )
|
||||
m_zoom_t1 = MAX_ZOOM;
|
||||
if( m_zoom_t1 > m_maxZoom )
|
||||
m_zoom_t1 = m_maxZoom;
|
||||
|
||||
m_camera_pos_t1.z = m_camera_pos_init.z * m_zoom_t1;
|
||||
|
||||
|
@ -500,12 +516,6 @@ bool CAMERA::Zoom_T1( float aFactor )
|
|||
}
|
||||
|
||||
|
||||
float CAMERA::ZoomGet() const
|
||||
{
|
||||
return m_zoom;
|
||||
}
|
||||
|
||||
|
||||
void CAMERA::RotateX( float aAngleInRadians )
|
||||
{
|
||||
m_rotate_aux.x += aAngleInRadians;
|
||||
|
|
|
@ -128,6 +128,9 @@ public:
|
|||
const SFVEC3F& GetLookAtPos_T1() const { return m_lookat_pos_t1; }
|
||||
|
||||
const SFVEC3F& GetCameraPos() const { return m_camera_pos; }
|
||||
const SFVEC3F& GetCameraInitPos() const { return m_camera_pos_init; }
|
||||
|
||||
float GetCameraMinDimension() const;
|
||||
|
||||
/**
|
||||
* Calculate a new mouse drag position
|
||||
|
@ -171,7 +174,21 @@ public:
|
|||
|
||||
bool Zoom_T1( float aFactor );
|
||||
|
||||
float ZoomGet() const ;
|
||||
float GetZoom() const { return m_zoom; }
|
||||
|
||||
float GetMinZoom() { return m_minZoom; }
|
||||
void SetMinZoom( float minZoom )
|
||||
{
|
||||
m_minZoom = minZoom;
|
||||
zoomChanged();
|
||||
}
|
||||
|
||||
float GetMaxZoom() { return m_maxZoom; }
|
||||
void SetMaxZoom( float maxZoom )
|
||||
{
|
||||
m_maxZoom = maxZoom;
|
||||
zoomChanged();
|
||||
}
|
||||
|
||||
void RotateX( float aAngleInRadians );
|
||||
void RotateY( float aAngleInRadians );
|
||||
|
@ -236,6 +253,7 @@ public:
|
|||
void MakeRayAtCurrrentMousePosition( SFVEC3F& aOutOrigin, SFVEC3F& aOutDirection ) const;
|
||||
|
||||
protected:
|
||||
void zoomChanged();
|
||||
void rebuildProjection();
|
||||
void updateFrustum();
|
||||
void updateViewMatrix();
|
||||
|
@ -249,6 +267,12 @@ protected:
|
|||
float m_zoom_t0;
|
||||
float m_zoom_t1;
|
||||
|
||||
/**
|
||||
* Possible 3D zoom range
|
||||
*/
|
||||
float m_minZoom;
|
||||
float m_maxZoom;
|
||||
|
||||
/**
|
||||
* The window size that this camera is working.
|
||||
*/
|
||||
|
|
|
@ -917,6 +917,21 @@ void RENDER_3D_RAYTRACE::Reload( REPORTER* aStatusReporter, REPORTER* aWarningRe
|
|||
}
|
||||
}
|
||||
|
||||
// Set min. and max. zoom range. This doesn't really fit here, but moving this outside of this
|
||||
// class would require reimplementing bounding box calculation (feel free to do this if you
|
||||
// have time and patience).
|
||||
if( m_objectContainer.GetList().size() > 0 )
|
||||
{
|
||||
/*float ratio = std::max( 1.0f, m_objectContainer.GetBBox().GetMaxDimension()
|
||||
/ m_boardAdapter.GetBBox().GetMaxDimension() );*/
|
||||
float ratio =
|
||||
std::max( 1.0f, m_objectContainer.GetBBox().GetMaxDimension() / RANGE_SCALE_3D );
|
||||
m_camera.SetMaxZoom( m_camera.GetMaxZoom() * ratio );
|
||||
|
||||
m_camera.SetMinZoom( static_cast<float>( MIN_DISTANCE_IU * m_boardAdapter.BiuTo3dUnits()
|
||||
/ -m_camera.GetCameraInitPos().z ) );
|
||||
}
|
||||
|
||||
// Create an accelerator
|
||||
delete m_accelerator;
|
||||
m_accelerator = new BVH_PBRT( m_objectContainer, 8, SPLITMETHOD::MIDDLE );
|
||||
|
|
|
@ -55,6 +55,10 @@ typedef enum
|
|||
class RENDER_3D_RAYTRACE : public RENDER_3D_BASE
|
||||
{
|
||||
public:
|
||||
// TODO: Take into account board thickness so that the camera won't move inside of the board
|
||||
// when facing it perpendicularly.
|
||||
static constexpr float MIN_DISTANCE_IU = 4 * PCB_IU_PER_MM;
|
||||
|
||||
explicit RENDER_3D_RAYTRACE( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdapter, CAMERA& aCamera );
|
||||
|
||||
~RENDER_3D_RAYTRACE();
|
||||
|
|
Loading…
Reference in New Issue