2014-08-20 17:53:09 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1992-2014 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
|
|
|
|
*/
|
|
|
|
|
2011-05-22 19:08:34 +00:00
|
|
|
/**
|
|
|
|
* @file 3d_canvas.cpp
|
|
|
|
*/
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <trigo.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <wx/image.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
#if !wxUSE_GLCANVAS
|
|
|
|
#error Please set wxUSE_GLCANVAS to 1 in setup.h.
|
|
|
|
#endif
|
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <wx/dataobj.h>
|
|
|
|
#include <wx/clipbrd.h>
|
2010-01-19 20:43:44 +00:00
|
|
|
#include <wx/wupdlock.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <gestfich.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-07-30 09:34:48 +00:00
|
|
|
#ifdef __WINDOWS__
|
|
|
|
#include <GL/glew.h> // must be included before gl.h
|
|
|
|
#endif
|
2014-07-30 09:01:25 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <3d_viewer.h>
|
2012-12-15 08:52:02 +00:00
|
|
|
#include <3d_canvas.h>
|
2012-08-11 12:52:13 +00:00
|
|
|
#include <info3d_visu.h>
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <trackball.h>
|
2012-08-11 12:52:13 +00:00
|
|
|
#include <3d_viewer_id.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-08-20 17:53:09 +00:00
|
|
|
#include <textures/text_silk.h>
|
|
|
|
#include <textures/text_pcb.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2007-05-06 16:03:28 +00:00
|
|
|
/*
|
2011-09-17 15:31:21 +00:00
|
|
|
* EDA_3D_CANVAS implementation
|
2007-05-06 16:03:28 +00:00
|
|
|
*/
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
BEGIN_EVENT_TABLE( EDA_3D_CANVAS, wxGLCanvas )
|
|
|
|
EVT_PAINT( EDA_3D_CANVAS::OnPaint )
|
2010-01-19 20:43:44 +00:00
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
// key event:
|
2011-09-17 15:31:21 +00:00
|
|
|
EVT_CHAR( EDA_3D_CANVAS::OnChar )
|
2010-01-19 20:43:44 +00:00
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
// mouse events
|
2011-09-17 15:31:21 +00:00
|
|
|
EVT_RIGHT_DOWN( EDA_3D_CANVAS::OnRightClick )
|
|
|
|
EVT_MOUSEWHEEL( EDA_3D_CANVAS::OnMouseWheel )
|
|
|
|
EVT_MOTION( EDA_3D_CANVAS::OnMouseMove )
|
2010-01-19 20:43:44 +00:00
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
// other events
|
2011-09-17 15:31:21 +00:00
|
|
|
EVT_ERASE_BACKGROUND( EDA_3D_CANVAS::OnEraseBackground )
|
|
|
|
EVT_MENU_RANGE( ID_POPUP_3D_VIEW_START, ID_POPUP_3D_VIEW_END, EDA_3D_CANVAS::OnPopUpMenu )
|
2007-05-06 16:03:28 +00:00
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
|
2012-12-15 08:52:02 +00:00
|
|
|
wxGLCanvas( parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize,
|
2009-11-04 20:46:53 +00:00
|
|
|
wxFULL_REPAINT_ON_RESIZE )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2011-08-03 15:09:39 +00:00
|
|
|
m_init = false;
|
2014-07-30 09:01:25 +00:00
|
|
|
m_shadow_init = false;
|
2014-03-08 19:04:23 +00:00
|
|
|
|
|
|
|
// Clear all gl list identifiers:
|
|
|
|
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
|
|
|
m_glLists[ii] = 0;
|
|
|
|
|
2009-07-13 15:25:41 +00:00
|
|
|
// Explicitly create a new rendering context instance for this canvas.
|
2009-11-04 20:46:53 +00:00
|
|
|
m_glRC = new wxGLContext( this );
|
2009-08-20 11:44:06 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
DisplayStatus();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
EDA_3D_CANVAS::~EDA_3D_CANVAS()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
ClearLists();
|
2011-08-03 15:09:39 +00:00
|
|
|
m_init = false;
|
2009-07-13 15:25:41 +00:00
|
|
|
delete m_glRC;
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-07-30 15:39:55 +00:00
|
|
|
void EDA_3D_CANVAS::ClearLists( int aGlList )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2014-03-08 19:04:23 +00:00
|
|
|
if( aGlList )
|
|
|
|
{
|
|
|
|
if( m_glLists[aGlList] > 0 )
|
|
|
|
glDeleteLists( m_glLists[aGlList], 1 );
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
m_glLists[aGlList] = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
|
|
|
|
{
|
|
|
|
if( m_glLists[ii] > 0 )
|
|
|
|
glDeleteLists( m_glLists[ii], 1 );
|
|
|
|
|
|
|
|
m_glLists[ii] = 0;
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnChar( wxKeyEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
SetView3D( event.GetKeyCode() );
|
|
|
|
event.Skip();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::SetView3D( int keycode )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
int ii;
|
2014-08-21 11:59:57 +00:00
|
|
|
double delta_move = 0.7 * GetPrm3DVisu().m_Zoom;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
|
|
switch( keycode )
|
|
|
|
{
|
|
|
|
case WXK_LEFT:
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.x -= delta_move;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_RIGHT:
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.x += delta_move;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_UP:
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.y += delta_move;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_DOWN:
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.y -= delta_move;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_HOME:
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom = 1.0;
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_END:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_F1:
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom /= 1.4;
|
|
|
|
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
|
|
|
GetPrm3DVisu().m_Zoom = 0.01;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WXK_F2:
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom *= 1.4;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
case 'R':
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.x = m_draw3dOffset.y = 0;
|
2007-08-20 01:20:48 +00:00
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'x':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
|
|
|
GetPrm3DVisu().m_ROTZ = -90;
|
|
|
|
GetPrm3DVisu().m_ROTX = -90;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'X':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
|
|
|
GetPrm3DVisu().m_ROTZ = 90;
|
|
|
|
GetPrm3DVisu().m_ROTX = -90;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'y':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
|
|
|
GetPrm3DVisu().m_ROTX = -90;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Y':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
|
|
|
GetPrm3DVisu().m_ROTX = -90;
|
|
|
|
GetPrm3DVisu().m_ROTZ = -180;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'z':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Z':
|
|
|
|
for( ii = 0; ii < 4; ii++ )
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Rot[ii] = 0.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
trackball( GetPrm3DVisu().m_Quat, 0.0, 0.0, 0.0, 0.0 );
|
|
|
|
GetPrm3DVisu().m_ROTX = -180;
|
2007-08-20 01:20:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DisplayStatus();
|
2011-08-03 15:09:39 +00:00
|
|
|
Refresh( false );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2010-01-19 20:43:44 +00:00
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnMouseWheel( wxMouseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2010-01-11 14:44:49 +00:00
|
|
|
if( event.ShiftDown() )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-01-11 14:44:49 +00:00
|
|
|
if( event.GetWheelRotation() < 0 )
|
2014-08-21 11:59:57 +00:00
|
|
|
SetView3D( WXK_UP ); // move up
|
2010-01-11 14:44:49 +00:00
|
|
|
else
|
2014-08-21 11:59:57 +00:00
|
|
|
SetView3D( WXK_DOWN ); // move down
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2010-01-11 14:44:49 +00:00
|
|
|
else if( event.ControlDown() )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2010-01-11 14:44:49 +00:00
|
|
|
if( event.GetWheelRotation() > 0 )
|
2014-08-21 11:59:57 +00:00
|
|
|
SetView3D( WXK_RIGHT ); // move right
|
2010-01-11 14:44:49 +00:00
|
|
|
else
|
2014-08-21 11:59:57 +00:00
|
|
|
SetView3D( WXK_LEFT ); // move left
|
2010-01-11 14:44:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( event.GetWheelRotation() > 0 )
|
2007-08-20 01:20:48 +00:00
|
|
|
{
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom /= 1.4;
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
|
|
|
GetPrm3DVisu().m_Zoom = 0.01;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
2010-01-11 14:44:49 +00:00
|
|
|
else
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom *= 1.4;
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2010-01-11 14:44:49 +00:00
|
|
|
DisplayStatus();
|
2011-08-03 15:09:39 +00:00
|
|
|
Refresh( false );
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Beginx = event.GetX();
|
|
|
|
GetPrm3DVisu().m_Beginy = event.GetY();
|
2010-01-11 14:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnMouseMove( wxMouseEvent& event )
|
2010-01-11 14:44:49 +00:00
|
|
|
{
|
|
|
|
wxSize size( GetClientSize() );
|
|
|
|
double spin_quat[4];
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( event.Dragging() )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2008-03-03 08:00:26 +00:00
|
|
|
if( event.LeftIsDown() )
|
|
|
|
{
|
|
|
|
/* drag in progress, simulate trackball */
|
|
|
|
trackball( spin_quat,
|
2014-08-21 11:59:57 +00:00
|
|
|
(2.0 * GetPrm3DVisu().m_Beginx - size.x) / size.x,
|
|
|
|
(size.y - 2.0 * GetPrm3DVisu().m_Beginy) / size.y,
|
2008-03-03 08:00:26 +00:00
|
|
|
( 2.0 * event.GetX() - size.x) / size.x,
|
|
|
|
( size.y - 2.0 * event.GetY() ) / size.y );
|
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
add_quats( spin_quat, GetPrm3DVisu().m_Quat, GetPrm3DVisu().m_Quat );
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
|
|
|
else if( event.MiddleIsDown() )
|
|
|
|
{
|
|
|
|
/* middle button drag -> pan */
|
2009-11-04 20:46:53 +00:00
|
|
|
|
|
|
|
/* Current zoom and an additional factor are taken into account
|
|
|
|
* for the amount of panning. */
|
2014-08-21 11:59:57 +00:00
|
|
|
const double PAN_FACTOR = 8.0 * GetPrm3DVisu().m_Zoom;
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.x -= PAN_FACTOR *
|
2014-08-21 11:59:57 +00:00
|
|
|
( GetPrm3DVisu().m_Beginx - event.GetX() ) / size.x;
|
2012-02-25 19:55:40 +00:00
|
|
|
m_draw3dOffset.y -= PAN_FACTOR *
|
2014-08-21 11:59:57 +00:00
|
|
|
(event.GetY() - GetPrm3DVisu().m_Beginy) / size.y;
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
|
|
|
/* orientation has changed, redraw mesh */
|
2007-08-20 01:20:48 +00:00
|
|
|
DisplayStatus();
|
2011-08-03 15:09:39 +00:00
|
|
|
Refresh( false );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Beginx = event.GetX();
|
|
|
|
GetPrm3DVisu().m_Beginy = event.GetY();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
/* Construct and display a popup menu when the right button is clicked.
|
2007-08-20 01:20:48 +00:00
|
|
|
*/
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnRightClick( wxMouseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
wxPoint pos;
|
|
|
|
wxMenu PopUpMenu;
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
pos.x = event.GetX();
|
|
|
|
pos.y = event.GetY();
|
|
|
|
|
|
|
|
wxMenuItem* item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMIN, _( "Zoom +" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( zoom_in_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_ZOOMOUT, _( "Zoom -" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( zoom_out_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
|
|
|
PopUpMenu.AppendSeparator();
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZPOS, _( "Top View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_top_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_ZNEG, _( "Bottom View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_bottom_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
|
|
|
PopUpMenu.AppendSeparator();
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XPOS, _( "Right View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_right_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_XNEG, _( "Left View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_left_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
|
|
|
PopUpMenu.AppendSeparator();
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YPOS, _( "Front View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_front_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_VIEW_YNEG, _( "Back View" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( axis3d_back_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
|
|
|
PopUpMenu.AppendSeparator();
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_LEFT, _( "Move left <-" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( left_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_RIGHT, _( "Move right ->" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( right_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_UP, _( "Move Up ^" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( up_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
2011-11-01 08:06:33 +00:00
|
|
|
item = new wxMenuItem( &PopUpMenu, ID_POPUP_MOVE3D_DOWN, _( "Move Down" ) );
|
2011-08-28 20:02:27 +00:00
|
|
|
item->SetBitmap( KiBitmap( down_xpm ));
|
2007-08-20 01:20:48 +00:00
|
|
|
PopUpMenu.Append( item );
|
|
|
|
|
|
|
|
PopupMenu( &PopUpMenu, pos );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnPopUpMenu( wxCommandEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
int key = 0;
|
|
|
|
|
|
|
|
switch( event.GetId() )
|
|
|
|
{
|
|
|
|
case ID_POPUP_ZOOMIN:
|
|
|
|
key = WXK_F1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_ZOOMOUT:
|
|
|
|
key = WXK_F2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_XPOS:
|
|
|
|
key = 'x';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_XNEG:
|
|
|
|
key = 'X';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_YPOS:
|
|
|
|
key = 'y';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_YNEG:
|
|
|
|
key = 'Y';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_ZPOS:
|
|
|
|
key = 'z';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_VIEW_ZNEG:
|
|
|
|
key = 'Z';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_MOVE3D_LEFT:
|
|
|
|
key = WXK_LEFT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_MOVE3D_RIGHT:
|
|
|
|
key = WXK_RIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_MOVE3D_UP:
|
|
|
|
key = WXK_UP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_POPUP_MOVE3D_DOWN:
|
|
|
|
key = WXK_DOWN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetView3D( key );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::DisplayStatus()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
wxString msg;
|
|
|
|
|
2012-02-25 19:55:40 +00:00
|
|
|
msg.Printf( wxT( "dx %3.2f" ), m_draw3dOffset.x );
|
|
|
|
Parent()->SetStatusText( msg, 1 );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-02-25 19:55:40 +00:00
|
|
|
msg.Printf( wxT( "dy %3.2f" ), m_draw3dOffset.y );
|
|
|
|
Parent()->SetStatusText( msg, 2 );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
msg.Printf( wxT( "View: %3.1f" ), 45 * GetPrm3DVisu().m_Zoom );
|
2012-02-25 19:55:40 +00:00
|
|
|
Parent()->SetStatusText( msg, 3 );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnPaint( wxPaintEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
wxPaintDC dc( this );
|
2009-11-04 20:46:53 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
Redraw();
|
|
|
|
event.Skip();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::OnEraseBackground( wxEraseEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
// Do nothing, to avoid flashing.
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2014-07-30 09:01:25 +00:00
|
|
|
typedef struct s_sImage
|
|
|
|
{
|
|
|
|
unsigned int width;
|
|
|
|
unsigned int height;
|
|
|
|
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
|
|
|
|
unsigned char pixel_data[64 * 64 * 4 + 1];
|
|
|
|
}tsImage;
|
|
|
|
|
|
|
|
|
|
|
|
GLuint load_and_generate_texture( tsImage *image )
|
|
|
|
{
|
|
|
|
|
|
|
|
GLuint texture;
|
|
|
|
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
|
|
|
glPixelStorei (GL_PACK_ALIGNMENT, 1);
|
|
|
|
|
|
|
|
glGenTextures( 1, &texture );
|
|
|
|
glBindTexture( GL_TEXTURE_2D, texture );
|
2014-08-21 11:59:57 +00:00
|
|
|
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, image->width, image->height,
|
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, image->pixel_data );
|
2014-07-30 09:01:25 +00:00
|
|
|
|
|
|
|
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
|
|
|
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
2014-08-19 14:51:15 +00:00
|
|
|
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2014-07-30 09:01:25 +00:00
|
|
|
|
|
|
|
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
|
|
|
return texture;
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
/* Initialize broad parameters for OpenGL */
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::InitGL()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
if( !m_init )
|
|
|
|
{
|
2011-08-03 15:09:39 +00:00
|
|
|
m_init = true;
|
2014-07-30 09:01:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
m_text_pcb = load_and_generate_texture( (tsImage *)&text_pcb );
|
|
|
|
m_text_silk = load_and_generate_texture( (tsImage *)&text_silk );
|
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
GetPrm3DVisu().m_Zoom = 1.0;
|
2012-02-25 19:55:40 +00:00
|
|
|
m_ZBottom = 1.0;
|
|
|
|
m_ZTop = 10.0;
|
2009-08-04 18:21:32 +00:00
|
|
|
|
|
|
|
glDisable( GL_CULL_FACE ); // show back faces
|
|
|
|
glEnable( GL_DEPTH_TEST ); // Enable z-buferring
|
2013-10-13 16:47:11 +00:00
|
|
|
glEnable( GL_ALPHA_TEST );
|
2009-08-04 18:21:32 +00:00
|
|
|
glEnable( GL_LINE_SMOOTH );
|
2013-10-18 10:33:50 +00:00
|
|
|
// glEnable(GL_POLYGON_SMOOTH); // creates issues with some graphic cards
|
2014-08-19 14:51:15 +00:00
|
|
|
glEnable( GL_NORMALIZE );
|
2009-08-04 18:21:32 +00:00
|
|
|
glEnable( GL_COLOR_MATERIAL );
|
|
|
|
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
|
|
|
|
2013-10-13 16:47:11 +00:00
|
|
|
// speedups
|
2014-07-30 09:01:25 +00:00
|
|
|
//glEnable( GL_DITHER );
|
2012-08-28 06:51:18 +00:00
|
|
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE );
|
|
|
|
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
2013-10-13 16:47:11 +00:00
|
|
|
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
2009-08-04 18:21:32 +00:00
|
|
|
|
2013-10-13 16:47:11 +00:00
|
|
|
// Initialize alpha blending function.
|
2009-08-04 18:21:32 +00:00
|
|
|
glEnable( GL_BLEND );
|
|
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2014-07-30 09:01:25 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
/* Initialize OpenGL light sources. */
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::SetLights()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2014-08-21 11:59:57 +00:00
|
|
|
// activate light. the source is above the xy plane, at source_pos
|
|
|
|
GLfloat source_pos[4] = { 0.0, 0.0, 30.0, 0.0 };
|
2014-08-12 16:03:50 +00:00
|
|
|
GLfloat light_color[4]; // color of lights (RGBA values)
|
|
|
|
light_color[3] = 1.0;
|
|
|
|
|
|
|
|
// Light above the xy plane
|
2014-08-19 14:51:15 +00:00
|
|
|
light_color[0] = light_color[1] = light_color[2] = 0.1;
|
|
|
|
glLightfv( GL_LIGHT0, GL_AMBIENT, light_color );
|
|
|
|
|
2014-08-12 16:03:50 +00:00
|
|
|
light_color[0] = light_color[1] = light_color[2] = 1.0;
|
2007-08-20 01:20:48 +00:00
|
|
|
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_color );
|
2014-07-30 09:01:25 +00:00
|
|
|
|
2014-08-19 14:51:15 +00:00
|
|
|
light_color[0] = light_color[1] = light_color[2] = 1.0;
|
2014-08-12 16:03:50 +00:00
|
|
|
glLightfv( GL_LIGHT0, GL_SPECULAR, light_color );
|
2014-07-30 09:01:25 +00:00
|
|
|
|
2014-08-21 11:59:57 +00:00
|
|
|
glLightfv( GL_LIGHT0, GL_POSITION, source_pos );
|
2014-08-19 14:51:15 +00:00
|
|
|
|
|
|
|
light_color[0] = light_color[1] = light_color[2] = 0.1;
|
|
|
|
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color );
|
|
|
|
|
2014-08-12 16:03:50 +00:00
|
|
|
glEnable( GL_LIGHT0 ); // White spot on Z axis ( top )
|
2007-08-20 01:20:48 +00:00
|
|
|
glEnable( GL_LIGHTING );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Create a Screenshot of the current 3D view.
|
2010-01-25 14:01:46 +00:00
|
|
|
* Output file format is png or jpeg, or image is copied to the clipboard
|
2007-08-20 01:20:48 +00:00
|
|
|
*/
|
2011-09-17 15:31:21 +00:00
|
|
|
void EDA_3D_CANVAS::TakeScreenshot( wxCommandEvent& event )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-08-29 16:59:50 +00:00
|
|
|
wxFileName fn( Parent()->GetDefaultFileName() );
|
2009-05-28 08:42:24 +00:00
|
|
|
wxString FullFileName;
|
|
|
|
wxString file_ext, mask;
|
2011-08-03 15:09:39 +00:00
|
|
|
bool fmt_is_jpeg = false;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
|
|
if( event.GetId() == ID_MENU_SCREENCOPY_JPEG )
|
2011-08-03 15:09:39 +00:00
|
|
|
fmt_is_jpeg = true;
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( event.GetId() != ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
|
|
|
{
|
2010-10-04 11:50:43 +00:00
|
|
|
file_ext = fmt_is_jpeg ? wxT( "jpg" ) : wxT( "png" );
|
|
|
|
mask = wxT( "*." ) + file_ext;
|
2012-08-29 16:59:50 +00:00
|
|
|
FullFileName = Parent()->GetDefaultFileName();
|
2009-04-05 20:49:15 +00:00
|
|
|
fn.SetExt( file_ext );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
2011-08-03 15:09:39 +00:00
|
|
|
FullFileName = EDA_FileSelector( _( "3D Image filename:" ), wxEmptyString,
|
|
|
|
fn.GetFullName(), file_ext, mask, this,
|
|
|
|
wxFD_SAVE, true );
|
2009-11-04 20:46:53 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( FullFileName.IsEmpty() )
|
|
|
|
return;
|
2010-12-03 18:58:50 +00:00
|
|
|
|
|
|
|
// Be sure the screen area destroyed by the file dialog is redrawn before making
|
|
|
|
// a screen copy.
|
|
|
|
// Without this call, under Linux the screen refresh is made to late.
|
|
|
|
wxYield();
|
2007-08-20 01:20:48 +00:00
|
|
|
}
|
|
|
|
|
2014-08-04 11:28:29 +00:00
|
|
|
struct viewport_params
|
2010-01-19 20:43:44 +00:00
|
|
|
{
|
|
|
|
GLint originx;
|
|
|
|
GLint originy;
|
|
|
|
GLint x;
|
|
|
|
GLint y;
|
|
|
|
} viewport;
|
2010-10-29 07:40:02 +00:00
|
|
|
|
2014-08-04 11:28:29 +00:00
|
|
|
// Be sure we have the latest 3D view (remember 3D view is buffered)
|
|
|
|
Refresh();
|
|
|
|
wxYield();
|
|
|
|
|
2010-10-04 11:50:43 +00:00
|
|
|
// Build image from the 3D buffer
|
2010-01-19 20:43:44 +00:00
|
|
|
wxWindowUpdateLocker noUpdates( this );
|
|
|
|
glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport );
|
|
|
|
|
|
|
|
unsigned char* pixelbuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 );
|
|
|
|
unsigned char* alphabuffer = (unsigned char*) malloc( viewport.x * viewport.y );
|
|
|
|
wxImage image( viewport.x, viewport.y );
|
|
|
|
|
2010-01-24 16:27:36 +00:00
|
|
|
glPixelStorei( GL_PACK_ALIGNMENT, 1 );
|
2010-01-19 20:43:44 +00:00
|
|
|
glReadBuffer( GL_BACK_LEFT );
|
2010-10-04 11:50:43 +00:00
|
|
|
glReadPixels( viewport.originx, viewport.originy,
|
|
|
|
viewport.x, viewport.y,
|
|
|
|
GL_RGB, GL_UNSIGNED_BYTE, pixelbuffer );
|
|
|
|
glReadPixels( viewport.originx, viewport.originy,
|
|
|
|
viewport.x, viewport.y,
|
|
|
|
GL_ALPHA, GL_UNSIGNED_BYTE, alphabuffer );
|
2010-01-19 20:43:44 +00:00
|
|
|
|
|
|
|
image.SetData( pixelbuffer );
|
|
|
|
image.SetAlpha( alphabuffer );
|
|
|
|
image = image.Mirror( false );
|
|
|
|
wxBitmap bitmap( image );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( event.GetId() == ID_TOOL_SCREENCOPY_TOCLIBBOARD )
|
|
|
|
{
|
|
|
|
wxBitmapDataObject* dobjBmp = new wxBitmapDataObject;
|
|
|
|
dobjBmp->SetBitmap( bitmap );
|
2011-08-03 15:09:39 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( wxTheClipboard->Open() )
|
|
|
|
{
|
|
|
|
if( !wxTheClipboard->SetData( dobjBmp ) )
|
2010-07-20 10:30:40 +00:00
|
|
|
wxMessageBox( _( "Failed to copy image to clipboard" ) );
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
wxTheClipboard->Flush(); /* the data in clipboard will stay
|
|
|
|
* available after the
|
|
|
|
* application exits */
|
2007-08-20 01:20:48 +00:00
|
|
|
wxTheClipboard->Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-08-20 11:44:06 +00:00
|
|
|
wxImage image = bitmap.ConvertToImage();
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
if( !image.SaveFile( FullFileName,
|
2011-08-03 15:09:39 +00:00
|
|
|
fmt_is_jpeg ? wxBITMAP_TYPE_JPEG : wxBITMAP_TYPE_PNG ) )
|
2010-07-20 10:30:40 +00:00
|
|
|
wxMessageBox( _( "Can't save file" ) );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
image.Destroy();
|
|
|
|
}
|
|
|
|
}
|