3D viewer: move helper functions from 3d_draw.cpp to 3d_draw_helper_functions.cpp. Add comments in .h sources. Better management of background color. coding style fixes.

This commit is contained in:
jean-pierre charras 2014-08-04 13:28:29 +02:00
parent 64a9ebc70e
commit 5f63becff1
7 changed files with 3942 additions and 3809 deletions

View File

@ -52,8 +52,9 @@ void CheckGLError(const char *aFileName, int aLineNumber)
} }
errLast = err; errLast = err;
wxLogError( wxT( "OpenGL error %d At: %s, line: %d" ), err, GetChars( FROM_UTF8( aFileName ) ), aLineNumber ); wxLogError( wxT( "OpenGL error %d At: %s, line: %d" ), err,
GetChars( FROM_UTF8( aFileName ) ), aLineNumber );
} }
} }
@ -625,7 +626,7 @@ void EDA_3D_CANVAS::TakeScreenshot( wxCommandEvent& event )
wxYield(); wxYield();
} }
struct vieport_params struct viewport_params
{ {
GLint originx; GLint originx;
GLint originy; GLint originy;
@ -633,6 +634,10 @@ void EDA_3D_CANVAS::TakeScreenshot( wxCommandEvent& event )
GLint y; GLint y;
} viewport; } viewport;
// Be sure we have the latest 3D view (remember 3D view is buffered)
Refresh();
wxYield();
// Build image from the 3D buffer // Build image from the 3D buffer
wxWindowUpdateLocker noUpdates( this ); wxWindowUpdateLocker noUpdates( this );
glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport ); glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport );

View File

@ -46,6 +46,7 @@
class BOARD_DESIGN_SETTINGS; class BOARD_DESIGN_SETTINGS;
class EDA_3D_FRAME; class EDA_3D_FRAME;
class CPOLYGONS_LIST;
class VIA; class VIA;
class D_PAD; class D_PAD;
@ -134,15 +135,40 @@ public:
void CreateDrawGL_List(); void CreateDrawGL_List();
void InitGL(); void InitGL();
void SetLights(); void SetLights();
void SetOffset(double aPosX, double aPosY) void SetOffset(double aPosX, double aPosY)
{ {
m_draw3dOffset.x = aPosX; m_draw3dOffset.x = aPosX;
m_draw3dOffset.y = aPosY; m_draw3dOffset.y = aPosY;
} }
private:
/**
* Helper function SetGLTechLayersColor
* Initialize the color to draw the non copper layers
* in realistic mode and normal mode.
*/
void SetGLTechLayersColor( LAYER_NUM aLayer ); void SetGLTechLayersColor( LAYER_NUM aLayer );
/**
* Helper function SetGLCopperColor
* Initialize the copper color to draw the board
* in realistic mode (a golden yellow color )
*/
void SetGLCopperColor(); void SetGLCopperColor();
/**
* Helper function SetGLEpoxyColor
* Initialize the color to draw the epoxy body board in realistic mode.
*/
void SetGLEpoxyColor( double aTransparency = 1.0 ); void SetGLEpoxyColor( double aTransparency = 1.0 );
/**
* Helper function SetGLSolderMaskColor
* Initialize the color to draw the solder mask layers in realistic mode.
*/
void SetGLSolderMaskColor( double aTransparency = 1.0 );
/** /**
* Function BuildBoard3DView * Function BuildBoard3DView
* Called by CreateDrawGL_List() * Called by CreateDrawGL_List()
@ -187,7 +213,31 @@ public:
void Draw3DGrid( double aGriSizeMM ); void Draw3DGrid( double aGriSizeMM );
void Draw3DAxis(); void Draw3DAxis();
/**
* Helper function BuildPadShapeThickOutlineAsPolygon:
* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
* with a line thickness = aWidth
* Used only to draw pads outlines on silkscreen layers.
*/
void BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer,
int aWidth,
int aCircleToSegmentsCount,
double aCorrectionFactor );
/**
* Helper function Draw3DViaHole:
* Draw the via hole:
* Build a vertical hole (a cylinder) between the first and the last via layers
*/
void Draw3DViaHole( const VIA * aVia ); void Draw3DViaHole( const VIA * aVia );
/**
* Helper function Draw3DPadHole:
* Draw the pad hole:
* Build a vertical hole (round or oblong) between the front and back layers
*/
void Draw3DPadHole( const D_PAD * aPad ); void Draw3DPadHole( const D_PAD * aPad );
void GenerateFakeShadowsTextures(); void GenerateFakeShadowsTextures();

View File

@ -65,44 +65,9 @@ static bool Is3DLayerEnabled( LAYER_ID aLayer );
*/ */
static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer ); static GLfloat Get3DLayer_Z_Orientation( LAYER_NUM aLayer );
/* 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.
*/
static void BuildPadShapeThickOutlineAsPolygon( D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer,
int aWidth,
int aCircleToSegmentsCount,
double aCorrectionFactor )
{
if( aPad->GetShape() == PAD_CIRCLE ) // Draw a ring
{
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
aPad->GetSize().x / 2, aCircleToSegmentsCount, aWidth );
return;
}
// For other shapes, draw polygon outlines /* Based on the tutorial http://www.ulrichmierendorff.com/software/opengl_blur.html
CPOLYGONS_LIST corners; * It will blur a openGL texture
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
aCircleToSegmentsCount, aCorrectionFactor );
// Add outlines as thick segments in polygon buffer
for( unsigned ii = 0, jj = corners.GetCornersCount() - 1;
ii < corners.GetCornersCount(); jj = ii, ii++ )
{
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
corners.GetPos( jj ),
corners.GetPos( ii ),
aCircleToSegmentsCount, aWidth );
}
}
// Based on the tutorial by http://www.ulrichmierendorff.com/software/opengl_blur.html
/* It will blur a openGL texture
*
*/ */
static void blur_tex( GLuint aTex, int aPasses, GLuint aTexture_size ) static void blur_tex( GLuint aTex, int aPasses, GLuint aTexture_size )
{ {
@ -297,20 +262,23 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures()
{ {
return; return;
} }
m_shadow_init = true;
// Init info 3d parameters and create gl lists:
CreateDrawGL_List(); CreateDrawGL_List();
m_shadow_init = true;
glClearColor( 0, 0, 0, 1 ); glClearColor( 0, 0, 0, 1 );
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadIdentity(); glLoadIdentity();
const double ZDIST_MAX = Millimeter2iu( 3.5 ) * g_Parm_3D_Visu.m_BiuTo3Dunits;
glOrtho( -g_Parm_3D_Visu.m_BoardSize.x * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, glOrtho( -g_Parm_3D_Visu.m_BoardSize.x * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
g_Parm_3D_Visu.m_BoardSize.x * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, g_Parm_3D_Visu.m_BoardSize.x * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
-g_Parm_3D_Visu.m_BoardSize.y * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, -g_Parm_3D_Visu.m_BoardSize.y * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
g_Parm_3D_Visu.m_BoardSize.y * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, g_Parm_3D_Visu.m_BoardSize.y * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
0.0, 3500000 * g_Parm_3D_Visu.m_BiuTo3Dunits ); 0.0, ZDIST_MAX );
// Render FRONT shadow // Render FRONT shadow
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
@ -336,7 +304,7 @@ void EDA_3D_CANVAS::GenerateFakeShadowsTextures()
g_Parm_3D_Visu.m_BoardSize.x * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, g_Parm_3D_Visu.m_BoardSize.x * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
-g_Parm_3D_Visu.m_BoardSize.y * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, -g_Parm_3D_Visu.m_BoardSize.y * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
g_Parm_3D_Visu.m_BoardSize.y * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f, g_Parm_3D_Visu.m_BoardSize.y * SHADOW_BOARD_SCALE * g_Parm_3D_Visu.m_BiuTo3Dunits / 2.0f,
0.0, 6.0f * 3500000 * g_Parm_3D_Visu.m_BiuTo3Dunits ); 0.0, 6.0f * ZDIST_MAX );
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); glLoadIdentity();
@ -368,7 +336,7 @@ void EDA_3D_CANVAS::Redraw()
if( g_Parm_3D_Visu.GetFlag( FL_MODULE ) && g_Parm_3D_Visu.IsRealisticMode() && if( g_Parm_3D_Visu.GetFlag( FL_MODULE ) && g_Parm_3D_Visu.IsRealisticMode() &&
g_Parm_3D_Visu.HightQualityMode() ) g_Parm_3D_Visu.HightQualityMode() )
{ {
GenerateFakeShadowsTextures (); GenerateFakeShadowsTextures();
} }
// *MUST* be called *after* SetCurrent( ): // *MUST* be called *after* SetCurrent( ):
@ -392,18 +360,29 @@ void EDA_3D_CANVAS::Redraw()
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
// Draw the background ( rectangle with color gradient)
glBegin( GL_QUADS ); glBegin( GL_QUADS );
glColor4f( 0.95, 0.95, 1.0, 1.0 ); #define BGCOLOR1(x) (x)
glVertex2f( -1.0, 0.85 ); #define BGCOLOR2(x) (x * 0.3)
glColor4f( BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Red ),
BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Green ),
BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Blue ),
1.0 );
glVertex2f( -1.0, 1.0 ); // Top left corner
glColor4f( g_Parm_3D_Visu.m_BgColor.m_Red, glColor4f( BGCOLOR2( g_Parm_3D_Visu.m_BgColor.m_Red ),
g_Parm_3D_Visu.m_BgColor.m_Green, BGCOLOR2( g_Parm_3D_Visu.m_BgColor.m_Green ),
g_Parm_3D_Visu.m_BgColor.m_Blue, 1.0 ); BGCOLOR2( g_Parm_3D_Visu.m_BgColor.m_Blue ),
glVertex2f( -1.0,-1.0 ); 1.0 );
glVertex2f( 1.0,-1.0 ); glVertex2f( -1.0,-1.0 ); // bottom left corner
glVertex2f( 1.0,-1.0 ); // bottom right corner
glColor4f( BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Red ),
BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Green ),
BGCOLOR1( g_Parm_3D_Visu.m_BgColor.m_Blue ),
1.0 );
glVertex2f( 1.0, 1.0 ); // top right corner
glColor4f( 0.95, 0.95, 1.0, 1.0 );
glVertex2f( 1.0, 0.85 );
glEnd(); glEnd();
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
@ -579,84 +558,10 @@ void EDA_3D_CANVAS::Redraw()
glDisable( GL_CULL_FACE ); glDisable( GL_CULL_FACE );
} }
} }
SwapBuffers(); SwapBuffers();
} }
// Helper function: initialize the copper color to draw the board
// in realistic mode.
void EDA_3D_CANVAS::SetGLCopperColor()
{
glDisable( GL_TEXTURE_2D );
// 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
// body board in realistic mode.
void EDA_3D_CANVAS::SetGLEpoxyColor( double aTransparency )
{
// Generates an epoxy color, near board color
const double lum = 0.2/255.0;
glColor4f( 255.0*lum, 218.0*lum, 110.0*lum, aTransparency );
}
// Helper function: initialize the color to draw the
// solder mask layers in realistic mode.
static inline void SetGLSolderMaskColor( double aTransparency = 1.0 )
{
// Generates a solder mask 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.
void EDA_3D_CANVAS::SetGLTechLayersColor( LAYER_NUM aLayer )
{
EDA_COLOR_T color;
if( g_Parm_3D_Visu.IsRealisticMode() )
{
switch( aLayer )
{
case B_Paste:
case F_Paste:
SetGLColor( DARKGRAY, 0.7 );
break;
case B_SilkS:
case F_SilkS:
SetGLColor( LIGHTGRAY, 0.9 );
if( g_Parm_3D_Visu.HightQualityMode() )
{
SetGLTexture( m_text_silk, 50.0f );
}
break;
case B_Mask:
case F_Mask:
SetGLSolderMaskColor( 0.7 );
if( g_Parm_3D_Visu.HightQualityMode() )
{
SetGLTexture( m_text_pcb, 35.0f );
}
break;
default:
color = g_ColorsSettings.GetLayerColor( aLayer );
SetGLColor( color, 0.7 );
break;
}
}
else
{
color = g_ColorsSettings.GetLayerColor( aLayer );
SetGLColor( color, 0.7 );
}
}
void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList ) void EDA_3D_CANVAS::BuildShadowList( GLuint aFrontList, GLuint aBacklist, GLuint aBoardList )
{ {
@ -1037,12 +942,14 @@ void EDA_3D_CANVAS::BuildBoard3DView(GLuint aBoardList, GLuint aBodyOnlyList)
glNewList( aBodyOnlyList, GL_COMPILE ); glNewList( aBodyOnlyList, GL_COMPILE );
if( bufferPcbOutlines.GetCornersCount() ) if( bufferPcbOutlines.GetCornersCount() )
{ {
glColor4f( 1.0, 1.0, 1.0, 1.0 ); glColor4f( 1.0, 1.0, 1.0, 1.0 );
Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness/2.0, Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness/2.0,
board_thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); board_thickness, g_Parm_3D_Visu.m_BiuTo3Dunits );
} }
glEndList(); glEndList();
} }
@ -1443,7 +1350,7 @@ void EDA_3D_CANVAS::CreateDrawGL_List()
CheckGLError( __FILE__, __LINE__ ); CheckGLError( __FILE__, __LINE__ );
} }
#ifdef PRINT_CALCULATION_TIME #ifdef PRINT_CALCULATION_TIME
unsigned endtime = GetRunningMicroSecs(); unsigned endtime = GetRunningMicroSecs();
@ -1481,192 +1388,6 @@ void EDA_3D_CANVAS::BuildFootprintShape3DList( GLuint aOpaqueList,
glEndList(); glEndList();
} }
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();
}
}
// draw a 3D grid: an horizontal grid (XY plane and Z = 0,
// and a vertical grid (XZ plane and Y = 0)
void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM )
{
double zpos = 0.0;
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
EDA_COLOR_T gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines
const double scale = g_Parm_3D_Visu.m_BiuTo3Dunits;
const double transparency = 0.3;
glNormal3f( 0.0, 0.0, 1.0 );
wxSize brd_size = g_Parm_3D_Visu.m_BoardSize;
wxPoint brd_center_pos = g_Parm_3D_Visu.m_BoardPos;
NEGATE( brd_center_pos.y );
int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) );
int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) );
// Grid limits, in 3D units
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;
// Draw horizontal grid centered on 3D origin (center of the board)
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor, transparency );
else
SetGLColor( gridcolor_marker, transparency );
int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM );
if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
{
glBegin( GL_LINES );
glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
glEnd();
if( ii != 0 )
{
glBegin( GL_LINES );
glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
glEnd();
}
}
if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
{
glBegin( GL_LINES );
glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
glEnd();
if( ii != 0 )
{
glBegin( GL_LINES );
glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
glEnd();
}
}
if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
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) )
SetGLColor( gridcolor, transparency );
else
SetGLColor( gridcolor_marker, transparency );
double delta = ii * aGriSizeMM * IU_PER_MM;
glBegin( GL_LINES );
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 )
{
glBegin( GL_LINES );
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( delta > xsize / 2 )
break;
}
// Draw horizontal grid lines on Z axis
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor, transparency);
else
SetGLColor( gridcolor_marker, transparency );
double delta = ii * aGriSizeMM * IU_PER_MM * scale;
if( delta <= zmax )
{
// 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 );
glEnd();
}
if( delta <= -zmin && ( ii != 0 ) )
{
// 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 );
glEnd();
}
if( ( delta > zmax ) && ( delta > -zmin ) )
break;
}
}
void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia )
{
LAYER_ID top_layer, bottom_layer;
int inner_radius = aVia->GetDrillValue() / 2;
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
aVia->LayerPair( &top_layer, &bottom_layer );
// Drawing via hole:
if( g_Parm_3D_Visu.IsRealisticMode() )
SetGLCopperColor();
else
{
EDA_COLOR_T color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + aVia->GetViaType() );
SetGLColor( color );
}
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;
Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius + thickness / 2, height,
thickness, zpos, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
void MODULE::ReadAndInsert3DComponentShape( EDA_3D_CANVAS* glcanvas, void MODULE::ReadAndInsert3DComponentShape( EDA_3D_CANVAS* glcanvas,
bool aAllowNonTransparentObjects, bool aAllowNonTransparentObjects,
@ -1706,65 +1427,6 @@ void MODULE::ReadAndInsert3DComponentShape( EDA_3D_CANVAS* glcanvas,
} }
// Draw 3D pads.
void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
{
// Draw the pad hole
wxSize drillsize = aPad->GetDrillSize();
bool hasHole = drillsize.x && drillsize.y;
if( !hasHole )
return;
// Store here the points to approximate hole by segments
CPOLYGONS_LIST holecornersBuffer;
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
int height = g_Parm_3D_Visu.GetLayerZcoordBIU( F_Cu ) -
g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
if( g_Parm_3D_Visu.IsRealisticMode() )
SetGLCopperColor();
else
SetGLColor( DARKGRAY );
int holeZpoz = g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu ) + thickness / 2;
int holeHeight = height - thickness;
if( drillsize.x == drillsize.y ) // usual round hole
{
Draw3D_ZaxisCylinder( aPad->GetPosition(),
(drillsize.x + thickness) / 2, holeHeight,
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
else // Oblong hole
{
wxPoint ends_offset;
int width;
if( drillsize.x > drillsize.y ) // Horizontal oval
{
ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
width = drillsize.y;
}
else // Vertical oval
{
ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
width = drillsize.x;
}
RotatePoint( &ends_offset, aPad->GetOrientation() );
wxPoint start = aPad->GetPosition() + ends_offset;
wxPoint end = aPad->GetPosition() - ends_offset;
int hole_radius = ( width + thickness ) / 2;
// Draw the hole
Draw3D_ZaxisOblongCylinder( start, end, hole_radius, holeHeight,
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
}
static bool Is3DLayerEnabled( LAYER_ID aLayer ) static bool Is3DLayerEnabled( LAYER_ID aLayer )
{ {
DISPLAY3D_FLG flg; DISPLAY3D_FLG flg;

View File

@ -0,0 +1,395 @@
/*
* 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
*/
/**
* @file 3d_draw_helper_functions.cpp
*/
#include <fctsys.h>
#include <Polyline.h>
#include <colors.h>
#include <colors_selection.h>
#include <class_pad.h>
#include <class_track.h>
#include <convert_basic_shapes_to_polygon.h>
#include <3d_viewer.h>
#include <3d_canvas.h>
#include <info3d_visu.h>
#include <3d_draw_basic_functions.h>
// Helper function: initialize the copper color to draw the board
// in realistic mode.
void EDA_3D_CANVAS::SetGLCopperColor()
{
glDisable( GL_TEXTURE_2D );
// 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
// body board in realistic mode.
void EDA_3D_CANVAS::SetGLEpoxyColor( double aTransparency )
{
// Generates an epoxy color, near board color
const double lum = 0.2/255.0;
glColor4f( 255.0*lum, 218.0*lum, 110.0*lum, aTransparency );
}
// Helper function: initialize the color to draw the
// solder mask layers in realistic mode.
void EDA_3D_CANVAS::SetGLSolderMaskColor( double aTransparency )
{
// Generates a solder mask 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.
void EDA_3D_CANVAS::SetGLTechLayersColor( LAYER_NUM aLayer )
{
EDA_COLOR_T color;
if( g_Parm_3D_Visu.IsRealisticMode() )
{
switch( aLayer )
{
case B_Paste:
case F_Paste:
SetGLColor( DARKGRAY, 0.7 );
break;
case B_SilkS:
case F_SilkS:
SetGLColor( LIGHTGRAY, 0.9 );
if( g_Parm_3D_Visu.HightQualityMode() )
{
SetGLTexture( m_text_silk, 50.0f );
}
break;
case B_Mask:
case F_Mask:
SetGLSolderMaskColor( 0.7 );
if( g_Parm_3D_Visu.HightQualityMode() )
{
SetGLTexture( m_text_pcb, 35.0f );
}
break;
default:
color = g_ColorsSettings.GetLayerColor( aLayer );
SetGLColor( color, 0.7 );
break;
}
}
else
{
color = g_ColorsSettings.GetLayerColor( aLayer );
SetGLColor( color, 0.7 );
}
}
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();
}
}
// draw a 3D grid: an horizontal grid (XY plane and Z = 0,
// and a vertical grid (XZ plane and Y = 0)
void EDA_3D_CANVAS::Draw3DGrid( double aGriSizeMM )
{
double zpos = 0.0;
EDA_COLOR_T gridcolor = DARKGRAY; // Color of grid lines
EDA_COLOR_T gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines
const double scale = g_Parm_3D_Visu.m_BiuTo3Dunits;
const double transparency = 0.3;
glNormal3f( 0.0, 0.0, 1.0 );
wxSize brd_size = g_Parm_3D_Visu.m_BoardSize;
wxPoint brd_center_pos = g_Parm_3D_Visu.m_BoardPos;
NEGATE( brd_center_pos.y );
int xsize = std::max( brd_size.x, Millimeter2iu( 100 ) );
int ysize = std::max( brd_size.y, Millimeter2iu( 100 ) );
// Grid limits, in 3D units
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;
// Draw horizontal grid centered on 3D origin (center of the board)
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor, transparency );
else
SetGLColor( gridcolor_marker, transparency );
int delta = KiROUND( ii * aGriSizeMM * IU_PER_MM );
if( delta <= xsize / 2 ) // Draw grid lines parallel to X axis
{
glBegin( GL_LINES );
glVertex3f( (brd_center_pos.x + delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x + delta) * scale, -ymax, zpos );
glEnd();
if( ii != 0 )
{
glBegin( GL_LINES );
glVertex3f( (brd_center_pos.x - delta) * scale, -ymin, zpos );
glVertex3f( (brd_center_pos.x - delta) * scale, -ymax, zpos );
glEnd();
}
}
if( delta <= ysize / 2 ) // Draw grid lines parallel to Y axis
{
glBegin( GL_LINES );
glVertex3f( xmin, -(brd_center_pos.y + delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y + delta) * scale, zpos );
glEnd();
if( ii != 0 )
{
glBegin( GL_LINES );
glVertex3f( xmin, -(brd_center_pos.y - delta) * scale, zpos );
glVertex3f( xmax, -(brd_center_pos.y - delta) * scale, zpos );
glEnd();
}
}
if( ( delta > ysize / 2 ) && ( delta > xsize / 2 ) )
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) )
SetGLColor( gridcolor, transparency );
else
SetGLColor( gridcolor_marker, transparency );
double delta = ii * aGriSizeMM * IU_PER_MM;
glBegin( GL_LINES );
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 )
{
glBegin( GL_LINES );
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( delta > xsize / 2 )
break;
}
// Draw horizontal grid lines on Z axis
for( int ii = 0; ; ii++ )
{
if( (ii % 5) )
SetGLColor( gridcolor, transparency);
else
SetGLColor( gridcolor_marker, transparency );
double delta = ii * aGriSizeMM * IU_PER_MM * scale;
if( delta <= zmax )
{
// 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 );
glEnd();
}
if( delta <= -zmin && ( ii != 0 ) )
{
// 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 );
glEnd();
}
if( ( delta > zmax ) && ( delta > -zmin ) )
break;
}
}
// Draw 3D pads.
void EDA_3D_CANVAS::Draw3DPadHole( const D_PAD* aPad )
{
// Draw the pad hole
wxSize drillsize = aPad->GetDrillSize();
bool hasHole = drillsize.x && drillsize.y;
if( !hasHole )
return;
// Store here the points to approximate hole by segments
CPOLYGONS_LIST holecornersBuffer;
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
int height = g_Parm_3D_Visu.GetLayerZcoordBIU( F_Cu ) -
g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu );
if( g_Parm_3D_Visu.IsRealisticMode() )
SetGLCopperColor();
else
SetGLColor( DARKGRAY );
int holeZpoz = g_Parm_3D_Visu.GetLayerZcoordBIU( B_Cu ) + thickness / 2;
int holeHeight = height - thickness;
if( drillsize.x == drillsize.y ) // usual round hole
{
Draw3D_ZaxisCylinder( aPad->GetPosition(),
(drillsize.x + thickness) / 2, holeHeight,
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
else // Oblong hole
{
wxPoint ends_offset;
int width;
if( drillsize.x > drillsize.y ) // Horizontal oval
{
ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
width = drillsize.y;
}
else // Vertical oval
{
ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
width = drillsize.x;
}
RotatePoint( &ends_offset, aPad->GetOrientation() );
wxPoint start = aPad->GetPosition() + ends_offset;
wxPoint end = aPad->GetPosition() - ends_offset;
int hole_radius = ( width + thickness ) / 2;
// Draw the hole
Draw3D_ZaxisOblongCylinder( start, end, hole_radius, holeHeight,
thickness, holeZpoz, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
}
void EDA_3D_CANVAS::Draw3DViaHole( const VIA* aVia )
{
LAYER_ID top_layer, bottom_layer;
int inner_radius = aVia->GetDrillValue() / 2;
int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU();
aVia->LayerPair( &top_layer, &bottom_layer );
// Drawing via hole:
if( g_Parm_3D_Visu.IsRealisticMode() )
SetGLCopperColor();
else
{
EDA_COLOR_T color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + aVia->GetViaType() );
SetGLColor( color );
}
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;
Draw3D_ZaxisCylinder( aVia->GetStart(), inner_radius + thickness / 2, height,
thickness, zpos, g_Parm_3D_Visu.m_BiuTo3Dunits );
}
/* Build a pad outline as non filled polygon, to draw pads on silkscreen layer
* Used only to draw pads outlines on silkscreen layers.
*/
void EDA_3D_CANVAS::BuildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
CPOLYGONS_LIST& aCornerBuffer,
int aWidth,
int aCircleToSegmentsCount,
double aCorrectionFactor )
{
if( aPad->GetShape() == PAD_CIRCLE ) // Draw a ring
{
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
aPad->GetSize().x / 2, aCircleToSegmentsCount, aWidth );
return;
}
// For other shapes, draw polygon outlines
CPOLYGONS_LIST corners;
aPad->BuildPadShapePolygon( corners, wxSize( 0, 0 ),
aCircleToSegmentsCount, aCorrectionFactor );
// Add outlines as thick segments in polygon buffer
for( unsigned ii = 0, jj = corners.GetCornersCount() - 1;
ii < corners.GetCornersCount(); jj = ii, ii++ )
{
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
corners.GetPos( jj ),
corners.GetPos( ii ),
aCircleToSegmentsCount, aWidth );
}
}

View File

@ -522,15 +522,15 @@ void EDA_3D_FRAME::Set3DBgColor()
newcolor = wxGetColourFromUser( this, oldcolor ); newcolor = wxGetColourFromUser( this, oldcolor );
if( !newcolor.IsOk() ) // Happens on cancel dialog if( !newcolor.IsOk() ) // Cancel command
return; return;
if( newcolor != oldcolor ) if( newcolor != oldcolor )
{ {
g_Parm_3D_Visu.m_BgColor.m_Red = (double) newcolor.Red() / 255.0; g_Parm_3D_Visu.m_BgColor.m_Red = (double) newcolor.Red() / 255.0;
g_Parm_3D_Visu.m_BgColor.m_Green = (double) newcolor.Green() / 255.0; g_Parm_3D_Visu.m_BgColor.m_Green = (double) newcolor.Green() / 255.0;
g_Parm_3D_Visu.m_BgColor.m_Blue = (double) newcolor.Blue() / 255.0; g_Parm_3D_Visu.m_BgColor.m_Blue = (double) newcolor.Blue() / 255.0;
NewDisplay(); m_canvas->Redraw();
} }
} }

View File

@ -17,6 +17,7 @@ set(3D-VIEWER_SRCS
3d_class.cpp 3d_class.cpp
3d_draw.cpp 3d_draw.cpp
3d_draw_basic_functions.cpp 3d_draw_basic_functions.cpp
3d_draw_helper_functions.cpp
3d_frame.cpp 3d_frame.cpp
3d_material.cpp 3d_material.cpp
3d_mesh_model.cpp 3d_mesh_model.cpp