2011-11-10 15:55:05 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2012-08-11 12:52:13 +00:00
|
|
|
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
2011-11-10 15:55:05 +00:00
|
|
|
*
|
|
|
|
* 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_draw.cpp
|
2013-05-03 17:51:10 +00:00
|
|
|
*/
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <common.h>
|
|
|
|
#include <trigo.h>
|
|
|
|
#include <pcbstruct.h>
|
|
|
|
#include <drawtxt.h>
|
|
|
|
#include <layers_id_colors_and_visibility.h>
|
2011-09-23 13:57:12 +00:00
|
|
|
|
2014-01-30 08:18:47 +00:00
|
|
|
#include <wxBasePcbFrame.h>
|
2012-01-23 04:33:36 +00:00
|
|
|
#include <class_board.h>
|
|
|
|
#include <class_module.h>
|
|
|
|
#include <class_track.h>
|
|
|
|
#include <class_edge_mod.h>
|
|
|
|
#include <class_zone.h>
|
|
|
|
#include <class_drawsegment.h>
|
|
|
|
#include <class_pcb_text.h>
|
|
|
|
#include <colors_selection.h>
|
2012-08-23 19:15:58 +00:00
|
|
|
#include <convert_basic_shapes_to_polygon.h>
|
2007-05-06 16:03:28 +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-26 13:59:55 +00:00
|
|
|
#include <3d_draw_basic_functions.h>
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-08-26 13:59:55 +00:00
|
|
|
// Imported function:
|
2013-05-03 17:51:10 +00:00
|
|
|
extern void CheckGLError();
|
|
|
|
|
2014-03-18 10:31:13 +00:00
|
|
|
/* Helper function
|
|
|
|
* returns true if aLayer should be displayed, false otherwise
|
2013-05-03 17:51:10 +00:00
|
|
|
*/
|
2014-06-24 16:17:18 +00:00
|
|
|
static bool Is3DLayerEnabled( LAYER_ID aLayer );
|
2013-05-03 17:51:10 +00:00
|
|
|
|
|
|
|
/* returns the Z orientation parameter 1.0 or -1.0 for aLayer
|
|
|
|
* Z orientation is 1.0 for all layers but "back" layers:
|
2014-06-24 16:17:18 +00:00
|
|
|
* B_Cu , B_Adhes, B_Paste ), B_SilkS
|
2013-05-03 17:51:10 +00:00
|
|
|
* used to calculate the Z orientation parameter for glNormal3f
|
|
|
|
*/
|
2013-03-31 13:27:46 +00:00
|
|
|
static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
/* Helper function BuildPadShapeThickOutlineAsPolygon:
|
|
|
|
* Build a pad shape outline as polygon, to draw pads on silkscreen layer
|
|
|
|
* with a line thickness = aWidth
|
|
|
|
* Used only to draw pads outlines on silkscreen layers.
|
|
|
|
*/
|
2013-05-03 17:51:10 +00:00
|
|
|
static void BuildPadShapeThickOutlineAsPolygon( D_PAD* aPad,
|
|
|
|
CPOLYGONS_LIST& aCornerBuffer,
|
|
|
|
int aWidth,
|
|
|
|
int aCircleToSegmentsCount,
|
|
|
|
double aCorrectionFactor )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
|
|
|
if( aPad->GetShape() == PAD_CIRCLE ) // Draw a ring
|
|
|
|
{
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
2013-05-03 17:51:10 +00:00
|
|
|
aPad->GetSize().x / 2, aCircleToSegmentsCount, aWidth );
|
2013-05-01 19:01:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For other shapes, draw polygon outlines
|
2013-05-03 17:51:10 +00:00
|
|
|
CPOLYGONS_LIST corners;
|
2013-05-01 19:01:14 +00:00
|
|
|
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
|
2013-05-03 17:51:10 +00:00
|
|
|
aCircleToSegmentsCount, aCorrectionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
|
|
|
|
// Add outlines as thick segments in polygon buffer
|
2013-05-09 19:08:12 +00:00
|
|
|
for( unsigned ii = 0, jj = corners.GetCornersCount() - 1;
|
|
|
|
ii < corners.GetCornersCount(); jj = ii, ii++ )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
|
|
|
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
2013-05-08 18:20:58 +00:00
|
|
|
corners.GetPos( jj ),
|
|
|
|
corners.GetPos( ii ),
|
2013-05-03 17:51:10 +00:00
|
|
|
aCircleToSegmentsCount, aWidth );
|
2013-05-01 19:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
void EDA_3D_CANVAS::Redraw()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2012-02-02 17:45:37 +00:00
|
|
|
// SwapBuffer requires the window to be shown before calling
|
2011-01-29 10:19:54 +00:00
|
|
|
if( !IsShown() )
|
|
|
|
return;
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
SetCurrent( *m_glRC );
|
2009-08-04 18:21:32 +00:00
|
|
|
|
|
|
|
// Set the OpenGL viewport according to the client size of this canvas.
|
|
|
|
// This is done here rather than in a wxSizeEvent handler because our
|
|
|
|
// OpenGL rendering context (and thus viewport setting) is used with
|
|
|
|
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
|
|
|
// handler, changing the size of one canvas causes a viewport setting that
|
|
|
|
// is wrong when next another canvas is repainted.
|
|
|
|
const wxSize ClientSize = GetClientSize();
|
2009-08-20 11:44:06 +00:00
|
|
|
|
|
|
|
// *MUST* be called *after* SetCurrent( ):
|
2009-08-04 18:21:32 +00:00
|
|
|
glViewport( 0, 0, ClientSize.x, ClientSize.y );
|
|
|
|
|
2008-03-03 08:00:26 +00:00
|
|
|
InitGL();
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2012-02-02 17:45:37 +00:00
|
|
|
glMatrixMode( GL_MODELVIEW ); // position viewer
|
|
|
|
// transformations
|
2007-05-06 16:03:28 +00:00
|
|
|
GLfloat mat[4][4];
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
// Translate motion first, so rotations don't mess up the orientation...
|
2012-02-25 19:55:40 +00:00
|
|
|
glTranslatef( m_draw3dOffset.x, m_draw3dOffset.y, 0.0F );
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2007-05-06 16:03:28 +00:00
|
|
|
build_rotmatrix( mat, g_Parm_3D_Visu.m_Quat );
|
|
|
|
glMultMatrixf( &mat[0][0] );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2008-03-03 08:00:26 +00:00
|
|
|
glRotatef( g_Parm_3D_Visu.m_Rot[0], 1.0, 0.0, 0.0 );
|
|
|
|
glRotatef( g_Parm_3D_Visu.m_Rot[1], 0.0, 1.0, 0.0 );
|
|
|
|
glRotatef( g_Parm_3D_Visu.m_Rot[2], 0.0, 0.0, 1.0 );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
if( ! m_glLists[GL_ID_BOARD] || ! m_glLists[GL_ID_TECH_LAYERS] )
|
2008-07-21 13:44:01 +00:00
|
|
|
CreateDrawGL_List();
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_AXIS ) && m_glLists[GL_ID_AXIS] )
|
|
|
|
glCallList( m_glLists[GL_ID_AXIS] );
|
|
|
|
|
|
|
|
// move the board in order to draw it with its center at 0,0 3D coordinates
|
|
|
|
glTranslatef( -g_Parm_3D_Visu.m_BoardPos.x * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
|
|
|
-g_Parm_3D_Visu.m_BoardPos.y * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
|
|
|
0.0F );
|
|
|
|
|
2014-03-18 10:31:13 +00:00
|
|
|
// draw all objects in lists
|
|
|
|
// transparent objects should be drawn after opaque objects
|
2014-03-08 19:04:23 +00:00
|
|
|
glCallList( m_glLists[GL_ID_BOARD] );
|
|
|
|
glCallList( m_glLists[GL_ID_TECH_LAYERS] );
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_COMMENTS ) || g_Parm_3D_Visu.GetFlag( FL_COMMENTS ) )
|
|
|
|
{
|
|
|
|
if( ! m_glLists[GL_ID_AUX_LAYERS] )
|
|
|
|
CreateDrawGL_List();
|
|
|
|
|
|
|
|
glCallList( m_glLists[GL_ID_AUX_LAYERS] );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_MODULE ) )
|
|
|
|
{
|
|
|
|
if( ! m_glLists[GL_ID_3DSHAPES_SOLID] )
|
|
|
|
CreateDrawGL_List();
|
|
|
|
|
|
|
|
glCallList( m_glLists[GL_ID_3DSHAPES_SOLID] );
|
2014-03-18 10:31:13 +00:00
|
|
|
}
|
2014-03-08 19:04:23 +00:00
|
|
|
|
2014-03-18 10:31:13 +00:00
|
|
|
// Grid uses transparency: draw it after all objects
|
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_GRID ) && m_glLists[GL_ID_GRID] )
|
|
|
|
glCallList( m_glLists[GL_ID_GRID] );
|
|
|
|
|
|
|
|
// This list must be drawn last, because it contains the
|
|
|
|
// transparent gl objects, which should be drawn after all
|
|
|
|
// non transparent objects
|
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP] )
|
2014-03-08 19:04:23 +00:00
|
|
|
glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP] );
|
2011-01-29 10:19:54 +00:00
|
|
|
|
2008-03-03 08:00:26 +00:00
|
|
|
SwapBuffers();
|
2007-11-01 05:27:31 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
// Helper function: initialize the copper color to draw the board
|
|
|
|
// in realistic mode.
|
|
|
|
static inline void SetGLCopperColor()
|
|
|
|
{
|
|
|
|
// Generates a golden yellow color, near board "copper" color
|
|
|
|
const double lum = 0.7/255.0;
|
|
|
|
glColor4f( 255.0*lum, 223.0*lum, 0.0*lum, 1.0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function: initialize the color to draw the epoxy layers
|
|
|
|
// ( body board and solder mask layers) in realistic mode.
|
|
|
|
static inline void SetGLEpoxyColor( double aTransparency = 1.0 )
|
|
|
|
{
|
|
|
|
// Generates an epoxy color, near board color
|
|
|
|
const double lum = 0.2/255.0;
|
|
|
|
glColor4f( 100.0*lum, 255.0*lum, 180.0*lum, aTransparency );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function: initialize the color to draw the non copper layers
|
|
|
|
// in realistic mode and normal mode.
|
|
|
|
static inline void SetGLTechLayersColor( LAYER_NUM aLayer )
|
|
|
|
{
|
|
|
|
if( g_Parm_3D_Visu.IsRealisticMode() )
|
|
|
|
{
|
|
|
|
switch( aLayer )
|
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Paste:
|
|
|
|
case F_Paste:
|
2013-10-07 11:51:08 +00:00
|
|
|
SetGLColor( DARKGRAY, 0.7 );
|
|
|
|
break;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_SilkS:
|
|
|
|
case F_SilkS:
|
2013-10-07 11:51:08 +00:00
|
|
|
SetGLColor( LIGHTGRAY, 0.9 );
|
|
|
|
break;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Mask:
|
|
|
|
case F_Mask:
|
2013-10-07 11:51:08 +00:00
|
|
|
SetGLEpoxyColor( 0.7 );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( aLayer );
|
|
|
|
SetGLColor( color, 0.7 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( aLayer );
|
|
|
|
SetGLColor( color, 0.7 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
void EDA_3D_CANVAS::BuildBoard3DView()
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2014-03-08 19:04:23 +00:00
|
|
|
BOARD* pcb = GetBoard();
|
2013-10-07 11:51:08 +00:00
|
|
|
bool realistic_mode = g_Parm_3D_Visu.IsRealisticMode();
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2014-05-17 19:29:15 +00:00
|
|
|
// Number of segments to convert a circle to polygon
|
2014-05-26 06:54:04 +00:00
|
|
|
// Boost polygon (at least v 1.54, v1.55 and previous) in very rare cases crashes
|
|
|
|
// when using 16 segments to approximate a circle.
|
|
|
|
// So using 18 segments is a workaround to try to avoid these crashes
|
|
|
|
// ( We already used this trick in plot_board_layers.cpp,
|
|
|
|
// see PlotSolderMaskLayer() )
|
|
|
|
const int segcountforcircle = 18;
|
2013-05-03 17:51:10 +00:00
|
|
|
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
|
|
|
|
const int segcountLowQuality = 12; // segments to draw a circle with low quality
|
|
|
|
// to reduce time calculations
|
|
|
|
// for holes and items which do not need
|
|
|
|
// a fine representation
|
|
|
|
double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) );
|
2013-10-04 08:42:09 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
CPOLYGONS_LIST bufferPolys;
|
2013-10-04 08:42:09 +00:00
|
|
|
bufferPolys.reserve( 200000 ); // Reserve for large board (tracks mainly)
|
|
|
|
|
|
|
|
CPOLYGONS_LIST bufferPcbOutlines; // stores the board main outlines
|
|
|
|
CPOLYGONS_LIST allLayerHoles; // Contains through holes, calculated only once
|
|
|
|
allLayerHoles.reserve( 20000 );
|
|
|
|
|
|
|
|
// Build a polygon from edge cut items
|
|
|
|
wxString msg;
|
2014-04-27 11:30:45 +00:00
|
|
|
|
|
|
|
if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) )
|
2013-10-04 08:42:09 +00:00
|
|
|
{
|
2013-10-07 14:50:23 +00:00
|
|
|
msg << wxT("\n\n") <<
|
2013-10-13 16:47:11 +00:00
|
|
|
_("Unable to calculate the board outlines.\n"
|
|
|
|
"Therefore use the board boundary box.");
|
2013-10-07 14:50:23 +00:00
|
|
|
wxMessageBox( msg );
|
2013-10-04 08:42:09 +00:00
|
|
|
}
|
2013-05-03 17:51:10 +00:00
|
|
|
|
|
|
|
CPOLYGONS_LIST bufferZonesPolys;
|
2013-10-04 08:42:09 +00:00
|
|
|
bufferZonesPolys.reserve( 500000 ); // Reserve for large board ( copper zones mainly )
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
CPOLYGONS_LIST currLayerHoles; // Contains holes for the current layer
|
|
|
|
bool throughHolesListBuilt = false; // flag to build the through hole polygon list only once
|
|
|
|
bool hightQualityMode = false;
|
2013-05-01 19:01:14 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
LSET cu_set = LSET::AllCuMask( g_Parm_3D_Visu.m_CopperLayersCount );
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
LAYER_ID cu_seq[MAX_CU_LAYERS]; // preferred sequence, could have called CuStack()
|
|
|
|
// but I assume that's backwards
|
|
|
|
|
|
|
|
for( unsigned i=0; i<DIM(cu_seq); ++i )
|
2014-06-29 13:05:51 +00:00
|
|
|
cu_seq[i] = ToLAYER_ID( B_Cu - i );
|
2014-06-24 16:17:18 +00:00
|
|
|
|
|
|
|
for( LSEQ cu = cu_set.Seq( cu_seq, DIM(cu_seq) ); cu; ++cu )
|
|
|
|
#else
|
|
|
|
for( LSEQ cu = cu_set.CuStack(); cu; ++cu )
|
|
|
|
#endif
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
LAYER_ID layer = *cu;
|
2008-07-21 13:44:01 +00:00
|
|
|
|
2014-01-30 08:18:47 +00:00
|
|
|
// Skip non enabled layers in normal mode,
|
|
|
|
// and internal layers in realistic mode
|
2013-10-07 11:51:08 +00:00
|
|
|
if( !Is3DLayerEnabled( layer ) )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-14 18:47:01 +00:00
|
|
|
bufferPolys.RemoveAllContours();
|
|
|
|
bufferZonesPolys.RemoveAllContours();
|
|
|
|
currLayerHoles.RemoveAllContours();
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Draw tracks:
|
2014-06-24 16:17:18 +00:00
|
|
|
for( TRACK* track = pcb->m_Track; track; track = track->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !track->IsOnLayer( layer ) )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
track->TransformShapeWithClearanceToPolygon( bufferPolys,
|
2013-05-03 17:51:10 +00:00
|
|
|
0, segcountforcircle,
|
|
|
|
correctionFactor );
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Add via hole
|
|
|
|
if( track->Type() == PCB_VIA_T )
|
|
|
|
{
|
2014-04-25 06:00:04 +00:00
|
|
|
VIA *via = static_cast<VIA*>( track );
|
|
|
|
VIATYPE_T viatype = via->GetViaType();
|
|
|
|
int holediameter = via->GetDrillValue();
|
|
|
|
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
|
2013-05-01 19:01:14 +00:00
|
|
|
int hole_outer_radius = (holediameter + thickness) / 2;
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-04-25 06:00:04 +00:00
|
|
|
if( viatype != VIA_THROUGH )
|
2013-05-01 19:01:14 +00:00
|
|
|
TransformCircleToPolygon( currLayerHoles,
|
2014-04-25 06:00:04 +00:00
|
|
|
via->GetStart(), hole_outer_radius,
|
2013-05-01 19:01:14 +00:00
|
|
|
segcountLowQuality );
|
2013-05-03 17:51:10 +00:00
|
|
|
else if( !throughHolesListBuilt )
|
2013-05-01 19:01:14 +00:00
|
|
|
TransformCircleToPolygon( allLayerHoles,
|
2014-04-25 06:00:04 +00:00
|
|
|
via->GetStart(), hole_outer_radius,
|
2013-05-01 19:01:14 +00:00
|
|
|
segcountLowQuality );
|
|
|
|
}
|
|
|
|
}
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// draw pads
|
2014-06-24 16:17:18 +00:00
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
|
|
|
module->TransformPadsShapesWithClearanceToPolygon( layer,
|
2013-05-03 17:51:10 +00:00
|
|
|
bufferPolys,
|
|
|
|
0,
|
|
|
|
segcountforcircle,
|
|
|
|
correctionFactor );
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2014-01-30 08:18:47 +00:00
|
|
|
// Micro-wave modules may have items on copper layers
|
2013-05-01 19:01:14 +00:00
|
|
|
module->TransformGraphicShapesWithClearanceToPolygonSet( layer,
|
2013-05-03 17:51:10 +00:00
|
|
|
bufferPolys,
|
|
|
|
0,
|
|
|
|
segcountforcircle,
|
|
|
|
correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
|
|
|
|
// Add pad hole, if any
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !throughHolesListBuilt )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
|
|
|
D_PAD* pad = module->Pads();
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( ; pad; pad = pad->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
pad->BuildPadDrillShapePolygon( allLayerHoles, 0,
|
|
|
|
segcountLowQuality );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw copper zones
|
2013-10-07 14:50:23 +00:00
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_ZONE ) )
|
2008-08-17 18:37:03 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
for( int ii = 0; ii < pcb->GetAreaCount(); ii++ )
|
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
ZONE_CONTAINER* zone = pcb->GetArea( ii );
|
|
|
|
LAYER_NUM zonelayer = zone->GetLayer();
|
2011-09-17 15:31:21 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
if( zonelayer == layer )
|
2014-05-26 06:54:04 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
zone->TransformSolidAreasShapesToPolygonSet(
|
2013-05-03 17:51:10 +00:00
|
|
|
hightQualityMode ? bufferPolys : bufferZonesPolys,
|
|
|
|
segcountLowQuality, correctionFactorLQ );
|
2014-05-26 06:54:04 +00:00
|
|
|
}
|
2013-05-01 19:01:14 +00:00
|
|
|
}
|
2009-11-16 13:18:20 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 18:43:53 +00:00
|
|
|
// draw graphic items on copper layers (texts)
|
2013-05-01 19:01:14 +00:00
|
|
|
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
|
2009-02-02 12:12:18 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !item->IsOnLayer( layer ) )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
2014-03-09 18:43:53 +00:00
|
|
|
case PCB_LINE_T: // should not exist on copper layers
|
2013-05-03 17:51:10 +00:00
|
|
|
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
|
2014-03-09 18:43:53 +00:00
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
break;
|
2011-09-17 15:31:21 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
case PCB_TEXT_T:
|
2013-05-03 17:51:10 +00:00
|
|
|
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
|
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-02-02 12:12:18 +00:00
|
|
|
}
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2013-10-04 08:42:09 +00:00
|
|
|
// bufferPolys contains polygons to merge. Many overlaps .
|
|
|
|
// Calculate merged polygons
|
2013-05-09 19:08:12 +00:00
|
|
|
if( bufferPolys.GetCornersCount() == 0 )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
KI_POLYGON_SET currLayerPolyset;
|
|
|
|
KI_POLYGON_SET polysetHoles;
|
2012-08-26 13:59:55 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Add polygons, without holes
|
2013-05-08 18:20:58 +00:00
|
|
|
bufferPolys.ExportTo( currLayerPolyset );
|
2012-08-26 13:59:55 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Add holes in polygon list
|
2013-05-08 18:20:58 +00:00
|
|
|
currLayerHoles.Append( allLayerHoles );
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-09 19:08:12 +00:00
|
|
|
if( currLayerHoles.GetCornersCount() > 0 )
|
2013-05-08 18:20:58 +00:00
|
|
|
currLayerHoles.ExportTo( polysetHoles );
|
2013-05-01 19:01:14 +00:00
|
|
|
|
|
|
|
// Merge polygons, remove holes
|
|
|
|
currLayerPolyset -= polysetHoles;
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
int thickness = g_Parm_3D_Visu.GetLayerObjectThicknessBIU( layer );
|
|
|
|
int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer );
|
2013-05-01 19:01:14 +00:00
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
if( realistic_mode )
|
|
|
|
SetGLCopperColor();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( layer );
|
|
|
|
SetGLColor( color );
|
|
|
|
}
|
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
|
2010-12-08 20:12:46 +00:00
|
|
|
|
2013-05-14 18:47:01 +00:00
|
|
|
bufferPolys.RemoveAllContours();
|
2013-05-08 18:20:58 +00:00
|
|
|
bufferPolys.ImportFrom( currLayerPolyset );
|
2013-05-01 19:01:14 +00:00
|
|
|
Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
|
|
|
|
thickness,
|
|
|
|
g_Parm_3D_Visu.m_BiuTo3Dunits );
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-09 19:08:12 +00:00
|
|
|
if( bufferZonesPolys.GetCornersCount() )
|
2013-05-01 19:01:14 +00:00
|
|
|
Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos,
|
|
|
|
thickness,
|
|
|
|
g_Parm_3D_Visu.m_BiuTo3Dunits );
|
|
|
|
|
|
|
|
throughHolesListBuilt = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw vias holes (vertical cylinders)
|
2014-06-24 16:17:18 +00:00
|
|
|
for( const TRACK* track = pcb->m_Track; track; track = track->Next() )
|
2008-03-03 08:00:26 +00:00
|
|
|
{
|
2014-04-25 06:00:04 +00:00
|
|
|
const VIA *via = dynamic_cast<const VIA*>(track);
|
|
|
|
|
|
|
|
if( via )
|
|
|
|
Draw3DViaHole( via );
|
2013-05-01 19:01:14 +00:00
|
|
|
}
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Draw pads holes (vertical cylinders)
|
2014-06-24 16:17:18 +00:00
|
|
|
for( const MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
Draw3DPadHole( pad );
|
|
|
|
}
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
// Draw board substrate:
|
2013-10-07 14:50:23 +00:00
|
|
|
if( bufferPcbOutlines.GetCornersCount() &&
|
|
|
|
( realistic_mode || g_Parm_3D_Visu.GetFlag( FL_SHOW_BOARD_BODY ) ) )
|
2013-10-07 11:51:08 +00:00
|
|
|
{
|
|
|
|
int copper_thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
|
2014-06-24 16:17:18 +00:00
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
// a small offset between substrate and external copper layer to avoid artifacts
|
|
|
|
// when drawing copper items on board
|
|
|
|
int epsilon = Millimeter2iu( 0.01 );
|
2014-06-24 16:17:18 +00:00
|
|
|
int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
|
|
|
|
int board_thickness = g_Parm_3D_Visu.GetLayerZcoordBIU( F_Cu )
|
|
|
|
- g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
|
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
// items on copper layers and having a thickness = copper_thickness
|
|
|
|
// are drawn from zpos - copper_thickness/2 to zpos + copper_thickness
|
|
|
|
// therefore substrate position is copper_thickness/2 to
|
|
|
|
// substrate_height - copper_thickness/2
|
|
|
|
zpos += (copper_thickness + epsilon) / 2;
|
|
|
|
board_thickness -= copper_thickness + epsilon;
|
|
|
|
|
|
|
|
if( realistic_mode )
|
|
|
|
SetGLEpoxyColor();
|
|
|
|
else
|
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( Edge_Cuts );
|
2013-10-07 11:51:08 +00:00
|
|
|
SetGLColor( color, 0.7 );
|
|
|
|
}
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( F_Cu ) );
|
2013-10-07 11:51:08 +00:00
|
|
|
KI_POLYGON_SET currLayerPolyset;
|
|
|
|
KI_POLYGON_SET polysetHoles;
|
|
|
|
|
|
|
|
// Add polygons, without holes
|
|
|
|
bufferPcbOutlines.ExportTo( currLayerPolyset );
|
|
|
|
|
|
|
|
// Build holes list
|
|
|
|
allLayerHoles.ExportTo( polysetHoles );
|
|
|
|
|
|
|
|
// remove holes
|
|
|
|
currLayerPolyset -= polysetHoles;
|
|
|
|
|
|
|
|
bufferPcbOutlines.RemoveAllContours();
|
|
|
|
bufferPcbOutlines.ImportFrom( currLayerPolyset );
|
|
|
|
|
|
|
|
// for Draw3D_SolidHorizontalPolyPolygons, zpos it the middle between bottom and top
|
|
|
|
// sides
|
|
|
|
Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness/2,
|
|
|
|
board_thickness, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
|
|
|
}
|
2014-03-08 19:04:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EDA_3D_CANVAS::BuildTechLayers3DView()
|
|
|
|
{
|
|
|
|
BOARD* pcb = GetBoard();
|
|
|
|
|
|
|
|
// Number of segments to draw a circle using segments
|
|
|
|
const int segcountforcircle = 16;
|
|
|
|
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
|
|
|
|
const int segcountLowQuality = 12; // segments to draw a circle with low quality
|
|
|
|
// to reduce time calculations
|
|
|
|
// for holes and items which do not need
|
|
|
|
// a fine representation
|
2014-06-24 16:17:18 +00:00
|
|
|
|
2014-04-27 11:30:45 +00:00
|
|
|
double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) );
|
2014-03-08 19:04:23 +00:00
|
|
|
|
|
|
|
CPOLYGONS_LIST bufferPolys;
|
2014-03-09 18:43:53 +00:00
|
|
|
bufferPolys.reserve( 100000 ); // Reserve for large board
|
2014-03-08 19:04:23 +00:00
|
|
|
CPOLYGONS_LIST allLayerHoles; // Contains through holes, calculated only once
|
|
|
|
allLayerHoles.reserve( 20000 );
|
|
|
|
|
|
|
|
CPOLYGONS_LIST bufferPcbOutlines; // stores the board main outlines
|
|
|
|
// Build a polygon from edge cut items
|
|
|
|
wxString msg;
|
2014-04-27 11:30:45 +00:00
|
|
|
|
|
|
|
if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) )
|
2014-03-08 19:04:23 +00:00
|
|
|
{
|
|
|
|
msg << wxT("\n\n") <<
|
|
|
|
_("Unable to calculate the board outlines.\n"
|
|
|
|
"Therefore use the board boundary box.");
|
|
|
|
wxMessageBox( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
|
2014-04-30 19:16:22 +00:00
|
|
|
|
|
|
|
// Add via holes
|
2014-06-24 16:17:18 +00:00
|
|
|
for( VIA* via = GetFirstVia( pcb->m_Track ); via;
|
2014-04-30 19:16:22 +00:00
|
|
|
via = GetFirstVia( via->Next() ) )
|
2014-03-08 19:04:23 +00:00
|
|
|
{
|
2014-04-30 19:16:22 +00:00
|
|
|
VIATYPE_T viatype = via->GetViaType();
|
|
|
|
int holediameter = via->GetDrillValue();
|
|
|
|
int hole_outer_radius = (holediameter + thickness) / 2;
|
|
|
|
|
|
|
|
if( viatype == VIA_THROUGH )
|
|
|
|
TransformCircleToPolygon( allLayerHoles,
|
|
|
|
via->GetStart(), hole_outer_radius,
|
|
|
|
segcountLowQuality );
|
2014-03-08 19:04:23 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 18:43:53 +00:00
|
|
|
// draw pads holes
|
2014-06-24 16:17:18 +00:00
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2014-03-09 18:43:53 +00:00
|
|
|
{
|
|
|
|
// Add pad hole, if any
|
|
|
|
D_PAD* pad = module->Pads();
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( ; pad; pad = pad->Next() )
|
2014-03-09 18:43:53 +00:00
|
|
|
pad->BuildPadDrillShapePolygon( allLayerHoles, 0,
|
|
|
|
segcountLowQuality );
|
|
|
|
}
|
2014-03-08 19:04:23 +00:00
|
|
|
|
|
|
|
// draw graphic items, on technical layers
|
2013-10-07 11:51:08 +00:00
|
|
|
|
2013-10-07 14:50:23 +00:00
|
|
|
KI_POLYGON_SET brdpolysetHoles;
|
|
|
|
allLayerHoles.ExportTo( brdpolysetHoles );
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
static const LAYER_ID sequence[] = {
|
|
|
|
B_Adhes,
|
|
|
|
F_Adhes,
|
|
|
|
B_Paste,
|
|
|
|
F_Paste,
|
|
|
|
B_SilkS,
|
|
|
|
F_SilkS,
|
|
|
|
B_Mask,
|
|
|
|
F_Mask,
|
|
|
|
};
|
|
|
|
|
|
|
|
for( LSEQ seq = pcb->GetEnabledLayers().Seq( sequence, DIM( sequence ) ); seq; ++seq )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
LAYER_ID layer = *seq;
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
// Skip user layers, which are not drawn here
|
|
|
|
if( IsUserLayer( layer) )
|
|
|
|
continue;
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !Is3DLayerEnabled( layer ) )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
if( layer == Edge_Cuts && g_Parm_3D_Visu.GetFlag( FL_SHOW_BOARD_BODY ) )
|
2013-10-04 08:42:09 +00:00
|
|
|
continue;
|
|
|
|
|
2013-05-14 18:47:01 +00:00
|
|
|
bufferPolys.RemoveAllContours();
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
|
2012-08-21 10:45:54 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !item->IsOnLayer( layer ) )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_LINE_T:
|
2013-05-03 17:51:10 +00:00
|
|
|
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
|
2014-03-08 19:04:23 +00:00
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCB_TEXT_T:
|
2013-05-03 17:51:10 +00:00
|
|
|
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
|
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-08-21 10:45:54 +00:00
|
|
|
}
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
if( layer == F_SilkS || layer == B_SilkS )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
D_PAD* pad = module->Pads();
|
|
|
|
int linewidth = g_DrawDefaultLineThickness;
|
2013-05-01 19:01:14 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( ; pad; pad = pad->Next() )
|
2013-05-01 19:01:14 +00:00
|
|
|
{
|
|
|
|
if( !pad->IsOnLayer( layer ) )
|
|
|
|
continue;
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
BuildPadShapeThickOutlineAsPolygon( pad, bufferPolys,
|
2014-04-27 11:30:45 +00:00
|
|
|
linewidth, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
module->TransformPadsShapesWithClearanceToPolygon( layer,
|
2014-04-27 11:30:45 +00:00
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
2013-05-01 19:01:14 +00:00
|
|
|
|
|
|
|
module->TransformGraphicShapesWithClearanceToPolygonSet( layer,
|
2014-04-27 11:30:45 +00:00
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw non copper zones
|
|
|
|
if( g_Parm_3D_Visu.GetFlag( FL_ZONE ) )
|
|
|
|
{
|
|
|
|
for( int ii = 0; ii < pcb->GetAreaCount(); ii++ )
|
|
|
|
{
|
|
|
|
ZONE_CONTAINER* zone = pcb->GetArea( ii );
|
|
|
|
|
|
|
|
if( !zone->IsOnLayer( layer ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
zone->TransformSolidAreasShapesToPolygonSet(
|
|
|
|
bufferPolys, segcountLowQuality, correctionFactorLQ );
|
|
|
|
}
|
2008-08-17 18:37:03 +00:00
|
|
|
}
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// bufferPolys contains polygons to merge. Many overlaps .
|
|
|
|
// Calculate merged polygons and remove pads and vias holes
|
2013-05-09 19:08:12 +00:00
|
|
|
if( bufferPolys.GetCornersCount() == 0 )
|
2013-05-01 19:01:14 +00:00
|
|
|
continue;
|
2013-05-03 17:51:10 +00:00
|
|
|
KI_POLYGON_SET currLayerPolyset;
|
|
|
|
KI_POLYGON_SET polyset;
|
2013-10-04 08:42:09 +00:00
|
|
|
|
|
|
|
// Solder mask layers are "negative" layers.
|
|
|
|
// Shapes should be removed from the full board area.
|
2014-06-24 16:17:18 +00:00
|
|
|
if( layer == B_Mask || layer == F_Mask )
|
2013-10-04 08:42:09 +00:00
|
|
|
{
|
|
|
|
bufferPcbOutlines.ExportTo( currLayerPolyset );
|
|
|
|
bufferPolys.Append( allLayerHoles );
|
|
|
|
bufferPolys.ExportTo( polyset );
|
|
|
|
currLayerPolyset -= polyset;
|
|
|
|
}
|
2013-10-07 14:50:23 +00:00
|
|
|
// Remove holes from Solder paste layers and siklscreen
|
2014-06-24 16:17:18 +00:00
|
|
|
else if( layer == B_Paste || layer == F_Paste
|
|
|
|
|| layer == B_SilkS || layer == F_SilkS )
|
2013-10-07 14:50:23 +00:00
|
|
|
{
|
|
|
|
bufferPolys.ExportTo( currLayerPolyset );
|
|
|
|
currLayerPolyset -= brdpolysetHoles;
|
|
|
|
}
|
2013-10-04 08:42:09 +00:00
|
|
|
else // usuall layers, merge polys built from each item shape:
|
|
|
|
{
|
|
|
|
bufferPolys.ExportTo( polyset );
|
|
|
|
currLayerPolyset += polyset;
|
|
|
|
}
|
2012-08-11 12:52:13 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
int thickness = g_Parm_3D_Visu.GetLayerObjectThicknessBIU( layer );
|
|
|
|
int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer );
|
2007-05-06 16:03:28 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
if( layer == Edge_Cuts )
|
2013-10-07 11:51:08 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
thickness = g_Parm_3D_Visu.GetLayerZcoordBIU( F_Cu )
|
|
|
|
- g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
|
|
|
|
zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu )
|
2013-10-07 11:51:08 +00:00
|
|
|
+ (thickness / 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// for Draw3D_SolidHorizontalPolyPolygons, zpos it the middle between bottom and top
|
|
|
|
// sides.
|
|
|
|
// However for top layers, zpos should be the bottom layer pos,
|
|
|
|
// and for bottom layers, zpos should be the top layer pos.
|
|
|
|
if( Get3DLayer_Z_Orientation( layer ) > 0 )
|
|
|
|
zpos += thickness/2;
|
|
|
|
else
|
|
|
|
zpos -= thickness/2 ;
|
|
|
|
}
|
|
|
|
|
2013-05-14 18:47:01 +00:00
|
|
|
bufferPolys.RemoveAllContours();
|
2013-05-08 18:20:58 +00:00
|
|
|
bufferPolys.ImportFrom( currLayerPolyset );
|
2014-03-08 19:04:23 +00:00
|
|
|
|
|
|
|
SetGLTechLayersColor( layer );
|
|
|
|
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
|
2013-05-01 19:01:14 +00:00
|
|
|
Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
|
|
|
|
thickness, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
/**
|
|
|
|
* Function BuildBoard3DAuxLayers
|
|
|
|
* Called by CreateDrawGL_List()
|
|
|
|
* Fills the OpenGL GL_ID_BOARD draw list with items
|
|
|
|
* on aux layers only
|
|
|
|
*/
|
|
|
|
void EDA_3D_CANVAS::BuildBoard3DAuxLayers()
|
|
|
|
{
|
|
|
|
const int segcountforcircle = 16;
|
|
|
|
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) );
|
2014-06-24 16:17:18 +00:00
|
|
|
BOARD* pcb = GetBoard();
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
CPOLYGONS_LIST bufferPolys;
|
2014-06-24 16:17:18 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
bufferPolys.reserve( 5000 ); // Reserve for items not on board
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
static const LAYER_ID sequence[] = {
|
|
|
|
Dwgs_User,
|
|
|
|
Cmts_User,
|
|
|
|
Eco1_User,
|
|
|
|
Eco2_User,
|
|
|
|
Edge_Cuts,
|
|
|
|
Margin
|
|
|
|
};
|
|
|
|
|
|
|
|
for( LSEQ aux( sequence, sequence+DIM(sequence) ); aux; ++aux )
|
2014-03-05 17:40:23 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
LAYER_ID layer = *aux;
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
if( !Is3DLayerEnabled( layer ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bufferPolys.RemoveAllContours();
|
|
|
|
|
|
|
|
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
|
|
|
|
{
|
|
|
|
if( !item->IsOnLayer( layer ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch( item->Type() )
|
|
|
|
{
|
|
|
|
case PCB_LINE_T:
|
|
|
|
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
|
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PCB_TEXT_T:
|
|
|
|
( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet(
|
|
|
|
bufferPolys, 0, segcountforcircle, correctionFactor );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2014-03-08 19:04:23 +00:00
|
|
|
{
|
|
|
|
module->TransformPadsShapesWithClearanceToPolygon( layer,
|
|
|
|
bufferPolys,
|
|
|
|
0,
|
|
|
|
segcountforcircle,
|
|
|
|
correctionFactor );
|
|
|
|
|
|
|
|
module->TransformGraphicShapesWithClearanceToPolygonSet( layer,
|
|
|
|
bufferPolys,
|
|
|
|
0,
|
|
|
|
segcountforcircle,
|
|
|
|
correctionFactor );
|
|
|
|
}
|
|
|
|
|
|
|
|
// bufferPolys contains polygons to merge. Many overlaps .
|
|
|
|
// Calculate merged polygons and remove pads and vias holes
|
|
|
|
if( bufferPolys.GetCornersCount() == 0 )
|
|
|
|
continue;
|
|
|
|
KI_POLYGON_SET currLayerPolyset;
|
|
|
|
KI_POLYGON_SET polyset;
|
|
|
|
bufferPolys.ExportTo( polyset );
|
|
|
|
currLayerPolyset += polyset;
|
|
|
|
|
|
|
|
int thickness = g_Parm_3D_Visu.GetLayerObjectThicknessBIU( layer );
|
|
|
|
int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer );
|
|
|
|
// for Draw3D_SolidHorizontalPolyPolygons,
|
|
|
|
// zpos it the middle between bottom and top sides.
|
|
|
|
// However for top layers, zpos should be the bottom layer pos,
|
|
|
|
// and for bottom layers, zpos should be the top layer pos.
|
|
|
|
if( Get3DLayer_Z_Orientation( layer ) > 0 )
|
|
|
|
zpos += thickness/2;
|
|
|
|
else
|
|
|
|
zpos -= thickness/2 ;
|
|
|
|
|
|
|
|
bufferPolys.RemoveAllContours();
|
|
|
|
bufferPolys.ImportFrom( currLayerPolyset );
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
SetGLTechLayersColor( layer );
|
|
|
|
glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
|
|
|
|
Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
|
|
|
|
thickness, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
2014-03-05 17:40:23 +00:00
|
|
|
}
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
void EDA_3D_CANVAS::CreateDrawGL_List()
|
2012-08-21 10:45:54 +00:00
|
|
|
{
|
2014-03-08 19:04:23 +00:00
|
|
|
BOARD* pcb = GetBoard();
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
wxBusyCursor dummy;
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Build 3D board parameters:
|
|
|
|
g_Parm_3D_Visu.InitSettings( pcb );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
// Create axis gl list (if it is not shown, the list will be not called
|
|
|
|
Draw3DAxis();
|
|
|
|
|
|
|
|
// Create grid gl list
|
|
|
|
if( ! m_glLists[GL_ID_GRID] )
|
2012-08-21 10:45:54 +00:00
|
|
|
{
|
2014-03-08 19:04:23 +00:00
|
|
|
m_glLists[GL_ID_GRID] = glGenLists( 1 );
|
|
|
|
glNewList( m_glLists[GL_ID_GRID], GL_COMPILE );
|
|
|
|
|
|
|
|
Draw3DGrid( g_Parm_3D_Visu.m_3D_Grid );
|
|
|
|
glEndList();
|
2012-08-21 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
// Create Board full gl lists:
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-14 18:47:01 +00:00
|
|
|
// For testing purpose only, display calculation time to generate 3D data
|
2013-05-03 17:51:10 +00:00
|
|
|
// #define PRINT_CALCULATION_TIME
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
#ifdef PRINT_CALCULATION_TIME
|
|
|
|
unsigned strtime = GetRunningMicroSecs();
|
|
|
|
#endif
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
if( ! m_glLists[GL_ID_BOARD] )
|
|
|
|
{
|
|
|
|
m_glLists[GL_ID_BOARD] = glGenLists( 1 );
|
|
|
|
glNewList( m_glLists[GL_ID_BOARD], GL_COMPILE );
|
|
|
|
BuildBoard3DView();
|
|
|
|
glEndList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( ! m_glLists[GL_ID_TECH_LAYERS] )
|
|
|
|
{
|
|
|
|
m_glLists[GL_ID_TECH_LAYERS] = glGenLists( 1 );
|
|
|
|
glNewList( m_glLists[GL_ID_TECH_LAYERS], GL_COMPILE );
|
|
|
|
BuildTechLayers3DView();
|
|
|
|
glEndList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( ! m_glLists[GL_ID_AUX_LAYERS] )
|
|
|
|
{
|
|
|
|
m_glLists[GL_ID_AUX_LAYERS] = glGenLists( 1 );
|
|
|
|
glNewList( m_glLists[GL_ID_AUX_LAYERS], GL_COMPILE );
|
|
|
|
BuildBoard3DAuxLayers();
|
|
|
|
glEndList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// draw modules 3D shapes
|
|
|
|
if( ! m_glLists[GL_ID_3DSHAPES_SOLID] && g_Parm_3D_Visu.GetFlag( FL_MODULE ) )
|
|
|
|
{
|
|
|
|
m_glLists[GL_ID_3DSHAPES_SOLID] = glGenLists( 1 );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
// GL_ID_3DSHAPES_TRANSP is an auxiliary list for 3D shapes;
|
|
|
|
// Ensure it is cleared before rebuilding it
|
|
|
|
if( m_glLists[GL_ID_3DSHAPES_TRANSP] )
|
|
|
|
glDeleteLists( m_glLists[GL_ID_3DSHAPES_TRANSP], 1 );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
m_glLists[GL_ID_3DSHAPES_TRANSP] = glGenLists( 1 );
|
|
|
|
BuildFootprintShape3DList( m_glLists[GL_ID_3DSHAPES_SOLID],
|
|
|
|
m_glLists[GL_ID_3DSHAPES_TRANSP] );
|
|
|
|
}
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Test for errors
|
|
|
|
CheckGLError();
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
#ifdef PRINT_CALCULATION_TIME
|
2013-05-03 17:51:10 +00:00
|
|
|
unsigned endtime = GetRunningMicroSecs();
|
|
|
|
wxString msg;
|
|
|
|
msg.Printf( "Built data %.1f ms", (double) (endtime - strtime) / 1000 );
|
2013-05-01 19:01:14 +00:00
|
|
|
Parent()->SetStatusText( msg, 0 );
|
|
|
|
#endif
|
2014-03-08 19:04:23 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 18:43:53 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
|
|
|
|
GLuint aTransparentList)
|
|
|
|
{
|
|
|
|
// aOpaqueList is the gl list for non transparent items
|
|
|
|
// aTransparentList is the gl list for non transparent items,
|
|
|
|
// which need to be drawn after all other items
|
|
|
|
|
|
|
|
BOARD* pcb = GetBoard();
|
2014-03-09 18:43:53 +00:00
|
|
|
glNewList( aOpaqueList, GL_COMPILE );
|
|
|
|
bool loadTransparentObjects = false;
|
|
|
|
|
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
|
|
|
module->ReadAndInsert3DComponentShape( this, !loadTransparentObjects,
|
|
|
|
loadTransparentObjects );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2014-03-09 18:43:53 +00:00
|
|
|
glEndList();
|
|
|
|
|
|
|
|
glNewList( aTransparentList, GL_COMPILE );
|
|
|
|
loadTransparentObjects = true;
|
2014-03-08 19:04:23 +00:00
|
|
|
|
|
|
|
for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
|
2014-03-09 18:43:53 +00:00
|
|
|
module->ReadAndInsert3DComponentShape( this, !loadTransparentObjects,
|
|
|
|
loadTransparentObjects );
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
glEndList();
|
2012-08-21 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
2014-03-08 19:04:23 +00:00
|
|
|
void EDA_3D_CANVAS::Draw3DAxis()
|
|
|
|
{
|
|
|
|
if( ! m_glLists[GL_ID_AXIS] )
|
|
|
|
{
|
|
|
|
m_glLists[GL_ID_AXIS] = glGenLists( 1 );
|
|
|
|
glNewList( m_glLists[GL_ID_AXIS], GL_COMPILE );
|
|
|
|
|
|
|
|
glEnable( GL_COLOR_MATERIAL );
|
|
|
|
SetGLColor( WHITE );
|
|
|
|
glBegin( GL_LINES );
|
|
|
|
glNormal3f( 0.0f, 0.0f, 1.0f ); // Normal is Z axis
|
|
|
|
glVertex3f( 0.0f, 0.0f, 0.0f );
|
|
|
|
glVertex3f( 1.0f, 0.0f, 0.0f ); // X axis
|
|
|
|
glVertex3f( 0.0f, 0.0f, 0.0f );
|
|
|
|
glVertex3f( 0.0f, -1.0f, 0.0f ); // Y axis
|
|
|
|
glNormal3f( 1.0f, 0.0f, 0.0f ); // Normal is Y axis
|
|
|
|
glVertex3f( 0.0f, 0.0f, 0.0f );
|
|
|
|
glVertex3f( 0.0f, 0.0f, 0.3f ); // Z axis
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glEndList();
|
|
|
|
}
|
|
|
|
}
|
2007-11-01 05:27:31 +00:00
|
|
|
|
2012-08-26 13:59:55 +00:00
|
|
|
// draw a 3D grid: an horizontal grid (XY plane and Z = 0,
|
|
|
|
// and a vertical grid (XZ plane and Y = 0)
|
2014-03-08 19:04:23 +00:00
|
|
|
void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM )
|
2012-08-11 12:52:13 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
double zpos = 0.0;
|
2013-04-04 21:35:01 +00:00
|
|
|
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
|
|
|
|
EDA_COLOR_T gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines
|
2014-03-18 10:31:13 +00:00
|
|
|
const double scale = g_Parm_3D_Visu.m_BiuTo3Dunits;
|
|
|
|
const double transparency = 0.3;
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
glNormal3f( 0.0, 0.0, 1.0 );
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
wxSize brd_size = g_Parm_3D_Visu.m_BoardSize;
|
2012-08-11 12:52:13 +00:00
|
|
|
wxPoint brd_center_pos = g_Parm_3D_Visu.m_BoardPos;
|
|
|
|
NEGATE( brd_center_pos.y );
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) );
|
|
|
|
int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) );
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
// Grid limits, in 3D units
|
2013-05-03 17:51:10 +00:00
|
|
|
double xmin = (brd_center_pos.x - xsize / 2) * scale;
|
|
|
|
double xmax = (brd_center_pos.x + xsize / 2) * scale;
|
|
|
|
double ymin = (brd_center_pos.y - ysize / 2) * scale;
|
|
|
|
double ymax = (brd_center_pos.y + ysize / 2) * scale;
|
|
|
|
double zmin = Millimeter2iu( -50 ) * scale;
|
|
|
|
double zmax = Millimeter2iu( 100 ) * scale;
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
// Draw horizontal grid centered on 3D origin (center of the board)
|
|
|
|
for( int ii = 0; ; ii++ )
|
|
|
|
{
|
|
|
|
if( (ii % 5) )
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor, transparency );
|
2012-08-11 12:52:13 +00:00
|
|
|
else
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor_marker, transparency );
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM );
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
|
2012-08-11 12:52:13 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
|
|
|
|
glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
if( ii != 0 )
|
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
|
|
|
|
glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
|
2012-08-11 12:52:13 +00:00
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
|
|
|
|
glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
|
|
|
|
glEnd();
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2012-08-11 12:52:13 +00:00
|
|
|
if( ii != 0 )
|
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
|
|
|
|
glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
|
2012-08-11 12:52:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw vertical grid n Z axis
|
|
|
|
glNormal3f( 0.0, -1.0, 0.0 );
|
|
|
|
|
|
|
|
// Draw vertical grid lines (parallel to Z axis)
|
|
|
|
for( int ii = 0; ; ii++ )
|
|
|
|
{
|
|
|
|
if( (ii % 5) )
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor, transparency );
|
2012-08-11 12:52:13 +00:00
|
|
|
else
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor_marker, transparency );
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
double delta = ii * aGriSizeMM * IU_PER_MM;
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( (brd_center_pos.x + delta) * scale, -brd_center_pos.y * scale, zmin );
|
|
|
|
glVertex3f( (brd_center_pos.x + delta) * scale, -brd_center_pos.y * scale, zmax );
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
if( ii != 0 )
|
|
|
|
{
|
2013-05-03 17:51:10 +00:00
|
|
|
glBegin( GL_LINES );
|
2012-08-11 12:52:13 +00:00
|
|
|
glVertex3f( (brd_center_pos.x - delta) * scale, -brd_center_pos.y * scale, zmin );
|
|
|
|
glVertex3f( (brd_center_pos.x - delta) * scale, -brd_center_pos.y * scale, zmax );
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( delta > xsize / 2 )
|
2012-08-11 12:52:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw horizontal grid lines on Z axis
|
|
|
|
for( int ii = 0; ; ii++ )
|
|
|
|
{
|
|
|
|
if( (ii % 5) )
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor, transparency);
|
2012-08-11 12:52:13 +00:00
|
|
|
else
|
2013-10-04 08:42:09 +00:00
|
|
|
SetGLColor( gridcolor_marker, transparency );
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
double delta = ii * aGriSizeMM * IU_PER_MM * scale;
|
2012-08-11 12:52:13 +00:00
|
|
|
|
|
|
|
if( delta <= zmax )
|
2013-05-03 17:51:10 +00:00
|
|
|
{
|
|
|
|
// Draw grid lines on Z axis (positive Z axis coordinates)
|
|
|
|
glBegin( GL_LINES );
|
|
|
|
glVertex3f( xmin, -brd_center_pos.y * scale, delta );
|
|
|
|
glVertex3f( xmax, -brd_center_pos.y * scale, delta );
|
2012-08-11 12:52:13 +00:00
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( delta <= -zmin && ( ii != 0 ) )
|
2013-05-03 17:51:10 +00:00
|
|
|
{
|
|
|
|
// Draw grid lines on Z axis (negative Z axis coordinates)
|
|
|
|
glBegin( GL_LINES );
|
|
|
|
glVertex3f( xmin, -brd_center_pos.y * scale, -delta );
|
|
|
|
glVertex3f( xmax, -brd_center_pos.y * scale, -delta );
|
2012-08-11 12:52:13 +00:00
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( ( delta > zmax ) && ( delta > -zmin ) )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-04-25 06:00:04 +00:00
|
|
|
void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
LAYER_ID top_layer, bottom_layer;
|
2013-05-03 17:51:10 +00:00
|
|
|
int inner_radius = aVia->GetDrillValue() / 2;
|
|
|
|
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
|
2009-10-10 01:25:53 +00:00
|
|
|
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
aVia->LayerPair( &top_layer, &bottom_layer );
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2012-08-26 13:59:55 +00:00
|
|
|
// Drawing via hole:
|
2013-10-07 11:51:08 +00:00
|
|
|
if( g_Parm_3D_Visu.IsRealisticMode() )
|
|
|
|
SetGLCopperColor();
|
|
|
|
else
|
|
|
|
{
|
2014-04-25 06:00:04 +00:00
|
|
|
EDA_COLOR_T color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + aVia->GetViaType() );
|
2013-10-07 11:51:08 +00:00
|
|
|
SetGLColor( color );
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
int height = g_Parm_3D_Visu.GetLayerZcoordBIU( top_layer ) -
|
|
|
|
g_Parm_3D_Visu.GetLayerZcoordBIU( bottom_layer ) - thickness;
|
|
|
|
int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( bottom_layer ) + thickness / 2;
|
2012-08-26 13:59:55 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius + thickness / 2, height,
|
2013-05-01 19:01:14 +00:00
|
|
|
thickness, zpos, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2014-03-09 18:43:53 +00:00
|
|
|
void MODULE::ReadAndInsert3DComponentShape( EDA_3D_CANVAS* glcanvas,
|
|
|
|
bool aAllowNonTransparentObjects,
|
|
|
|
bool aAllowTransparentObjects )
|
2008-08-16 17:42:40 +00:00
|
|
|
{
|
2011-02-16 21:51:35 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
// Read from disk and draws the footprint 3D shapes if exists
|
|
|
|
S3D_MASTER* shape3D = m_3D_Drawings;
|
|
|
|
double zpos = g_Parm_3D_Visu.GetModulesZcoord3DIU( IsFlipped() );
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
glPushMatrix();
|
2012-08-27 11:41:22 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
glTranslatef( m_Pos.x * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
|
|
|
-m_Pos.y * g_Parm_3D_Visu.m_BiuTo3Dunits,
|
|
|
|
zpos );
|
2008-11-24 06:53:43 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
if( m_Orient )
|
|
|
|
glRotatef( (double) m_Orient / 10, 0.0, 0.0, 1.0 );
|
2008-11-24 06:53:43 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
if( IsFlipped() )
|
|
|
|
{
|
|
|
|
glRotatef( 180.0, 0.0, 1.0, 0.0 );
|
|
|
|
glRotatef( 180.0, 0.0, 0.0, 1.0 );
|
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
for( ; shape3D; shape3D = shape3D->Next() )
|
2014-03-05 17:40:23 +00:00
|
|
|
{
|
2014-03-09 18:43:53 +00:00
|
|
|
shape3D->SetLoadNonTransparentObjects( aAllowNonTransparentObjects );
|
|
|
|
shape3D->SetLoadTransparentObjects( aAllowTransparentObjects );
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2014-03-05 17:40:23 +00:00
|
|
|
if( shape3D->Is3DType( S3D_MASTER::FILE3D_VRML ) )
|
|
|
|
shape3D->ReadData();
|
2008-08-17 18:37:03 +00:00
|
|
|
}
|
2014-03-05 17:40:23 +00:00
|
|
|
|
|
|
|
glPopMatrix();
|
2007-05-06 16:03:28 +00:00
|
|
|
}
|
|
|
|
|
2011-11-24 17:32:51 +00:00
|
|
|
|
2012-02-02 17:45:37 +00:00
|
|
|
// Draw 3D pads.
|
2014-04-25 06:00:04 +00:00
|
|
|
void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
|
2007-05-06 16:03:28 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
// Draw the pad hole
|
2013-05-03 17:51:10 +00:00
|
|
|
wxSize drillsize = aPad->GetDrillSize();
|
|
|
|
bool hasHole = drillsize.x && drillsize.y;
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
if( !hasHole )
|
2013-05-01 19:01:14 +00:00
|
|
|
return;
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2012-08-26 13:59:55 +00:00
|
|
|
// Store here the points to approximate hole by segments
|
2013-05-03 17:51:10 +00:00
|
|
|
CPOLYGONS_LIST holecornersBuffer;
|
|
|
|
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
|
2014-06-24 16:17:18 +00:00
|
|
|
int height = g_Parm_3D_Visu.GetLayerZcoordBIU( F_Cu ) -
|
|
|
|
g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
|
2009-11-04 20:46:53 +00:00
|
|
|
|
2013-10-07 11:51:08 +00:00
|
|
|
if( g_Parm_3D_Visu.IsRealisticMode() )
|
|
|
|
SetGLCopperColor();
|
|
|
|
else
|
|
|
|
SetGLColor( DARKGRAY );
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
int holeZpoz = g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu ) + thickness / 2;
|
2013-05-03 17:51:10 +00:00
|
|
|
int holeHeight = height - thickness;
|
2012-08-26 13:59:55 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
if( drillsize.x == drillsize.y ) // usual round hole
|
2008-03-03 08:00:26 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
Draw3D_ZaxisCylinder( aPad->GetPosition(),
|
|
|
|
(drillsize.x + thickness) / 2, holeHeight,
|
|
|
|
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
2013-05-01 19:01:14 +00:00
|
|
|
else // Oblong hole
|
2008-03-03 08:00:26 +00:00
|
|
|
{
|
2012-08-26 13:59:55 +00:00
|
|
|
wxPoint ends_offset;
|
2013-05-03 17:51:10 +00:00
|
|
|
int width;
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
if( drillsize.x > drillsize.y ) // Horizontal oval
|
2012-08-26 13:59:55 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
|
|
|
|
width = drillsize.y;
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
2013-05-01 19:01:14 +00:00
|
|
|
else // Vertical oval
|
2008-03-03 08:00:26 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
|
|
|
|
width = drillsize.x;
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
RotatePoint( &ends_offset, aPad->GetOrientation() );
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
wxPoint start = aPad->GetPosition() + ends_offset;
|
|
|
|
wxPoint end = aPad->GetPosition() - ends_offset;
|
|
|
|
int hole_radius = ( width + thickness ) / 2;
|
2008-03-03 08:00:26 +00:00
|
|
|
|
2013-05-01 19:01:14 +00:00
|
|
|
// Draw the hole
|
|
|
|
Draw3D_ZaxisOblongCylinder( start, end, hole_radius, holeHeight,
|
|
|
|
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
|
2008-03-03 08:00:26 +00:00
|
|
|
}
|
2010-08-19 14:21:05 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
static bool Is3DLayerEnabled( LAYER_ID aLayer )
|
2008-08-16 17:42:40 +00:00
|
|
|
{
|
2013-10-07 14:50:23 +00:00
|
|
|
DISPLAY3D_FLG flg;
|
2013-10-07 11:51:08 +00:00
|
|
|
bool realistic_mode = g_Parm_3D_Visu.IsRealisticMode();
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2012-04-09 09:16:47 +00:00
|
|
|
// see if layer needs to be shown
|
|
|
|
// check the flags
|
2013-05-03 17:51:10 +00:00
|
|
|
switch( aLayer )
|
2012-04-09 09:16:47 +00:00
|
|
|
{
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Adhes:
|
|
|
|
case F_Adhes:
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_ADHESIVE;
|
2013-05-16 19:04:21 +00:00
|
|
|
break;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Paste:
|
|
|
|
case F_Paste:
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_SOLDERPASTE;
|
2013-05-16 19:04:21 +00:00
|
|
|
break;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_SilkS:
|
|
|
|
case F_SilkS:
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_SILKSCREEN;
|
2013-05-03 17:51:10 +00:00
|
|
|
break;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Mask:
|
|
|
|
case F_Mask:
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_SOLDERMASK;
|
2013-05-16 19:04:21 +00:00
|
|
|
break;
|
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case Dwgs_User:
|
|
|
|
case Cmts_User:
|
2013-10-07 11:51:08 +00:00
|
|
|
if( realistic_mode )
|
|
|
|
return false;
|
|
|
|
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_COMMENTS;
|
2013-05-03 17:51:10 +00:00
|
|
|
break;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case Eco1_User:
|
|
|
|
case Eco2_User:
|
2013-10-07 11:51:08 +00:00
|
|
|
if( realistic_mode )
|
|
|
|
return false;
|
|
|
|
|
2013-10-07 14:50:23 +00:00
|
|
|
flg = FL_ECO;
|
2013-05-03 17:51:10 +00:00
|
|
|
break;
|
2013-03-20 14:50:12 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
case B_Cu:
|
|
|
|
case F_Cu:
|
2013-10-07 11:51:08 +00:00
|
|
|
return g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( aLayer )
|
|
|
|
|| realistic_mode;
|
|
|
|
break;
|
|
|
|
|
2013-05-03 17:51:10 +00:00
|
|
|
default:
|
2013-10-07 11:51:08 +00:00
|
|
|
// the layer is an internal copper layer
|
|
|
|
if( realistic_mode )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( aLayer );
|
2013-03-31 13:27:46 +00:00
|
|
|
}
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2012-04-09 09:16:47 +00:00
|
|
|
// if the layer has a flag, return the flag
|
2013-10-07 14:50:23 +00:00
|
|
|
return g_Parm_3D_Visu.GetFlag( flg ) &&
|
2013-10-07 11:51:08 +00:00
|
|
|
g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( aLayer );
|
2008-08-16 17:42:40 +00:00
|
|
|
}
|
|
|
|
|
2008-08-17 18:37:03 +00:00
|
|
|
|
2013-03-31 13:27:46 +00:00
|
|
|
GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer )
|
2008-08-16 17:42:40 +00:00
|
|
|
{
|
2013-05-01 19:01:14 +00:00
|
|
|
double nZ = 1.0;
|
2011-09-07 19:41:04 +00:00
|
|
|
|
2014-06-24 16:17:18 +00:00
|
|
|
if( ( aLayer == B_Cu )
|
|
|
|
|| ( aLayer == B_Adhes )
|
|
|
|
|| ( aLayer == B_Paste )
|
|
|
|
|| ( aLayer == B_SilkS )
|
|
|
|
|| ( aLayer == B_Mask ) )
|
2008-08-17 18:37:03 +00:00
|
|
|
nZ = -1.0;
|
2012-08-21 10:45:54 +00:00
|
|
|
|
2008-08-17 18:37:03 +00:00
|
|
|
return nZ;
|
2008-08-16 17:42:40 +00:00
|
|
|
}
|