KiCad PCB EDA Suite
eda_3d_canvas.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
30 #include <GL/glew.h> // Must be included first
31 
32 #include "../common_ogl/openGL_includes.h"
33 #include "../common_ogl/ogl_utils.h"
34 #include "eda_3d_canvas.h"
35 #include "../3d_viewer_id.h"
36 #include "../3d_rendering/3d_render_raytracing/c3d_render_raytracing.h"
37 #include "../3d_viewer/eda_3d_viewer.h"
38 #include "../3d_rendering/test_cases.h"
39 #include <class_board.h>
40 #include "status_text_reporter.h"
41 #include <gl_context_mgr.h>
42 #include <profile.h> // To use GetRunningMicroSecs or an other profiling utility
43 #include <bitmaps.h>
44 
51 const wxChar * EDA_3D_CANVAS::m_logTrace = wxT( "KI_TRACE_EDA_3D_CANVAS" );
52 
54 
55 
56 BEGIN_EVENT_TABLE( EDA_3D_CANVAS, wxGLCanvas )
57  EVT_PAINT( EDA_3D_CANVAS::OnPaint )
58  EVT_CHAR( EDA_3D_CANVAS::OnKeyEvent )
59  EVT_CHAR_HOOK( EDA_3D_CANVAS::OnCharHook )
60 
61  // mouse events
62  EVT_LEFT_DOWN( EDA_3D_CANVAS::OnLeftDown )
63  EVT_LEFT_UP( EDA_3D_CANVAS::OnLeftUp )
64  EVT_MIDDLE_UP( EDA_3D_CANVAS::OnMiddleUp )
65  EVT_MIDDLE_DOWN( EDA_3D_CANVAS::OnMiddleDown)
66  EVT_RIGHT_DOWN( EDA_3D_CANVAS::OnRightClick )
67  EVT_MOUSEWHEEL( EDA_3D_CANVAS::OnMouseWheel )
68  EVT_MOTION( EDA_3D_CANVAS::OnMouseMove )
69 
70 #ifdef USE_OSX_MAGNIFY_EVENT
71  EVT_MAGNIFY( EDA_3D_CANVAS::OnMagnify )
72 #endif
73 
74  // other events
75  EVT_ERASE_BACKGROUND( EDA_3D_CANVAS::OnEraseBackground )
77  ID_POPUP_3D_VIEW_END, EDA_3D_CANVAS::OnPopUpMenu )
78 
79  EVT_CLOSE( EDA_3D_CANVAS::OnCloseWindow )
80 END_EVENT_TABLE()
81 
82 
83 EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow *aParent,
84  const int *aAttribList,
85  BOARD *aBoard,
86  CINFO3D_VISU &aSettings , S3D_CACHE *a3DCachePointer ) :
87 
88  wxGLCanvas( aParent,
89  wxID_ANY,
90  aAttribList,
91  wxDefaultPosition,
92  wxDefaultSize,
93  wxFULL_REPAINT_ON_RESIZE
94  ),
95  m_settings( aSettings )
96 {
97  // Run test cases in debug mode, once.
98  //DBG( Run_3d_viewer_test_cases() );
99 
100  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::EDA_3D_CANVAS" ) );
101 
102  m_editing_timeout_timer.SetOwner( this );
103  Connect( m_editing_timeout_timer.GetId(),
104  wxEVT_TIMER,
105  wxTimerEventHandler( EDA_3D_CANVAS::OnTimerTimeout_Editing ),
106  NULL,
107  this );
108 
109  m_redraw_trigger_timer.SetOwner( this );
110  Connect( m_redraw_trigger_timer.GetId(),
111  wxEVT_TIMER,
112  wxTimerEventHandler( EDA_3D_CANVAS::OnTimerTimeout_Redraw ),
113  NULL,
114  this );
115 
116  m_mouse_was_moved = false;
117  m_mouse_is_moving = false;
118  m_camera_is_moving = false;
119  m_render_pivot = false;
120  m_camera_moving_speed = 1.0f;
121 
122  m_strtime_camera_movement = 0;
123 
124  m_is_opengl_initialized = false;
125 
126  m_render_raytracing_was_requested = false;
127 
128  m_parentStatusBar = NULL;
129  m_glRC = NULL;
130 
131  m_3d_render = NULL;
132 
133  m_3d_render_raytracing = new C3D_RENDER_RAYTRACING( aSettings );
134  m_3d_render_ogl_legacy = new C3D_RENDER_OGL_LEGACY( aSettings );
135 
136  wxASSERT( m_3d_render_raytracing != NULL );
137  wxASSERT( m_3d_render_ogl_legacy != NULL );
138 
139  RenderEngineChanged();
140 
141  wxASSERT( aBoard != NULL );
142  m_settings.SetBoard( aBoard );
143 
144  wxASSERT( a3DCachePointer != NULL );
145  m_settings.Set3DCacheManager( a3DCachePointer );
146 }
147 
148 
150 {
151  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::~EDA_3D_CANVAS" ) );
152 
153  releaseOpenGL();
154 }
155 
156 
158 {
159  if( m_glRC )
160  {
162 
163  delete m_3d_render_raytracing;
164  m_3d_render_raytracing = NULL;
165 
166  delete m_3d_render_ogl_legacy;
167  m_3d_render_ogl_legacy = NULL;
168 
169  // This is just a copy of a pointer, can safelly be set to NULL
170  m_3d_render = NULL;
171 
174  m_glRC = NULL;
175  }
176 }
177 
178 
179 void EDA_3D_CANVAS::OnCloseWindow( wxCloseEvent &event )
180 {
181  releaseOpenGL();
182 
183  event.Skip();
184 }
185 
186 
188 {
189  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::initializeOpenGL" ) );
190 
191  const GLenum err = glewInit();
192 
193  if( GLEW_OK != err )
194  {
195  const wxString msgError = (const char*) glewGetErrorString( err );
196 
197  wxLogMessage( msgError );
198 
199  return false;
200  }
201  else
202  {
203  wxLogTrace( m_logTrace,
204  wxString( wxT( "EDA_3D_CANVAS::initializeOpenGL Using GLEW " ) ) +
205  FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
206  }
207 
209 
210  return true;
211 }
212 
213 
214 void EDA_3D_CANVAS::GetScreenshot( wxImage &aDstImage )
215 {
216  OGL_GetScreenshot( aDstImage );
217 }
218 
219 
220 void EDA_3D_CANVAS::ReloadRequest( BOARD *aBoard , S3D_CACHE *aCachePointer )
221 {
222  if( aCachePointer != NULL )
223  m_settings.Set3DCacheManager( aCachePointer );
224 
225  if( aBoard != NULL )
226  m_settings.SetBoard( aBoard );
227 
228  if( m_3d_render )
230 }
231 
232 
234 {
236 
237  if( m_3d_render )
239 
241  //m_mouse_was_moved = true;
242 
243  Request_refresh();
244 }
245 
246 
248 {
249  if( m_parentStatusBar )
250  {
251  wxString msg;
252 
253  msg.Printf( wxT( "dx %3.2f" ), m_settings.CameraGet().GetCameraPos().x );
254  m_parentStatusBar->SetStatusText( msg, 1 );
255 
256  msg.Printf( wxT( "dy %3.2f" ), m_settings.CameraGet().GetCameraPos().y );
257  m_parentStatusBar->SetStatusText( msg, 2 );
258 
259  //msg.Printf( _( "Zoom: %3.1f" ), 50 * m_settings.CameraGet().ZoomGet() );
260  //m_parentStatusBar->SetStatusText( msg, 3 );
261  }
262 }
263 
264 
265 void EDA_3D_CANVAS::OnPaint( wxPaintEvent &event )
266 {
267  // Please have a look at:
268  // https://lists.launchpad.net/kicad-developers/msg25149.html
269  // wxPaintDC( this );
270  // event.Skip( false );
271 
272  // SwapBuffer requires the window to be shown before calling
273  if( !IsShownOnScreen() )
274  {
275  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnPaint !IsShown" ) );
276  return;
277  }
278 
279  // Because the board to draw is handled by the parent viewer frame,
280  // ensure this parent is still alive. When it is closed before the viewer
281  // frame, a paint event can be generated after the parent is closed,
282  // therefore with invalid board.
283  // This is dependant of the platform.
284  // Especially on OSX, but also on Windows, it frequently happens
285  if( !GetParent()->GetParent()->IsShown() )
286  return; // The parent board editor frame is no more alive
287 
288  wxString err_messages;
289 
290  // !TODO: implement error reporter
291  //WX_STRING_REPORTER errorReporter( &err_messages );
292  STATUS_TEXT_REPORTER activityReporter( m_parentStatusBar, 0 );
293 
294 
295  unsigned strtime = GetRunningMicroSecs();
296 
297  // "Makes the OpenGL state that is represented by the OpenGL rendering
298  // context context current, i.e. it will be used by all subsequent OpenGL calls.
299  // This function may only be called when the window is shown on screen"
300 
301  // Explicitly create a new rendering context instance for this canvas.
302  if( m_glRC == NULL )
304 
306 
307  // Set the OpenGL viewport according to the client size of this canvas.
308  // This is done here rather than in a wxSizeEvent handler because our
309  // OpenGL rendering context (and thus viewport setting) is used with
310  // multiple canvases: If we updated the viewport in the wxSizeEvent
311  // handler, changing the size of one canvas causes a viewport setting that
312  // is wrong when next another canvas is repainted.
313  wxSize clientSize = GetClientSize();
314 
315  const bool windows_size_changed = m_settings.CameraGet().SetCurWindowSize( clientSize );
316 
317 
318  // Initialize openGL if need
319  // /////////////////////////////////////////////////////////////////////////
321  {
322  if( !initializeOpenGL() )
323  {
325 
326  return;
327  }
328  }
329 
330 
331  // Check if a raytacing was requented and need to switch to raytracing mode
333  {
334  const bool was_camera_changed = m_settings.CameraGet().ParametersChanged();
335 
336  // It reverts back to OpenGL mode if it was requested a raytracing
337  // render of the current scene. AND the mouse / camera is moving
338  if( ( m_mouse_is_moving ||
340  was_camera_changed ||
341  windows_size_changed ) &&
343  {
346  }
347  }
348 
349 
350  float curtime_delta_s = 0.0f;
351 
352  if( m_camera_is_moving )
353  {
354  const unsigned curtime_delta = GetRunningMicroSecs() - m_strtime_camera_movement;
355  curtime_delta_s = (curtime_delta / 1e6) * m_camera_moving_speed;
356  m_settings.CameraGet().Interpolate( curtime_delta_s );
357 
358  if( curtime_delta_s > 1.0f )
359  {
360  m_render_pivot = false;
361  m_camera_is_moving = false;
362  m_mouse_was_moved = true;
363 
365  DisplayStatus();
366  }
367  else
368  {
369  Request_refresh();
370  }
371  }
372 
373 
374  // It will return true if the render request a new redraw
375  bool requested_redraw = false;
376 
377  if( m_3d_render )
378  {
379  m_3d_render->SetCurWindowSize( clientSize );
380 
381  requested_redraw = m_3d_render->Redraw( m_mouse_was_moved || m_camera_is_moving,
382  &activityReporter );
383  }
384 
385  if( m_render_pivot )
386  {
387  const float scale = glm::min( m_settings.CameraGet().ZoomGet(), 1.0f );
388  render_pivot( curtime_delta_s, scale * scale );
389  }
390 
391  // "Swaps the double-buffer of this window, making the back-buffer the
392  // front-buffer and vice versa, so that the output of the previous OpenGL
393  // commands is displayed on the window."
394  SwapBuffers();
395 
397 
398  if( !activityReporter.HasMessage() )
399  {
401  {
402  // Calculation time in miliseconds
403  const double calculation_time = (double)( GetRunningMicroSecs() - strtime) / 1e3;
404 
405  activityReporter.Report( wxString::Format( _( "Render time %.0f ms ( %.1f fps)" ),
406  calculation_time, 1000.0 / calculation_time ) );
407  }
408  }
409 
410  // This will reset the flag of camera parameters changed
412 
413  if( !err_messages.IsEmpty() )
414  wxLogMessage( err_messages );
415 
416  if( (!m_camera_is_moving) && requested_redraw )
417  {
418  m_mouse_was_moved = false;
419  Request_refresh( false );
420  }
421 }
422 
423 
424 void EDA_3D_CANVAS::OnEraseBackground( wxEraseEvent &event )
425 {
426  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnEraseBackground" ) );
427  // Do nothing, to avoid flashing.
428 }
429 
430 
431 void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent &event )
432 {
433  bool mouseActivity = false;
434 
435  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnMouseWheel" ) );
436 
437  if( m_camera_is_moving )
438  return;
439 
440  float delta_move = m_delta_move_step_factor * m_settings.CameraGet().ZoomGet();
441 
443  delta_move *= (0.01f * event.GetWheelRotation());
444  else
445  if( event.GetWheelRotation() < 0 )
446  delta_move = -delta_move;
447 
448  // mousewheel_panning enabled:
449  // wheel -> pan;
450  // wheel + shift -> horizontal scrolling;
451  // wheel + ctrl -> zooming;
452  // mousewheel_panning disabled:
453  // wheel + shift -> vertical scrolling;
454  // wheel + ctrl -> horizontal scrolling;
455  // wheel -> zooming.
456 
457  if( m_settings.GetFlag( FL_MOUSEWHEEL_PANNING ) && !event.ControlDown() )
458  {
459  if( event.GetWheelAxis() == wxMOUSE_WHEEL_HORIZONTAL || event.ShiftDown() )
460  m_settings.CameraGet().Pan( SFVEC3F( -delta_move, 0.0f, 0.0f ) );
461  else
462  m_settings.CameraGet().Pan( SFVEC3F( 0.0f, -delta_move, 0.0f ) );
463 
464  mouseActivity = true;
465  }
466  else if( event.ShiftDown() && !m_settings.GetFlag( FL_MOUSEWHEEL_PANNING ) )
467  {
468  m_settings.CameraGet().Pan( SFVEC3F( 0.0f, -delta_move, 0.0f ) );
469  mouseActivity = true;
470  }
471  else if( event.ControlDown() && !m_settings.GetFlag( FL_MOUSEWHEEL_PANNING ) )
472  {
473  m_settings.CameraGet().Pan( SFVEC3F( delta_move, 0.0f, 0.0f ) );
474  mouseActivity = true;
475  }
476  else
477  {
478  mouseActivity = m_settings.CameraGet().Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
479  }
480 
481  // If it results on a camera movement
482  if( mouseActivity )
483  {
484  DisplayStatus();
485  Request_refresh();
486 
487  m_mouse_is_moving = true;
488  m_mouse_was_moved = true;
489 
491  }
492 
493  // Update the cursor current mouse position on the camera
494  m_settings.CameraGet().SetCurMousePosition( event.GetPosition() );
495 }
496 
497 
498 #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
499 void EDA_3D_CANVAS::OnMagnify( wxMouseEvent& event )
500 {
501  if( m_camera_is_moving )
502  return;
503 
504  //m_is_moving_mouse = true;
506 
507  float magnification = ( event.GetMagnification() + 1.0f );
508 
509  m_settings.CameraGet().Zoom( magnification );
510 
511  DisplayStatus();
512  Request_refresh();
513 
514  // Please someone test if this is need
515  //m_settings.CameraGet().SetCurMousePosition( event.GetPosition() );
516 }
517 #endif
518 
519 
520 void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent &event )
521 {
522  //wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnMouseMove" ) );
523 
524  if( m_camera_is_moving )
525  return;
526 
527  m_settings.CameraGet().SetCurWindowSize( GetClientSize() );
528 
529  if( event.Dragging() )
530  {
531  if( event.LeftIsDown() ) // Drag
532  m_settings.CameraGet().Drag( event.GetPosition() );
533  else if( event.MiddleIsDown() ) // Pan
534  m_settings.CameraGet().Pan( event.GetPosition() );
535 
536  m_mouse_is_moving = true;
537  m_mouse_was_moved = true;
538 
539  // orientation has changed, redraw mesh
540  DisplayStatus();
541  Request_refresh();
542  }
543 
544  const wxPoint eventPosition = event.GetPosition();
545  m_settings.CameraGet().SetCurMousePosition( eventPosition );
546 }
547 
548 
549 void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent &event )
550 {
552 }
553 
554 
555 void EDA_3D_CANVAS::OnLeftUp( wxMouseEvent &event )
556 {
557  if( m_camera_is_moving )
558  return;
559 
560  if( m_mouse_is_moving )
561  {
562  m_mouse_is_moving = false;
564  }
565 }
566 
567 
568 void EDA_3D_CANVAS::OnMiddleDown( wxMouseEvent &event )
569 {
571 }
572 
573 
574 void EDA_3D_CANVAS::OnMiddleUp( wxMouseEvent &event )
575 {
576  if( m_camera_is_moving )
577  return;
578 
579  if( m_mouse_is_moving )
580  {
581  m_mouse_is_moving = false;
583  }
584  else
585  {
587  }
588 }
589 
590 
591 void EDA_3D_CANVAS::OnRightClick( wxMouseEvent &event )
592 {
593  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnRightClick" ) );
594 
595  if( m_camera_is_moving )
596  return;
597 
598  wxPoint pos;
599  wxMenu PopUpMenu;
600 
601  pos.x = event.GetX();
602  pos.y = event.GetY();
603 
604  wxMenuItem* item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMIN, _( "Zoom +" ) );
605  item->SetBitmap( KiBitmap( zoom_in_xpm ));
606  PopUpMenu.Append( item );
607 
608  item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMOUT, _( "Zoom -" ) );
609  item->SetBitmap( KiBitmap( zoom_out_xpm ));
610  PopUpMenu.Append( item );
611 
612  PopUpMenu.AppendSeparator();
613  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZPOS, _( "Top View" ) );
614  item->SetBitmap( KiBitmap( axis3d_top_xpm ));
615  PopUpMenu.Append( item );
616 
617  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZNEG, _( "Bottom View" ) );
618  item->SetBitmap( KiBitmap( axis3d_bottom_xpm ));
619  PopUpMenu.Append( item );
620 
621  PopUpMenu.AppendSeparator();
622  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XPOS, _( "Right View" ) );
623  item->SetBitmap( KiBitmap( axis3d_right_xpm ));
624  PopUpMenu.Append( item );
625 
626  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XNEG, _( "Left View" ) );
627  item->SetBitmap( KiBitmap( axis3d_left_xpm ));
628  PopUpMenu.Append( item );
629 
630  PopUpMenu.AppendSeparator();
631  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YPOS, _( "Front View" ) );
632  item->SetBitmap( KiBitmap( axis3d_front_xpm ));
633  PopUpMenu.Append( item );
634 
635  item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YNEG, _( "Back View" ) );
636  item->SetBitmap( KiBitmap( axis3d_back_xpm ));
637  PopUpMenu.Append( item );
638 
639  PopUpMenu.AppendSeparator();
640  item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_LEFT, _( "Move left <-" ) );
641  item->SetBitmap( KiBitmap( left_xpm ));
642  PopUpMenu.Append( item );
643 
644  item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_RIGHT, _( "Move right ->" ) );
645  item->SetBitmap( KiBitmap( right_xpm ));
646  PopUpMenu.Append( item );
647 
648  item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_UP, _( "Move Up ^" ) );
649  item->SetBitmap( KiBitmap( up_xpm ));
650  PopUpMenu.Append( item );
651 
652  item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_DOWN, _( "Move Down" ) );
653  item->SetBitmap( KiBitmap( down_xpm ));
654  PopUpMenu.Append( item );
655 
656  PopupMenu( &PopUpMenu, pos );
657 }
658 
659 
660 void EDA_3D_CANVAS::OnPopUpMenu( wxCommandEvent &event )
661 {
662  int id = event.GetId();
663 
664  wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnPopUpMenu id:%d" ), id );
665 
666  int key = 0;
667 
668  switch( id )
669  {
670  case ID_POPUP_ZOOMIN:
671  key = WXK_F1;
672  break;
673 
674  case ID_POPUP_ZOOMOUT:
675  key = WXK_F2;
676  break;
677 
678  case ID_POPUP_VIEW_XPOS:
679  key = 'x';
680  break;
681 
682  case ID_POPUP_VIEW_XNEG:
683  key = 'X';
684  break;
685 
686  case ID_POPUP_VIEW_YPOS:
687  key = 'y';
688  break;
689 
690  case ID_POPUP_VIEW_YNEG:
691  key = 'Y';
692  break;
693 
694  case ID_POPUP_VIEW_ZPOS:
695  key = 'z';
696  break;
697 
698  case ID_POPUP_VIEW_ZNEG:
699  key = 'Z';
700  break;
701 
703  key = WXK_LEFT;
704  break;
705 
707  key = WXK_RIGHT;
708  break;
709 
710  case ID_POPUP_MOVE3D_UP:
711  key = WXK_UP;
712  break;
713 
715  key = WXK_DOWN;
716  break;
717 
718  default:
719  return;
720  }
721 
722  SetView3D( key );
723 }
724 
725 
726 void EDA_3D_CANVAS::OnCharHook( wxKeyEvent &event )
727 {
728  //wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnCharHook" ) );
729  event.Skip();
730 }
731 
732 
733 void EDA_3D_CANVAS::OnKeyEvent( wxKeyEvent& event )
734 {
735  //wxLogTrace( m_logTrace, wxT( "EDA_3D_CANVAS::OnKeyEvent" ) );
736 
737  if( m_camera_is_moving )
738  return;
739 
740  SetView3D( event.GetKeyCode() );
741  event.Skip();
742 }
743 
744 
745 void EDA_3D_CANVAS::OnTimerTimeout_Editing( wxTimerEvent &event )
746 {
747  (void)event;
748 
749  m_mouse_is_moving = false;
750  m_mouse_was_moved = false;
751 
752  Request_refresh();
753 }
754 
755 
757 {
759 }
760 
761 
763 {
764  m_editing_timeout_timer.Start( m_3d_render->GetWaitForEditingTimeOut() , wxTIMER_ONE_SHOT );
765 }
766 
767 
768 void EDA_3D_CANVAS::OnTimerTimeout_Redraw( wxTimerEvent &event )
769 {
770  (void)event;
771 
772  //Refresh();
773  //Update();
774 
775  wxPaintEvent redrawEvent;
776  wxPostEvent( this, redrawEvent );
777 }
778 
779 
780 void EDA_3D_CANVAS::Request_refresh( bool aRedrawImmediately )
781 {
782  if( aRedrawImmediately )
783  {
784  // On some systems, just calling Refresh does not work always
785  // (Issue experienced on Win7 MSYS2)
786  //Refresh();
787  //Update();
788 
789  // Using PostEvent will take priority to other events, like
790  // mouse movements, keys, etc.
791  wxPaintEvent redrawEvent;
792  wxPostEvent( this, redrawEvent );
793 
794  // This behaves the same
795  // wxQueueEvent( this,
796  // From wxWidget documentation: "The heap-allocated and
797  // non-NULL event to queue, the function takes ownership of it."
798  // new wxPaintEvent()
799  // );
800  }
801  else
802  {
803  // Schedule a timed redraw
804  m_redraw_trigger_timer.Start( 10 , wxTIMER_ONE_SHOT );
805  }
806 }
807 
808 
809 void EDA_3D_CANVAS::request_start_moving_camera( float aMovingSpeed, bool aRenderPivot )
810 {
811  wxASSERT( aMovingSpeed > FLT_EPSILON );
812 
813  m_render_pivot = aRenderPivot;
814  m_camera_moving_speed = aMovingSpeed;
815 
817 
818  DisplayStatus();
819  Request_refresh();
820 
821  m_camera_is_moving = true;
822 
824 }
825 
826 
828 {
829  SFVEC3F rayOrigin;
830  SFVEC3F rayDir;
831 
832  // Generate a ray origin and direction based on current mouser position and camera
833  m_settings.CameraGet().MakeRayAtCurrrentMousePosition( rayOrigin, rayDir );
834 
835  RAY mouseRay;
836  mouseRay.Init( rayOrigin, rayDir );
837 
838  float hit_t;
839 
840  // Test it with the board bounding box
841  if( m_settings.GetBBox3DU().Intersect( mouseRay, &hit_t ) )
842  {
845  m_settings.CameraGet().SetLookAtPos_T1( mouseRay.at( hit_t ) );
847 
849  }
850 }
851 
852 
853 void EDA_3D_CANVAS::SetView3D( int keycode )
854 {
855  if( m_camera_is_moving )
856  return;
857 
858  const float delta_move = m_delta_move_step_factor * m_settings.CameraGet().ZoomGet();
859  const float arrow_moving_time_speed = 8.0f;
860 
861  switch( keycode )
862  {
863  case WXK_SPACE:
865  return;
866 
867  case WXK_LEFT:
870  m_settings.CameraGet().Pan_T1( SFVEC3F( -delta_move, 0.0f, 0.0f ) );
871  request_start_moving_camera( arrow_moving_time_speed, false );
872  return;
873 
874  case WXK_RIGHT:
877  m_settings.CameraGet().Pan_T1( SFVEC3F( +delta_move, 0.0f, 0.0f ) );
878  request_start_moving_camera( arrow_moving_time_speed, false );
879  return;
880 
881  case WXK_UP:
884  m_settings.CameraGet().Pan_T1( SFVEC3F( 0.0f, +delta_move, 0.0f ) );
885  request_start_moving_camera( arrow_moving_time_speed, false );
886  return;
887 
888  case WXK_DOWN:
891  m_settings.CameraGet().Pan_T1( SFVEC3F( 0.0f, -delta_move, 0.0f ) );
892  request_start_moving_camera( arrow_moving_time_speed, false );
893  return;
894 
895  case WXK_HOME:
900  return;
901 
902  case WXK_END:
903  break;
904 
905  case WXK_TAB:
908  m_settings.CameraGet().RotateZ_T1( glm::radians( 45.0f ) );
910  break;
911 
912  case WXK_F1:
915  if( m_settings.CameraGet().Zoom_T1( 1.4f ) )
917  return;
918 
919  case WXK_F2:
922  if( m_settings.CameraGet().Zoom_T1( 1/1.4f ) )
924  return;
925 
926  case '+':
927  break;
928 
929  case '-':
930  break;
931 
932  case 't':
933  case 'T':
936  ReloadRequest();
937  break;
938 
939  case 's':
940  case 'S':
943  ReloadRequest();
944  break;
945 
946  case 'v':
947  case 'V':
950  ReloadRequest();
951  break;
952 
953  case 'r':
954  case 'R':
959  return;
960 
961  case 'x':
965  m_settings.CameraGet().RotateZ_T1( glm::radians( -90.0f ) );
966  m_settings.CameraGet().RotateX_T1( glm::radians( -90.0f ) );
968  return;
969 
970  case 'X':
974  m_settings.CameraGet().RotateZ_T1( glm::radians( 90.0f ) );
975  m_settings.CameraGet().RotateX_T1( glm::radians( -90.0f ) );
977  return;
978 
979  case 'y':
983  m_settings.CameraGet().RotateX_T1( glm::radians( -90.0f ) );
985  return;
986 
987  case 'Y':
991  m_settings.CameraGet().RotateX_T1( glm::radians( -90.0f ) );
992  m_settings.CameraGet().RotateZ_T1( glm::radians( -180.0f ) );
994  return;
995 
996  case 'z':
1001  glm::min( glm::max( m_settings.CameraGet().ZoomGet(), 0.5f ), 1.125f ) );
1002  return;
1003 
1004  case 'Z':
1008  m_settings.CameraGet().RotateX_T1( glm::radians( -180.0f ) );
1010  glm::min( glm::max( m_settings.CameraGet().ZoomGet(), 0.5f ), 1.125f ) );
1011  return;
1012 
1013  default:
1014  return;
1015  }
1016 
1017  m_mouse_was_moved = true;
1018 
1020 
1021  DisplayStatus();
1022  Request_refresh();
1023 }
1024 
1025 
1027 {
1028 
1029  switch( m_settings.RenderEngineGet() )
1030  {
1033  break;
1034 
1037  break;
1038 
1039  default:
1040  m_3d_render = NULL;
1041  break;
1042  }
1043 
1044  if( m_3d_render )
1046 
1047  m_mouse_was_moved = false;
1048 
1049  Request_refresh();
1050 }
C3D_RENDER_RAYTRACING * m_3d_render_raytracing
Raytracing render class.
void SetLookAtPos_T1(const SFVEC3F &aLookAtPos)
Definition: ccamera.h:125
void OGL_GetScreenshot(wxImage &aDstImage)
OGL_GetScreenshot - got the pixel data of current OpenGL image.
Definition: ogl_utils.cpp:35
float ZoomGet() const
Definition: ccamera.cpp:490
void OnMouseMove(wxMouseEvent &event)
void request_start_moving_camera(float aMovingSpeed=2.0f, bool aRenderPivot=true)
request_start_moving_camera - start a camera movement
void releaseOpenGL()
releaseOpenGL - free created targets and openGL context
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
virtual void SetT0_and_T1_current_T()
SetT0_and_T1_current_T - This will set T0 and T1 with the current values.
Definition: ccamera.cpp:535
bool m_mouse_is_moving
true if mouse activity is on progress
CINFO3D_VISU & m_settings
Stores all pre-computed 3D information and visualization settings to render the board.
void ResetXYpos_T1()
Definition: ccamera.cpp:382
unsigned m_strtime_camera_movement
Stores the ticktime when the camera star its movement.
void stop_editingTimeOut_Timer()
stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition: ray.cpp:38
wxStatusBar * m_parentStatusBar
Parent statusbar to report progress.
Class BOARD to handle a board.
wxGLContext * m_glRC
current OpenGL context
SFVEC3F at(float t) const
Definition: ray.h:65
void OnCloseWindow(wxCloseEvent &event)
OnCloseWindow - called when the frame is closed.
Class EDA_3D_CANVAS Implement a canvas based on a wxGLCanvas.
Definition: eda_3d_canvas.h:53
wxTimer m_editing_timeout_timer
Time timeout will expires after some time sinalizing that the mouse / keyboard movements are over...
Definition: ray.h:43
void DisplayStatus()
DisplayStatus - Update the status bar with the position information.
C3D_RENDER_OGL_LEGACY * m_3d_render_ogl_legacy
OpenGL legacy render class.
void Request_refresh(bool aRedrawImmediately=true)
Request_refresh - Schedule a refresh update of the canvas.
void ReloadRequest(BOARD *aBoard=NULL, S3D_CACHE *aCachePointer=NULL)
virtual int GetWaitForEditingTimeOut()=0
GetWaitForEditingTimeOut - Give the interface the time (in ms) that it should wait for editing or mov...
void UnlockCtx(wxGLContext *aContext)
Function UnlockCtx allows other canvases to bind an OpenGL context.
void SetCurMousePosition(const wxPoint &aPosition)
It updates the current mouse position without make any new recalculations on camera.
Definition: ccamera.cpp:401
bool Zoom(float aFactor)
Definition: ccamera.cpp:454
void OnLeftDown(wxMouseEvent &event)
float m_camera_moving_speed
1.0f will be 1:1
static GL_CONTEXT_MANAGER & Get()
Function Get returns the GL_CONTEXT_MANAGER instance (singleton).
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:36
void OnLeftUp(wxMouseEvent &event)
void restart_editingTimeOut_Timer()
restart_editingTimeOut_Timer - reset the editing timer
void RenderRaytracingRequest()
RenderRaytracingRequest - Request to render the current view in Raytracing mode.
void OnKeyEvent(wxKeyEvent &event)
void OnMiddleDown(wxMouseEvent &event)
bool m_mouse_was_moved
true if there was some type of activity, it will be used to render in preview mode ...
void OnEraseBackground(wxEraseEvent &event)
void OnMouseWheel(wxMouseEvent &event)
void RenderEngineChanged()
RenderEngineChanged - Notify that the render engine was changed.
Class STATUS_TEXT_REPORTER is a wrapper for reporting to a wxString in a wxFrame status text...
Class CINFO3D_VISU Helper class to handle information needed to display 3D board. ...
Definition: cinfo3d_visu.h:70
bool m_camera_is_moving
true if camera animation is ongoing
virtual void Interpolate(float t)
Interpolate - It will update the matrix to interpolate between T0 and T1 values.
Definition: ccamera.cpp:549
virtual void Drag(const wxPoint &aNewMousePosition)=0
Calculate a new mouse drag position.
EVT_MIDDLE_DOWN(mpWindow::OnMouseMiddleDown) EVT_MOUSEWHEEL(mpWindow
Definition: mathplot.cpp:1724
const SFVEC3F & GetCameraPos() const
Definition: ccamera.h:131
bool SetCurWindowSize(const wxSize &aSize)
SetCurWindowSize - update the windows size of the camera.
Definition: ccamera.cpp:428
void OnPopUpMenu(wxCommandEvent &event)
bool Intersect(const RAY &aRay, float *t) const
Function Intersect.
Definition: cbbox_ray.cpp:46
void OnTimerTimeout_Redraw(wxTimerEvent &event)
bool Zoom_T1(float aFactor)
Definition: ccamera.cpp:473
virtual void Pan_T1(const SFVEC3F &aDeltaOffsetInc)=0
void RotateX_T1(float aAngleInRadians)
Definition: ccamera.cpp:517
RENDER_ENGINE RenderEngineGet() const
RenderEngineGet.
Definition: cinfo3d_visu.h:234
virtual void Reset_T1()
Definition: ccamera.cpp:92
void LockCtx(wxGLContext *aContext, wxGLCanvas *aCanvas)
Function LockCtx sets a context as current and prevents other canvases from switching it...
bool m_render_pivot
activated the render of pivot while camera moving
bool m_is_opengl_initialized
Flag to store if opengl was initialized already.
C3D_RENDER_BASE * m_3d_render
The current render in used for this canvas.
void OnMiddleUp(wxMouseEvent &event)
The C3D_RENDER_OGL_LEGACY class render the board using openGL legacy mode.
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
void GetScreenshot(wxImage &aDstImage)
Request a screenshot and output it to the aDstImage.
virtual bool Redraw(bool aIsMoving, REPORTER *aStatusTextReporter=NULL)=0
Redraw - Ask to redraw the view.
void OnCharHook(wxKeyEvent &event)
const int scale
void SetView3D(int keycode)
SetView3D - Helper function to call view commands.
bool initializeOpenGL()
initializeOpenGL
void MakeRayAtCurrrentMousePosition(SFVEC3F &aOutOrigin, SFVEC3F &aOutDirection) const
MakeRayAtCurrrentMousePosition - Make a ray based on the latest mouse position.
Definition: ccamera.cpp:350
void move_pivot_based_on_cur_mouse_position()
move_pivot_based_on_cur_mouse_position - This function hits a ray to the board and start a moviment ...
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
CCAMERA & CameraGet() const
CameraGet - get current camera in use.
Definition: cinfo3d_visu.h:210
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
virtual void Pan(const wxPoint &aNewMousePosition)=0
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
void OnPaint(wxPaintEvent &event)
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
void OnRightClick(wxMouseEvent &event)
void OnTimerTimeout_Editing(wxTimerEvent &event)
void DestroyCtx(wxGLContext *aContext)
Function DestroyCtx destroys a managed OpenGL context.
wxGLContext * CreateCtx(wxGLCanvas *aCanvas, const wxGLContext *aOther=NULL)
Function CreateCtx creates a managed OpenGL context.
void SetFlag(DISPLAY3D_FLG aFlag, bool aState)
SetFlag - set the status of a flag.
virtual void SetCurWindowSize(const wxSize &aSize)=0
SetCurWindowSize - Before each render, the canvas will tell the render what is the size of its window...
EVT_MENU_RANGE(ID_POPUP_3D_VIEW_START, ID_POPUP_3D_VIEW_END, EDA_3D_CANVAS::OnPopUpMenu) EDA_3D_CANVAS
void ReloadRequest()
ReloadRequest - !TODO: this must be reviewed to add flags to improve specific render.
void RotateZ_T1(float aAngleInRadians)
Definition: ccamera.cpp:529
void SetBoard(BOARD *aBoard)
SetBoard - Set current board to be rendered.
Definition: cinfo3d_visu.h:122
wxTimer m_redraw_trigger_timer
This timer will be used to schedule a redraw event.
static const float m_delta_move_step_factor
Step factor to used with cursor on relation to the current zoom.
void render_pivot(float t, float aScale)
render_pivot - render the pivot cursor
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED) override
Function Report is a pure virtual function to override in the derived object.
void SetInterpolateMode(CAMERA_INTERPOLATION aInterpolateMode)
Definition: ccamera.h:198
#define min(a, b)
Definition: auxiliary.h:85
bool ParametersChanged()
Function ParametersChanged.
Definition: ccamera.cpp:567
void Set3DCacheManager(S3D_CACHE *aCachePointer)
Set3DCacheManager - Update the Cache manager pointer.
Definition: cinfo3d_visu.h:82
const CBBOX & GetBBox3DU() const
GetBBox3DU - Get the bbox of the pcb board.
Definition: cinfo3d_visu.h:147
bool m_render_raytracing_was_requested
Flags that the user requested the current view to be render with raytracing.