diff --git a/3d-viewer/3d_aux.cpp b/3d-viewer/3d_aux.cpp index 26abe84a9f..c2407f2c8d 100644 --- a/3d-viewer/3d_aux.cpp +++ b/3d-viewer/3d_aux.cpp @@ -44,6 +44,9 @@ #include #include +// Exported function: +void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ); + void S3D_MASTER::Set_Object_Coords( std::vector< S3D_VERTEX >& aVertices ) { @@ -75,7 +78,7 @@ void S3D_MASTER::Set_Object_Coords( std::vector< S3D_VERTEX >& aVertices ) } -void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices ) +void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ) { unsigned ii; GLfloat ax, ay, az, bx, by, bz, nx, ny, nz, r; @@ -126,9 +129,9 @@ void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices ) /* draw polygon/triangle/quad */ for( ii = 0; ii < aVertices.size(); ii++ ) { - glVertex3f( aVertices[ii].x * DataScale3D, - aVertices[ii].y * DataScale3D, - aVertices[ii].z * DataScale3D ); + glVertex3f( aVertices[ii].x * aBiuTo3DUnits, + aVertices[ii].y * aBiuTo3DUnits, + aVertices[ii].z * aBiuTo3DUnits ); } glEnd(); @@ -172,35 +175,6 @@ GLuint EDA_3D_CANVAS::DisplayCubeforTest() return gllist; } - -INFO3D_VISU::INFO3D_VISU() -{ - int ii; - - m_Beginx = m_Beginy = 0.0; // position of mouse - m_Zoom = 1.0; - m_3D_Grid = 10.0; // Grid value in mm - trackball( m_Quat, 0.0, 0.0, 0.0, 0.0 ); - - for( ii = 0; ii < 4; ii++ ) - m_Rot[ii] = 0.0; - - m_CopperLayersCount = 2; - m_BoardSettings = NULL; - - // default all special item layers Visible - for( ii = 0; ii < FL_LAST; ii++) - m_DrawFlags[ii] = true; - - m_DrawFlags[FL_GRID] = false; -} - - -INFO3D_VISU::~INFO3D_VISU() -{ -} - - VERTEX_VALUE_CTRL::VERTEX_VALUE_CTRL( wxWindow* parent, const wxString& title, wxBoxSizer* BoxSizer ) { diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 4317241ec9..df9bbb1fd2 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -45,59 +45,13 @@ #include <3d_viewer.h> #include #include +#include <3d_draw_basic_functions.h> -// angle increment to draw a circle, approximated by segments -#define ANGLE_INC(x) (3600/(x)) - -// Thickness of copper -// TODO: use the actual copper thickness to draw copper items with thickness -#define COPPER_THICKNESS (int)(0.035 * IU_PER_MM) - +// Imported function: +extern void SetGLColor( int color ); +extern void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ); extern void CheckGLError(); -/* draw a thick segment using 3D primitives, in a XY plane - * wxPoint aStart, wxPoint aEnd = YX position of ends in board units - * aWidth = width of segment in board units - * aThickness = thickness of segment in board units - * aZpos = z position of segment in board units - */ -static void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd, - int aWidth, int aThickness, int aZpos, - double aBiuTo3DUnits ); - -static void Draw3D_SegmentWithHole( double startx, double starty, - double endx, double endy, - double width, double holex, - double holey, double holeradius, - double zpos ); - -/* draw an arc using 3D primitives, in a plane parallel to the XY plane - * aCenterPos = 3D position of the center - * aStartPointX, aStartPointY = start point coordinate of arc (3D units) - * aWidth = width of the circle (3D units) - * aArcAngle = arc angle in 1/10 degrees - * aWidth = thickness of arc - */ -static void Draw3D_ArcSegment( const S3D_VERTEX& aCenterPos, - double aStartPointX, double aStartPointY, - double aArcAngle, double aWidth ); - -/* draw a circle with hole using 3D primitives, in a XY plane - * aCenterPos = 3D position of the center - * aRadius = radius of the circle (3D units) - * aHoleRadius = radius of the hole (3D units) - * Used to draw vias and round pads with round hole - */ -static void Draw3D_FilledCircleWithHole( const S3D_VERTEX& aPos, double aRadius, double aHoleRadius ); - -/* draw a circle using 3D primitives, in a plane parallel to the XY plane - * aCenterPos = 3D position of the center - * aRadius = radius of the circle (3D units) - * aWidth = width of the circle (3D units) - * Does the same think as Draw3D_FilledCircleWithHole, just does not use the same parmeters - * Used to draw circular segments - */ -static void Draw3D_ThickCircle( const S3D_VERTEX& aCenterPos, double aRadius, double aWidth ); /* returns true if aLayer should be displayed, false otherwise */ @@ -110,38 +64,6 @@ static bool Is3DLayerEnabled( int aLayer ); */ static GLfloat Get3DLayer_Z_Orientation( int aLayer ); -/* draw a cylinder using 3D primitives. - * the cylinder axis is parallel to the Z axis - * aCenterPos = 3D position of the axis cylinder - * aRadius = radius of the cylinder (3D units) - * aHeight = height of the cylinder (3D units) - */ -static void Draw3D_ZaxisCylinder( const S3D_VERTEX& aPos, double aRadius, double aHeight ); - -/* draw an oblong cylinder (oblong hole) using 3D primitives. - * the cylinder axis are parallel to the Z axis - * aStartPos = 3D position of the first axis cylinder - * aEndx, aEndy = 3D position of the second axis cylinder - * aRadius = radius of the cylinder (3D units) - * aHeight = height of the cylinder (3D units) - */ -static void Draw3D_ZaxisOblongCylinder( const S3D_VERTEX& aStartPos, - double aEndx, double aEndy, - double aRadius, double aHeight ); - - -#ifndef CALLBACK -#define CALLBACK -#endif - -// CALLBACK functions for GLU_TESS -static void CALLBACK tessBeginCB( GLenum which ); -static void CALLBACK tessEndCB(); -static void CALLBACK tessErrorCB( GLenum errorCode ); -static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ); -static void CALLBACK tesswxPoint2Vertex( const GLvoid* data ); - - void EDA_3D_CANVAS::Redraw( bool finish ) { // SwapBuffer requires the window to be shown before calling @@ -203,104 +125,8 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() m_gllist = glGenLists( 1 ); - EDA_RECT bbbox = pcbframe->GetBoardBoundingBox(); - - g_Parm_3D_Visu.m_BoardSettings = &pcb->GetDesignSettings(); - - g_Parm_3D_Visu.m_BoardSize = bbbox.GetSize(); - g_Parm_3D_Visu.m_BoardPos = bbbox.Centre(); - - g_Parm_3D_Visu.m_BoardPos.y = -g_Parm_3D_Visu.m_BoardPos.y; - g_Parm_3D_Visu.m_CopperLayersCount = pcb->GetCopperLayerCount(); - - // Ensure the board has 2 sides for 3D views, because it is hard to find - // a *really* single side board in the true life... - if( g_Parm_3D_Visu.m_CopperLayersCount < 2 ) - g_Parm_3D_Visu.m_CopperLayersCount = 2; - - g_Parm_3D_Visu.m_BoardScale = 2.0 / std::max( g_Parm_3D_Visu.m_BoardSize.x, - g_Parm_3D_Visu.m_BoardSize.y ); - - g_Parm_3D_Visu.m_EpoxyThickness = pcb->GetDesignSettings().GetBoardThickness() - * g_Parm_3D_Visu.m_BoardScale; - // Arbitrary choose a thickness for non copper layers: - g_Parm_3D_Visu.m_NonCopperLayerThickness = g_Parm_3D_Visu.m_EpoxyThickness / 20; - - // Init Z position of each layer - // calculate z position for each copper layer - int layer; - int copper_layers_cnt = g_Parm_3D_Visu.m_CopperLayersCount; - for( layer = 0; layer < copper_layers_cnt; layer++ ) - { - g_Parm_3D_Visu.m_LayerZcoord[layer] = - g_Parm_3D_Visu.m_EpoxyThickness * layer / (copper_layers_cnt - 1); - } - double zpos_copper_back = g_Parm_3D_Visu.m_LayerZcoord[0]; - double zpos_copper_front = g_Parm_3D_Visu.m_EpoxyThickness; - - // Fill remaining unused copper layers and front layer zpos - // with g_Parm_3D_Visu.m_EpoxyThickness - for( ; layer <= LAST_COPPER_LAYER; layer++ ) - { - g_Parm_3D_Visu.m_LayerZcoord[layer] = g_Parm_3D_Visu.m_EpoxyThickness; - } - - // calculate z position for each non copper layer - for( int layer_id = FIRST_NO_COPPER_LAYER; layer_id < NB_LAYERS; layer_id++ ) - { - double zpos; - switch( layer_id ) - { - case ADHESIVE_N_BACK: - zpos = zpos_copper_back - - 4 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case ADHESIVE_N_FRONT: - zpos = zpos_copper_front + - 4 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SOLDERPASTE_N_BACK: - zpos = zpos_copper_back - - 3 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SOLDERPASTE_N_FRONT: - zpos = zpos_copper_front + - 3 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SOLDERMASK_N_BACK: - zpos = zpos_copper_back - - 1 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SOLDERMASK_N_FRONT: - zpos = zpos_copper_front + - 1 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SILKSCREEN_N_BACK: - zpos = zpos_copper_back - - 2 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - case SILKSCREEN_N_FRONT: - zpos = zpos_copper_front + - 2 * g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - default: - zpos = zpos_copper_front + - (layer_id - FIRST_NO_COPPER_LAYER + 5) * - g_Parm_3D_Visu.m_NonCopperLayerThickness; - break; - - } - - g_Parm_3D_Visu.m_LayerZcoord[layer_id] = zpos; - } + // Build 3D board parameters: + g_Parm_3D_Visu.InitSettings( pcb ); glNewList( m_gllist, GL_COMPILE_AND_EXECUTE ); @@ -323,12 +149,9 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() glEnd(); } - // Draw epoxy limits (do not use, works and test in progress) - // TODO - // 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_BoardScale, - -g_Parm_3D_Visu.m_BoardPos.y * g_Parm_3D_Visu.m_BoardScale, + 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 ); glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis @@ -358,6 +181,9 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() } } + + // Draw epoxy limits: TODO + // draw graphic items EDA_ITEM* PtStruct; @@ -408,13 +234,16 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() */ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) { - int layer = aZone->GetLayer(); + int layer = aZone->GetLayer(); int color = g_ColorsSettings.GetLayerColor( layer ); + int thickness = layer >= FIRST_NO_COPPER_LAYER ? + g_Parm_3D_Visu.GetNonCopperLayerThicknessBIU() : + g_Parm_3D_Visu.GetCopperThicknessBIU(); if( layer == LAST_COPPER_LAYER ) layer = g_Parm_3D_Visu.m_CopperLayersCount - 1; - int zpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BoardScale ); + int zpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BiuTo3Dunits ); SetGLColor( color ); glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); @@ -424,7 +253,9 @@ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) // solid polygons only are used to fill areas if( aZone->GetFilledPolysList().size() > 3 ) { - Draw3D_SolidPolygonsInZones( aZone ); + Draw3D_SolidHorizontalPolyPolygons( aZone->GetFilledPolysList(), + g_Parm_3D_Visu.GetLayerZcoordBIU( layer ), + thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); } } else @@ -433,8 +264,8 @@ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) for( unsigned iseg = 0; iseg < aZone->m_FillSegmList.size(); iseg++ ) Draw3D_SolidSegment( aZone->m_FillSegmList[iseg].m_Start, aZone->m_FillSegmList[iseg].m_End, - aZone->m_ZoneMinThickness, COPPER_THICKNESS, zpos, - g_Parm_3D_Visu.m_BoardScale ); + aZone->m_ZoneMinThickness, thickness, zpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); } // Draw copper area outlines @@ -460,8 +291,8 @@ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) wxPoint start( begincorner->x, begincorner->y ); wxPoint end( endcorner->x, endcorner->y ); Draw3D_SolidSegment( start, end, - aZone->m_ZoneMinThickness, COPPER_THICKNESS, zpos, - g_Parm_3D_Visu.m_BoardScale ); + aZone->m_ZoneMinThickness, thickness, zpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); } if( (endcorner->end_contour) || (ic == imax) ) @@ -473,8 +304,8 @@ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) wxPoint start( endcorner->x, endcorner->y ); wxPoint end( firstcorner->x, firstcorner->y ); Draw3D_SolidSegment( start, end, - aZone->m_ZoneMinThickness, COPPER_THICKNESS, zpos, - g_Parm_3D_Visu.m_BoardScale ); + aZone->m_ZoneMinThickness, thickness, zpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); } ic++; @@ -490,13 +321,14 @@ void EDA_3D_CANVAS::Draw3D_Zone( ZONE_CONTAINER* aZone ) } -// draw mm grid.. +// 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::DrawGrid( double aGriSizeMM ) { - double zpos = -g_Parm_3D_Visu.m_NonCopperLayerThickness/2; + double zpos = 0.0; int gridcolor = DARKGRAY; // Color of grid lines int gridcolor_marker = LIGHTGRAY; // Color of grid lines every 5 lines - double scale = g_Parm_3D_Visu.m_BoardScale; + double scale = g_Parm_3D_Visu.m_BiuTo3Dunits; glNormal3f( 0.0, 0.0, 1.0 ); @@ -625,96 +457,37 @@ void EDA_3D_CANVAS::Draw3D_Track( TRACK* aTrack ) { int layer = aTrack->GetLayer(); int color = g_ColorsSettings.GetLayerColor( layer ); + int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU(); if( layer == LAST_COPPER_LAYER ) layer = g_Parm_3D_Visu.m_CopperLayersCount - 1; - int zpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BoardScale ); + int zpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BiuTo3Dunits ); SetGLColor( color ); glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); Draw3D_SolidSegment( aTrack->m_Start, aTrack->m_End, - aTrack->m_Width, COPPER_THICKNESS, zpos, - g_Parm_3D_Visu.m_BoardScale ); + aTrack->m_Width, thickness, zpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); } - -void EDA_3D_CANVAS::Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone ) -{ - double zpos; - int layer = aZone->GetLayer(); - - int color = g_ColorsSettings.GetLayerColor( layer ); - - if( layer == LAST_COPPER_LAYER ) - layer = g_Parm_3D_Visu.m_CopperLayersCount - 1; - - zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; - g_Parm_3D_Visu.m_ActZpos = zpos; - - SetGLColor( color ); - glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - - GLUtesselator* tess = gluNewTess(); - gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*)() )tessBeginCB ); - gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*)() )tessEndCB ); - gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*)() )tessErrorCB ); - gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*)() )tessCPolyPt2Vertex ); - - GLdouble v_data[3]; - v_data[2] = zpos; - - //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); - - // Draw solid areas contained in this zone - int StartContour = 1; - - std::vector polysList = aZone->GetFilledPolysList(); - for( unsigned ii = 0; ii < polysList.size(); ii++ ) - { - if( StartContour == 1 ) - { - gluTessBeginPolygon( tess, NULL ); - gluTessBeginContour( tess ); - StartContour = 0; - } - - v_data[0] = polysList[ii].x * g_Parm_3D_Visu.m_BoardScale; - v_data[1] = -polysList[ii].y * g_Parm_3D_Visu.m_BoardScale; - gluTessVertex( tess, v_data, &polysList[ii] ); - - if( polysList[ii].end_contour == 1 ) - { - gluTessEndContour( tess ); - gluTessEndPolygon( tess ); - StartContour = 1; - } - } - - gluDeleteTess( tess ); -} - - void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via ) { - double x, y, r, hole; int layer, top_layer, bottom_layer; - double zpos, height; int color; + double biu_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits ; - r = via->m_Width * g_Parm_3D_Visu.m_BoardScale / 2; - hole = via->GetDrillValue(); - hole *= g_Parm_3D_Visu.m_BoardScale / 2; - x = via->m_Start.x * g_Parm_3D_Visu.m_BoardScale; - y = via->m_Start.y * g_Parm_3D_Visu.m_BoardScale; + int outer_radius = via->m_Width / 2; + int inner_radius = via->GetDrillValue() / 2; + int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU(); via->ReturnLayerPair( &top_layer, &bottom_layer ); - // Drawing filled circles: + // Drawing horizontal thick rings: for( layer = bottom_layer; layer < g_Parm_3D_Visu.m_CopperLayersCount; layer++ ) { - zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; + int zpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / biu_to_3Dunits ); if( layer < g_Parm_3D_Visu.m_CopperLayersCount - 1 ) { @@ -733,41 +506,43 @@ void EDA_3D_CANVAS::Draw3D_Via( SEGVIA* via ) SetGLColor( color ); - glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - - if( layer == LAYER_N_BACK ) - zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale; - else - zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale; - - S3D_VERTEX pos( x, -y, zpos); - Draw3D_FilledCircleWithHole( pos, r, hole ); + if( thickness == 0 ) + glNormal3f( 0.0, 0.0, layer == LAYER_N_BACK ? -1.0 : 1.0 ); + Draw3D_ZaxisCylinder( via->m_Start, (outer_radius + inner_radius)/2, + thickness, outer_radius - inner_radius, + zpos - (thickness/2), biu_to_3Dunits ); if( layer >= top_layer ) break; } - // Drawing hole: + // Drawing via hole: color = g_ColorsSettings.GetItemColor( VIAS_VISIBLE + via->m_Shape ); SetGLColor( color ); - height = g_Parm_3D_Visu.m_LayerZcoord[top_layer] - g_Parm_3D_Visu.m_LayerZcoord[bottom_layer]; - S3D_VERTEX position( x, -y, g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] ); - Draw3D_ZaxisCylinder( position, hole, height ); + int height = g_Parm_3D_Visu.GetLayerZcoordBIU(top_layer) - + g_Parm_3D_Visu.m_LayerZcoord[bottom_layer] - thickness; + int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU(bottom_layer) + thickness/2; + + Draw3D_ZaxisCylinder( via->m_Start, inner_radius + thickness/2, height, + thickness, zpos, biu_to_3Dunits ); } void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment ) { - int layer = segment->GetLayer(); + int layer = segment->GetLayer(); int color = g_ColorsSettings.GetLayerColor( layer ); + int thickness = layer >= FIRST_NO_COPPER_LAYER ? + g_Parm_3D_Visu.GetNonCopperLayerThicknessBIU() : + g_Parm_3D_Visu.GetCopperThicknessBIU(); SetGLColor( color ); - double w = segment->GetWidth() * g_Parm_3D_Visu.m_BoardScale; - double x = segment->GetStart().x * g_Parm_3D_Visu.m_BoardScale; - double y = segment->GetStart().y * g_Parm_3D_Visu.m_BoardScale; - double xf = segment->GetEnd().x * g_Parm_3D_Visu.m_BoardScale; - double yf = segment->GetEnd().y * g_Parm_3D_Visu.m_BoardScale; + double w = segment->GetWidth() * g_Parm_3D_Visu.m_BiuTo3Dunits; + double x = segment->GetStart().x * g_Parm_3D_Visu.m_BiuTo3Dunits; + double y = segment->GetStart().y * g_Parm_3D_Visu.m_BiuTo3Dunits; + double xf = segment->GetEnd().x * g_Parm_3D_Visu.m_BiuTo3Dunits; + double yf = segment->GetEnd().y * g_Parm_3D_Visu.m_BiuTo3Dunits; if( layer == EDGE_N ) { @@ -786,18 +561,22 @@ void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment ) break; case S_CIRCLE: - { - S3D_VERTEX pos( x, -y, zpos ); - Draw3D_ThickCircle( pos, hypot( x - xf, y - yf ), w ); - } + { + int radius = KiROUND( hypot( double(segment->GetStart().x - segment->GetEnd().x), + double(segment->GetStart().y - segment->GetEnd().y) ) + ); + Draw3D_ZaxisCylinder( segment->GetStart(), radius, + thickness, segment->GetWidth(), + g_Parm_3D_Visu.GetLayerZcoordBIU(layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); + } break; default: Draw3D_SolidSegment( segment->GetStart(), segment->GetEnd(), - segment->GetWidth(), COPPER_THICKNESS, - KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / - g_Parm_3D_Visu.m_BoardScale ), - g_Parm_3D_Visu.m_BoardScale ); + segment->GetWidth(), thickness, + g_Parm_3D_Visu.GetLayerZcoordBIU(layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); break; } } @@ -820,17 +599,21 @@ void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment ) case S_CIRCLE: { - S3D_VERTEX pos( x, -y, zpos ); - Draw3D_ThickCircle( pos, hypot( x - xf, y - yf ), w ); + int radius = KiROUND( hypot( double(segment->GetStart().x - segment->GetEnd().x), + double(segment->GetStart().y - segment->GetEnd().y) ) + ); + Draw3D_ZaxisCylinder( segment->GetStart(), radius, + thickness, segment->GetWidth(), + g_Parm_3D_Visu.GetLayerZcoordBIU(layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); } break; default: Draw3D_SolidSegment( segment->GetStart(), segment->GetEnd(), - segment->GetWidth(), COPPER_THICKNESS, - KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / - g_Parm_3D_Visu.m_BoardScale ), - g_Parm_3D_Visu.m_BoardScale ); + segment->GetWidth(), thickness, + g_Parm_3D_Visu.GetLayerZcoordBIU(layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); break; } } @@ -841,14 +624,14 @@ void EDA_3D_CANVAS::Draw3D_DrawSegment( DRAWSEGMENT* segment ) // These variables are used in Draw3dTextSegm. // But Draw3dTextSegm is a call back function, so we cannot send them as arguments, // so they are static. -int s_Text3DWidth, s_Text3DZPos; +int s_Text3DWidth, s_Text3DZPos, s_thickness; // This is a call back function, used by DrawGraphicText to draw the 3D text shape: static void Draw3dTextSegm( int x0, int y0, int xf, int yf ) { Draw3D_SolidSegment( wxPoint( x0, y0), wxPoint( xf, yf ), - s_Text3DWidth, COPPER_THICKNESS, s_Text3DZPos, - g_Parm_3D_Visu.m_BoardScale ); + s_Text3DWidth, s_thickness, s_Text3DZPos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); } @@ -858,10 +641,13 @@ void EDA_3D_CANVAS::Draw3D_DrawText( TEXTE_PCB* text ) int color = g_ColorsSettings.GetLayerColor( layer ); SetGLColor( color ); - s_Text3DZPos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BoardScale ); + s_Text3DZPos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BiuTo3Dunits ); s_Text3DWidth = text->GetThickness(); glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) ); wxSize size = text->m_Size; + s_thickness = layer >= FIRST_NO_COPPER_LAYER ? + g_Parm_3D_Visu.GetNonCopperLayerThicknessBIU() : + g_Parm_3D_Visu.GetCopperThicknessBIU(); if( text->m_Mirror ) NEGATE( size.x ); @@ -906,13 +692,8 @@ void MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) D_PAD* pad = m_Pads; // Draw pads - glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); - glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis - for( ; pad != NULL; pad = pad->Next() ) - { pad->Draw3D( glcanvas ); - } // Draw module shape: 3D shape if exists (or module outlines if not exists) S3D_MASTER* Struct3D = m_3D_Drawings; @@ -922,8 +703,8 @@ void MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) { glPushMatrix(); - glTranslatef( m_Pos.x * g_Parm_3D_Visu.m_BoardScale, - -m_Pos.y * g_Parm_3D_Visu.m_BoardScale, + glTranslatef( m_Pos.x * g_Parm_3D_Visu.m_BiuTo3Dunits, + -m_Pos.y * g_Parm_3D_Visu.m_BiuTo3Dunits, g_Parm_3D_Visu.m_LayerZcoord[m_Layer] ); if( m_Orient ) @@ -937,8 +718,6 @@ void MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) glRotatef( 180.0, 0.0, 0.0, 1.0 ); } - DataScale3D = g_Parm_3D_Visu.m_BoardScale * UNITS3D_TO_UNITSPCB; - for( ; Struct3D != NULL; Struct3D = Struct3D->Next() ) { if( !Struct3D->m_Shape3DName.IsEmpty() ) @@ -952,8 +731,6 @@ void MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) } EDA_ITEM* Struct = m_Drawings; - glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis - for( ; Struct != NULL; Struct = Struct->Next() ) { switch( Struct->Type() ) @@ -994,11 +771,11 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) dx = m_End.x; dy = m_End.y; - w = m_Width * g_Parm_3D_Visu.m_BoardScale; - x = m_Start.x * g_Parm_3D_Visu.m_BoardScale; - y = m_Start.y * g_Parm_3D_Visu.m_BoardScale; - fx = dx * g_Parm_3D_Visu.m_BoardScale; - fy = dy * g_Parm_3D_Visu.m_BoardScale; + w = m_Width * g_Parm_3D_Visu.m_BiuTo3Dunits; + x = m_Start.x * g_Parm_3D_Visu.m_BiuTo3Dunits; + y = m_Start.y * g_Parm_3D_Visu.m_BiuTo3Dunits; + fx = dx * g_Parm_3D_Visu.m_BiuTo3Dunits; + fy = dy * g_Parm_3D_Visu.m_BiuTo3Dunits; if( m_Layer == EDGE_N ) @@ -1006,20 +783,28 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) for( int layer = 0; layer < g_Parm_3D_Visu.m_CopperLayersCount; layer++ ) { glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - int izpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[layer] / g_Parm_3D_Visu.m_BoardScale ); + int izpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer ); + int thickness = m_Layer >= FIRST_NO_COPPER_LAYER ? + g_Parm_3D_Visu.GetNonCopperLayerThicknessBIU() : + g_Parm_3D_Visu.GetCopperThicknessBIU(); switch( m_Shape ) { case S_SEGMENT: Draw3D_SolidSegment( m_Start, m_End, m_Width, - COPPER_THICKNESS, izpos, - g_Parm_3D_Visu.m_BoardScale ); + thickness, izpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); break; case S_CIRCLE: { - S3D_VERTEX pos( x, -y, g_Parm_3D_Visu.m_LayerZcoord[layer] ); - Draw3D_ThickCircle( pos, hypot( x - fx, y - fy ), w); + int radius = KiROUND( hypot( double(m_Start.x - m_End.x), + double(m_Start.y - m_End.y) ) + ); + Draw3D_ZaxisCylinder( m_Start, radius, + thickness, GetWidth(), + g_Parm_3D_Visu.GetLayerZcoordBIU(layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); } break; @@ -1048,7 +833,7 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) pt += module->m_Pos; } - glcanvas->Draw3D_Polygon( points, g_Parm_3D_Visu.m_LayerZcoord[layer] ); + Draw3D_HorizontalPolygon( points, izpos, 0, g_Parm_3D_Visu.m_BiuTo3Dunits); } break; @@ -1061,21 +846,29 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) } else { + int thickness = m_Layer >= FIRST_NO_COPPER_LAYER ? + g_Parm_3D_Visu.GetNonCopperLayerThicknessBIU() : + g_Parm_3D_Visu.GetCopperThicknessBIU(); glNormal3f( 0.0, 0.0, (m_Layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - int izpos = KiROUND( g_Parm_3D_Visu.m_LayerZcoord[m_Layer] / g_Parm_3D_Visu.m_BoardScale ); + int izpos = g_Parm_3D_Visu.GetLayerZcoordBIU(m_Layer); switch( m_Shape ) { case S_SEGMENT: Draw3D_SolidSegment( m_Start, m_End, m_Width, - COPPER_THICKNESS, izpos, - g_Parm_3D_Visu.m_BoardScale ); + thickness, izpos, + g_Parm_3D_Visu.m_BiuTo3Dunits ); break; case S_CIRCLE: { - S3D_VERTEX pos( x, -y, g_Parm_3D_Visu.m_LayerZcoord[m_Layer] ); - Draw3D_ThickCircle( pos, hypot( x - fx, y - fy ), w ); + int radius = KiROUND( hypot( double(m_Start.x - m_End.x), + double(m_Start.y - m_End.y) ) + ); + Draw3D_ZaxisCylinder( m_Start, radius, + thickness, GetWidth(), + g_Parm_3D_Visu.GetLayerZcoordBIU(m_Layer), + g_Parm_3D_Visu.m_BiuTo3Dunits ); } break; @@ -1104,7 +897,7 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) pt += module->m_Pos; } - glcanvas->Draw3D_Polygon( points, g_Parm_3D_Visu.m_LayerZcoord[m_Layer] ); + Draw3D_HorizontalPolygon( points, izpos, 0, g_Parm_3D_Visu.m_BiuTo3Dunits ); } break; @@ -1120,90 +913,82 @@ void EDGE_MODULE::Draw3D( EDA_3D_CANVAS* glcanvas ) // Draw 3D pads. void D_PAD::Draw3D( EDA_3D_CANVAS* glcanvas ) { - int ii, ll, layer, nlmax; - int ux0, uy0, - dx, dx0, dy, dy0, - delta_cx, delta_cy, - xc, yc; - int angle; - double zpos; - double x, y, r, w; + int layer, nlmax; bool Oncu, Oncmp, Both; int color; - double scale = g_Parm_3D_Visu.m_BoardScale; - double holeX = (double) m_Drill.x * scale / 2; - double holeY = (double) m_Drill.y * scale / 2; - double hole = fmin( holeX, holeY ); + double scale = g_Parm_3D_Visu.m_BiuTo3Dunits; - // Calculate the center of the pad. + // Calculate the center of the pad shape. wxPoint shape_pos = ReturnShapePos(); - ux0 = shape_pos.x; - uy0 = shape_pos.y; - xc = ux0; - yc = uy0; - dx = dx0 = m_Size.x >> 1; - dy = dy0 = m_Size.y >> 1; + int height = g_Parm_3D_Visu.GetLayerZcoordBIU(LAYER_N_FRONT) - + g_Parm_3D_Visu.GetLayerZcoordBIU(LAYER_N_BACK); + int thickness = g_Parm_3D_Visu.GetCopperThicknessBIU(); - angle = m_Orient; - double drillx = m_Pos.x * scale; - double drilly = m_Pos.y * scale; - double height = g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_FRONT] - - g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_BACK]; + // Store here the points to approximate hole by segments + std::vector holecornersBuffer; + const int slice = 12; // number of segments to approximate a circle // Draw the pad hole - if( holeX && holeY ) + bool hasHole = m_Drill.x && m_Drill.y; + + if( hasHole ) { SetGLColor( DARKGRAY ); - S3D_VERTEX position( drillx, -drilly, g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_BACK] ); + int holeZpoz = g_Parm_3D_Visu.GetLayerZcoordBIU(LAYER_N_BACK) + thickness/2; + int holeHeight = height - thickness; - if( holeX == holeY ) // usual round hole - Draw3D_ZaxisCylinder( position, hole, height ); - else // Oval hole + if( m_Drill.x == m_Drill.y ) // usual round hole { - double ldx, ldy; + Draw3D_ZaxisCylinder( m_Pos, (m_Drill.x + thickness) / 2, holeHeight, + thickness, holeZpoz, scale ); + TransformCircleToPolygon( holecornersBuffer, m_Pos, m_Drill.x/2, slice ); + } + else // Oblong hole + { + wxPoint ends_offset; + int width; - if( holeX > holeY ) // Horizontal oval - { - ldx = holeX - holeY; - ldy = 0; - w = m_Size.y * scale; - } - else // Vertical oval - { - ldx = 0; - ldy = holeY - holeX; - w = m_Size.x * scale; - } + if( m_Drill.x > m_Drill.y ) // Horizontal oval + { + ends_offset.x = ( m_Drill.x - m_Drill.y ) / 2; + width = m_Drill.y; + } + else // Vertical oval + { + ends_offset.y = ( m_Drill.y - m_Drill.x ) / 2; + width = m_Drill.x; + } - RotatePoint( &ldx, &ldy, angle ); + RotatePoint( &ends_offset, m_Orient ); - { - double ox = ux0 * scale + ldx; - double oy = uy0 * scale + ldy; - double fx = ux0 * scale - ldx; - double fy = uy0 * scale - ldy; + wxPoint start = m_Pos + ends_offset; + wxPoint end = m_Pos - ends_offset; + int hole_radius = ( width + thickness ) / 2; - S3D_VERTEX position( ox, -oy, g_Parm_3D_Visu.m_LayerZcoord[LAYER_N_BACK] ); - Draw3D_ZaxisOblongCylinder( position, fx, -fy, hole, height ); - } + // Prepare the shape creation + TransformRoundedEndsSegmentToPolygon( holecornersBuffer, start, end, slice, width ); + + // Draw the hole + Draw3D_ZaxisOblongCylinder( start, end, hole_radius, holeHeight, + thickness, holeZpoz, scale ); } } glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis + nlmax = g_Parm_3D_Visu.m_CopperLayersCount - 1; Oncu = (m_layerMask & LAYER_BACK) ? true : false; Oncmp = (m_layerMask & LAYER_FRONT) ? true : false; Both = Oncu && Oncmp; - switch( m_PadShape & 0x7F ) + // Store here the points to approximate pad shape by segments + std::vector polyPadShape; + + switch( GetShape() ) { case PAD_CIRCLE: - x = xc * scale; - y = yc * scale; - r = (double) dx * scale; - for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ ) { if( layer && (layer == nlmax) ) @@ -1224,541 +1009,106 @@ void D_PAD::Draw3D( EDA_3D_CANVAS* glcanvas ) continue; SetGLColor( color ); - glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; + int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer ); + int ring_radius = (m_Size.x + m_Drill.x) / 4; + if( thickness == 0 ) + glNormal3f( 0.0, 0.0, layer == LAYER_N_BACK ? -1.0 : 1.0 ); - if( layer == LAYER_N_BACK ) - zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale; - else - zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale; - - S3D_VERTEX position( x, -y, zpos ); - Draw3D_FilledCircleWithHole( position, r, hole ); - } + Draw3D_ZaxisCylinder(shape_pos, ring_radius, + thickness, ( m_Size.x - m_Drill.x) / 2, + zpos - (thickness/2), scale ); + } break; case PAD_OVAL: - if( dx > dy ) // Horizontal ellipse { - delta_cx = dx - dy; - delta_cy = 0; - w = m_Size.y * scale; + wxPoint ends_offset; + int width; + if( m_Size.x > m_Size.y ) // Horizontal ellipse + { + ends_offset.x = ( m_Size.x - m_Size.y ) / 2; + width = m_Size.y; } else // Vertical ellipse { - delta_cx = 0; - delta_cy = dy - dx; - w = m_Size.x * scale; + ends_offset.y = ( m_Size.y - m_Size.x ) / 2; + width = m_Size.x; } - RotatePoint( &delta_cx, &delta_cy, angle ); - - { - double ox, oy, fx, fy; - ox = (double) ( ux0 + delta_cx ) * scale; - oy = (double) ( uy0 + delta_cy ) * scale; - fx = (double) ( ux0 - delta_cx ) * scale; - fy = (double) ( uy0 - delta_cy ) * scale; - - for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ ) - { - if( layer && (layer == nlmax) ) - layer = LAYER_N_FRONT; - - if( (layer == LAYER_N_FRONT) && !Oncmp ) - continue; - - if( (layer == LAYER_N_BACK) && !Oncu ) - continue; - - if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both ) - continue; - - color = g_ColorsSettings.GetLayerColor( layer ); - glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - - if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) - continue; - - SetGLColor( color ); - zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; - - if( layer == LAYER_N_BACK ) - zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale; - else - zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale; - - Draw3D_SegmentWithHole( ox, -oy, fx, -fy, w, drillx, -drilly, hole, zpos ); - } + RotatePoint( &ends_offset, m_Orient ); + wxPoint start = shape_pos + ends_offset; + wxPoint end = shape_pos - ends_offset; + TransformRoundedEndsSegmentToPolygon( polyPadShape, start, end, slice, width ); + if( hasHole ) + polyPadShape.insert( polyPadShape.end(), holecornersBuffer.begin(), holecornersBuffer.end() ); } - break; case PAD_RECT: case PAD_TRAPEZOID: - { - wxPoint coord[5]; - wxRealPoint fcoord[8], f_hole_coord[8]; - BuildPadPolygon( coord, wxSize(0,0), angle ); - - for( ii = 0; ii < 4; ii++ ) { - coord[ii].x += ux0; - coord[ii].y += uy0; - ll = ii * 2; - fcoord[ll].x = coord[ii].x *scale; - fcoord[ll].y = coord[ii].y *scale; - } - - for( ii = 0; ii < 7; ii += 2 ) + wxPoint coord[5]; + BuildPadPolygon( coord, wxSize(0,0), m_Orient ); + for( int ii = 0; ii < 4; ii ++ ) { - ll = ii + 2; - - if( ll > 7 ) - ll -= 8; - - fcoord[ii + 1].x = (fcoord[ii].x + fcoord[ll].x) / 2; - fcoord[ii + 1].y = (fcoord[ii].y + fcoord[ll].y) / 2; + CPolyPt pt( coord[ii].x + shape_pos.x, coord[ii].y+ shape_pos.y ); + polyPadShape.push_back( pt ); } + polyPadShape.back().end_contour = true; - for( ii = 0; ii < 8; ii++ ) - { - f_hole_coord[ii].x = -hole * 0.707; - f_hole_coord[ii].y = hole * 0.707; - RotatePoint( &f_hole_coord[ii].x, &f_hole_coord[ii].y, angle - (ii * 450) ); - f_hole_coord[ii].x += drillx; - f_hole_coord[ii].y += drilly; + if( hasHole ) + polyPadShape.insert( polyPadShape.end(), holecornersBuffer.begin(), holecornersBuffer.end() ); } - - for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ ) - { - if( layer && (layer == nlmax) ) - layer = LAYER_N_FRONT; - - if( (layer == LAYER_N_FRONT) && !Oncmp ) - continue; - - if( (layer == LAYER_N_BACK) && !Oncu ) - continue; - - if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both ) - continue; - - color = g_ColorsSettings.GetLayerColor( layer ); - glNormal3f( 0.0, 0.0, (layer == LAYER_N_BACK) ? -1.0 : 1.0 ); - - if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) - continue; - - SetGLColor( color ); - zpos = g_Parm_3D_Visu.m_LayerZcoord[layer]; - - if( layer == LAYER_N_BACK ) - zpos = zpos - 5 * g_Parm_3D_Visu.m_BoardScale; - else - zpos = zpos + 5 * g_Parm_3D_Visu.m_BoardScale; - - glBegin( GL_QUAD_STRIP ); - - for( ii = 0; ii < 8; ii++ ) - { - glVertex3f( f_hole_coord[ii].x, -f_hole_coord[ii].y, zpos ); - glVertex3f( fcoord[ii].x, -fcoord[ii].y, zpos ); - } - - glVertex3f( f_hole_coord[0].x, -f_hole_coord[0].y, zpos ); - glVertex3f( fcoord[0].x, -fcoord[0].y, zpos ); - glEnd(); - } - } break; default: break; } -} - -void SetGLColor( int color ) -{ - double red, green, blue; - StructColors colordata = ColorRefs[color & MASKCOLOR]; - - red = colordata.m_Red / 255.0; - blue = colordata.m_Blue / 255.0; - green = colordata.m_Green / 255.0; - glColor3f( red, green, blue ); -} - - -void Draw3D_FilledCircleWithHole( const S3D_VERTEX& aPos, double radius, double hole_radius ) -{ - const int slice = 16; - const int rot_angle = ANGLE_INC(slice); - - glBegin( GL_QUAD_STRIP ); - - for( int ii = 0; ii <= slice; ii++ ) + if( polyPadShape.size() ) { - double x = hole_radius; - double y = 0.0; - RotatePoint( &x, &y, ii * rot_angle ); - glVertex3f( x + aPos.x, y + aPos.y, aPos.z ); - x = radius; - y = 0.0; - RotatePoint( &x, &y, ii * rot_angle ); - glVertex3f( x + aPos.x, y + aPos.y, aPos.z ); - } - - glEnd(); -} - -static void Draw3D_ZaxisCylinder( const S3D_VERTEX& aPos, double aRadius, double aHeight ) -{ - const int slice = 12; - - std::vector< S3D_VERTEX > coords; - coords.resize( 4 ); - - double tmp = DataScale3D; - DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data(); - - coords[0].x = coords[1].x = aPos.x + aRadius; - coords[0].y = coords[1].y = aPos.y; - coords[0].z = coords[3].z = aPos.z; - coords[1].z = coords[2].z = aPos.z + aHeight; - - for( int ii = 0; ii <= slice; ii++ ) - { - double x = aRadius; - double y = 0.0; - RotatePoint( &x, &y, ii * ANGLE_INC(slice) ); - coords[2].x = coords[3].x = aPos.x + x; - coords[2].y = coords[3].y = aPos.y + y; - Set_Object_Data( coords ); - coords[0].x = coords[2].x; - coords[0].y = coords[2].y; - coords[1].x = coords[3].x; - coords[1].y = coords[3].y; - } - - glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis - DataScale3D = tmp; -} - - -/* draw a thick segment using 3D primitives, in a XY plane - * wxPoint aStart, wxPoint aEnd = YX position of end in board units - * aWidth = width of segment in board units - * aThickness = thickness of segment in board units - * aZpos = z position of segment in board units - */ -void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd, - int aWidth, int aThickness, int aZpos, double aBiuTo3DUnits ) -{ - std::vector cornerBuffer; - const int slice = 16; - TransformRoundedEndsSegmentToPolygon(cornerBuffer, aStart, aEnd, slice, aWidth ); - - //Build the 3D data : upper side then lower side - double zupperpos = ( aZpos + (aThickness/2) ) * aBiuTo3DUnits; - double zlowerpos = ( aZpos - (aThickness/2) ) * aBiuTo3DUnits; - if( aThickness ) - glNormal3f( 0.0, 0.0, 1.0 ); // Normale is Z axis - - double zpos = zupperpos; // start with upper side - for( int face = 0; face < 2; face ++ ) - { - glBegin( GL_POLYGON ); - for( unsigned ii = 0; ii < cornerBuffer.size(); ii++ ) - glVertex3f( cornerBuffer[ii].x * aBiuTo3DUnits, - - cornerBuffer[ii].y * aBiuTo3DUnits, zpos ); - - // Close the polygon shape - glVertex3f( cornerBuffer[0].x * aBiuTo3DUnits, - - cornerBuffer[0].y * aBiuTo3DUnits, zpos ); - glEnd(); - - if( aThickness == 0 ) - return; - - // Prepare the creation of lower side - glNormal3f( 0.0, 0.0, -1.0 ); // Normale now is -Z axis - zpos = zlowerpos; - } - - //Build the 3D data : vertical sides - std::vector< S3D_VERTEX > vertices; - vertices.resize(4); - for( int ii = 0; ii < slice; ii++ ) - { - int jj = ii+1; - if( jj >=slice ) - jj = 0; - vertices[0].x = cornerBuffer[ii].x; - vertices[0].y = -cornerBuffer[ii].y; - vertices[0].z = aZpos + (aThickness/2); - vertices[1].x = cornerBuffer[ii].x; - vertices[1].y = -cornerBuffer[ii].y; - vertices[1].z = aZpos - (aThickness/2); - vertices[2].x = cornerBuffer[jj].x; - vertices[2].y = -cornerBuffer[jj].y; - vertices[2].z = aZpos - (aThickness/2); - vertices[3].x = cornerBuffer[jj].x; - vertices[3].y = -cornerBuffer[jj].y; - vertices[3].z = aZpos + (aThickness/2); - - Set_Object_Data( vertices ); - } - - glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis -} - -/* Draw a polygon similar to a segment ends with round hole - */ -static void Draw3D_SegmentWithHole( double startx, double starty, - double endx, double endy, - double width, double holex, - double holey, double holeradius, - double zpos ) -{ - double x, y, xin, yin; - double firstx = 0, firsty = 0, firstxin = 0, firstyin = 0; - int ii, angle, theta; - - // Calculate the coordinates of the segment assumed horizontal - // Then turn the strips of the desired angle - // All calculations are done with startx, starty as local origin - endx -= startx; - endy -= starty; - holex -= startx; - holey -= starty; - angle = (int) ( ( atan2( endy, endx ) * 1800 / M_PI ) + 0.5 ); - - RotatePoint( &endx, &endy, angle ); - RotatePoint( &holex, &holey, angle ); - width /= 2; - - glBegin( GL_QUAD_STRIP ); - - // Path of the flare to right (1st half polygon at the end of the segment) - // around the half-hole drilling - for( ii = 0; ii <= 8; ii++ ) - { - x = 0.0; - y = -width; - xin = 0.0; - yin = -holeradius; - theta = -ii * 225; - RotatePoint( &x, &y, theta ); - RotatePoint( &xin, &yin, theta ); - x += endx; - RotatePoint( &x, &y, -angle ); - xin += holex; - RotatePoint( &xin, &yin, -angle ); - glVertex3f( startx + xin, starty + yin, zpos ); - glVertex3f( startx + x, starty + y, zpos ); - - if( ii == 0 ) + for( layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; layer++ ) { - firstx = startx + x; - firsty = starty + y; - firstxin = startx + xin; - firstyin = starty + yin; + if( layer && (layer == nlmax) ) + layer = LAYER_N_FRONT; + + if( (layer == LAYER_N_FRONT) && !Oncmp ) + continue; + + if( (layer == LAYER_N_BACK) && !Oncu ) + continue; + + if( (layer > FIRST_COPPER_LAYER) && (layer < LAST_COPPER_LAYER) && !Both ) + continue; + + if( g_Parm_3D_Visu.m_BoardSettings->IsLayerVisible( layer ) == false ) + continue; + + color = g_ColorsSettings.GetLayerColor( layer ); + SetGLColor( color ); + + if( thickness == 0 ) + glNormal3f( 0.0, 0.0, layer == LAYER_N_BACK ? -1.0 : 1.0 ); + + // If not hole: draw a single polygon + int zpos = g_Parm_3D_Visu.GetLayerZcoordBIU( layer ); + if( hasHole ) + { + Draw3D_SolidHorizontalPolygonWithHoles( polyPadShape, zpos, + thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); + } + + else + { + Draw3D_SolidHorizontalPolyPolygons( polyPadShape, zpos, + thickness, g_Parm_3D_Visu.m_BiuTo3Dunits ); + } } } - // Layout of the rounded left (2nd half polygon is the origin of the - // segment) - for( ii = 0; ii <= 8; ii++ ) - { - theta = -ii * 225; - x = 0.0; - y = width; - RotatePoint( &x, &y, -angle + theta ); - xin = 0.0; - yin = holeradius; - RotatePoint( &xin, &yin, theta ); - xin += holex; - RotatePoint( &xin, &yin, -angle ); - glVertex3f( startx + xin, starty + yin, zpos ); - glVertex3f( startx + x, starty + y, zpos ); - } - - glVertex3f( firstxin, firstyin, zpos ); - glVertex3f( firstx, firsty, zpos ); - glEnd(); } - -static void Draw3D_ArcSegment( const S3D_VERTEX& aCenterPos, - double aStartPointX, double aStartPointY, - double aArcAngle, double aWidth ) -{ - const int slice = 16; // Number of segments to approximate a circle by segments - double arcStart_Angle; - - arcStart_Angle = (atan2( aStartPointX - aCenterPos.x, aStartPointY - aCenterPos.y ) * 1800 / M_PI ); - double radius = hypot( aStartPointX - aCenterPos.x, aStartPointY - aCenterPos.y ) - + ( aWidth / 2); - double hole = radius - aWidth; - - // Calculate the number of segments to approximate this arc - int imax = (int) ( (double) aArcAngle / ANGLE_INC(slice) ); - - if( imax < 0 ) - imax = -imax; - - if( imax == 0 ) - imax = 1; - - // Adjust delta_angle to have exactly imax segments in arc_angle - // i.e. arc_angle = imax delta_agnle. - double delta_angle = (double) aArcAngle / imax; - - glBegin( GL_QUAD_STRIP ); - - for( int ii = 0; ii <= imax; ii++ ) - { - double angle = (double) ii * delta_angle; - angle += arcStart_Angle + 900; - double dx = hole; - double dy = 0.0; - RotatePoint( &dx, &dy, (int) angle ); - glVertex3f( dx + aStartPointX, dy + aStartPointY, aCenterPos.z ); - dx = radius; - dy = 0.0; - RotatePoint( &dx, &dy, (int) angle ); - glVertex3f( dx + aStartPointX, dy + aStartPointY, aCenterPos.z ); - } - - glEnd(); -} - - -static void Draw3D_ThickCircle( const S3D_VERTEX& aCenterPos, double aRadius, double aWidth ) -{ - double outer_radius = aRadius + ( aWidth / 2); - double inner_radius = outer_radius - aWidth; - - Draw3D_FilledCircleWithHole( aCenterPos, outer_radius, inner_radius ); -} - -/* - * Function Draw3D_ZaxisOblongCylinder: - * draw a segment with an oblong hole. - * Used to draw oblong holes - */ -void Draw3D_ZaxisOblongCylinder( const S3D_VERTEX& aStartPos, - double aEndx, double aEndy, - double aRadius, double aHeight ) -{ - const int slice = 16; - std::vector coords; - - coords.resize( 4 ); - - double tmp = DataScale3D; - - DataScale3D = 1.0; // Coordinate is already in range for Set_Object_Data(); - - double dx = aEndx - aStartPos.x; - double dy = aEndy - aStartPos.y; - double angle = atan2( dy, dx ) * 1800 / M_PI; - dx = 0; - dy = aRadius; - - // draws the first rectangle between half cylinders - RotatePoint( &dx, &dy, angle ); - coords[0].x = coords[1].x = aStartPos.x + dx; - coords[0].y = coords[1].y = aStartPos.y - dy; - coords[2].x = coords[3].x = aEndx + dx; - coords[2].y = coords[3].y = aEndy - dy; - coords[0].z = coords[3].z = aStartPos.z; - coords[1].z = coords[2].z = aStartPos.z + aHeight; - Set_Object_Data( coords ); - - // Draw the first half cylinder - for( int ii = 1; ii <= slice/2; ii++ ) - { - double ddx = dx; - double ddy = -dy; - RotatePoint( &ddx, &ddy, -ii * ANGLE_INC(slice) ); - coords[0].x = coords[2].x; - coords[0].y = coords[2].y; - coords[1].x = coords[3].x; - coords[1].y = coords[3].y; - coords[2].x = coords[3].x = aEndx + ddx; - coords[2].y = coords[3].y = aEndy + ddy; - Set_Object_Data( coords ); - } - - // draws the second rectangle between half cylinders - coords[0].x = coords[1].x = aEndx - dx; - coords[0].y = coords[1].y = aEndy + dy; - coords[2].x = coords[3].x = aStartPos.x - dx; - coords[2].y = coords[3].y = aStartPos.y + dy; - coords[0].z = coords[3].z = aStartPos.z; - coords[1].z = coords[2].z = aStartPos.z + aHeight; - Set_Object_Data( coords ); - - // Draw the second half cylinder - for( int ii = 1; ii <= slice/2; ii++ ) - { - double ddx = -dx; - double ddy = dy; - RotatePoint( &ddx, &ddy, -ii * ANGLE_INC(slice) ); - coords[0].x = coords[2].x; - coords[0].y = coords[2].y; - coords[1].x = coords[3].x; - coords[1].y = coords[3].y; - coords[2].x = coords[3].x = aStartPos.x + ddx; - coords[2].y = coords[3].y = aStartPos.y + ddy; - Set_Object_Data( coords ); - } - - glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis - DataScale3D = tmp; -} - - -void EDA_3D_CANVAS::Draw3D_Polygon( std::vector& aCornersList, double aZpos ) -{ - g_Parm_3D_Visu.m_ActZpos = aZpos; - - GLUtesselator* tess = gluNewTess(); - gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*)() )tessBeginCB ); - gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*)() )tessEndCB ); - gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*)() )tessErrorCB ); - gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*)() )tesswxPoint2Vertex ); - - GLdouble v_data[3]; - v_data[2] = aZpos; - - //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); - - // Draw solid polygon - gluTessBeginPolygon( tess, NULL ); - gluTessBeginContour( tess ); - - for( unsigned ii = 0; ii < aCornersList.size(); ii++ ) - { - v_data[0] = aCornersList[ii].x * g_Parm_3D_Visu.m_BoardScale; - v_data[1] = -aCornersList[ii].y * g_Parm_3D_Visu.m_BoardScale; - // gluTessVertex store pointers on data, not data, so do not store - // different corners values in a temporary variable - // but send pointer on each corner value in aCornersList - gluTessVertex( tess, v_data, &aCornersList[ii] ); - } - - gluTessEndContour( tess ); - gluTessEndPolygon( tess ); - - gluDeleteTess( tess ); -} - - bool Is3DLayerEnabled( int aLayer ) { int flg = -1; @@ -1806,52 +1156,3 @@ GLfloat Get3DLayer_Z_Orientation( int aLayer ) return nZ; } - - -/////////////////////////////////////////////////////////////////////////////// -// GLU_TESS CALLBACKS -/////////////////////////////////////////////////////////////////////////////// - -void CALLBACK tessBeginCB( GLenum which ) -{ - glBegin( which ); -} - - -void CALLBACK tessEndCB() -{ - glEnd(); -} - - -void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ) -{ - // cast back to double type - const CPolyPt* ptr = (const CPolyPt*) data; - - glVertex3f( ptr->x * g_Parm_3D_Visu.m_BoardScale, - -ptr->y * g_Parm_3D_Visu.m_BoardScale, - g_Parm_3D_Visu.m_ActZpos ); -} - -void CALLBACK tesswxPoint2Vertex( const GLvoid* data ) -{ - const wxPoint* ptr = (const wxPoint*) data; - - glVertex3f( ptr->x * g_Parm_3D_Visu.m_BoardScale, - -ptr->y * g_Parm_3D_Visu.m_BoardScale, - g_Parm_3D_Visu.m_ActZpos ); -} - - -void CALLBACK tessErrorCB( GLenum errorCode ) -{ -#if defined(DEBUG) - const GLubyte* errorStr; - - errorStr = gluErrorString( errorCode ); - - // DEBUG // - D( printf( "Tess ERROR: %s\n", errorStr ); ) -#endif -} diff --git a/3d-viewer/3d_draw_basic_functions.cpp b/3d-viewer/3d_draw_basic_functions.cpp new file mode 100644 index 0000000000..0680745a63 --- /dev/null +++ b/3d-viewer/3d_draw_basic_functions.cpp @@ -0,0 +1,591 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 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_basic_functions.cpp + */ + +#include +#include +#include + +#include <3d_viewer.h> +#include +#include <3d_draw_basic_functions.h> + + +// Imported function: +extern void Set_Object_Data( std::vector& aVertices, double aBiuTo3DUnits ); +extern void CheckGLError(); + + +#ifndef CALLBACK +#define CALLBACK +#endif + +// CALLBACK functions for GLU_TESS +static void CALLBACK tessBeginCB( GLenum which ); +static void CALLBACK tessEndCB(); +static void CALLBACK tessErrorCB( GLenum errorCode ); +static void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ); +static void CALLBACK tesswxPoint2Vertex( const GLvoid* data ); + +/** draw a ring using 3D primitives, in a plane parallel to the XY plane + * @param aCenterPos = position of the center (Board internal units) + * @param aOuterRadius = radius of the external circle (Board internal units) + * @param aInnerRadius = radius of the circle (Board internal units) + * @param aZpos = z position in board internal units + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + */ +static void Draw3D_FlatRing( wxPoint aCenterPos, int aOuterRadius, + int aInnerRadius, int aZpos, double aBiuTo3DUnits ); + + +void SetGLColor( int color ) +{ + double red, green, blue; + StructColors colordata = ColorRefs[color & MASKCOLOR]; + + red = colordata.m_Red / 255.0; + blue = colordata.m_Blue / 255.0; + green = colordata.m_Green / 255.0; + glColor3f( red, green, blue ); +} + + +/* draw all solid polygons found in aPolysList + * aZpos = z position in board internal units + * aThickness = thickness in board internal units + * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. + * If aThickness 1 0, a solid object is drawn. + * The top side is located at aZpos + aThickness / 2 + * The bottom side is located at aZpos - aThickness / 2 + */ +void Draw3D_SolidHorizontalPolyPolygons( const std::vector& aPolysList, + int aZpos, int aThickness, double aBiuTo3DUnits ) +{ + GLUtesselator* tess = gluNewTess(); + + gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB ); + gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB ); + gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB ); + gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex ); + + GLdouble v_data[3]; + double zpos = ( aZpos + (aThickness / 2) ) * aBiuTo3DUnits; + g_Parm_3D_Visu.m_CurrentZpos = zpos; + v_data[2] = aZpos + (aThickness / 2); + + // Set normal to toward positive Z axis, for a solid object only (to draw the top side) + if( aThickness ) + glNormal3f( 0.0, 0.0, 1.0 ); + + // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + + // Draw solid areas contained in this list + std::vector polylist = aPolysList; // temporary copy for gluTessVertex + + for( int side = 0; side < 2; side++ ) + { + int startContour = 1; + + for( unsigned ii = 0; ii < polylist.size(); ii++ ) + { + if( startContour == 1 ) + { + gluTessBeginPolygon( tess, NULL ); + gluTessBeginContour( tess ); + startContour = 0; + } + + v_data[0] = polylist[ii].x * aBiuTo3DUnits; + v_data[1] = -polylist[ii].y * aBiuTo3DUnits; + // gluTessVertex store pointers on data, not data, so do not store + // different corners values in a temporary variable + // but send pointer on each CPolyPt value in polylist + // before calling gluDeleteTess + gluTessVertex( tess, v_data, &polylist[ii] ); + + if( polylist[ii].end_contour == 1 ) + { + gluTessEndContour( tess ); + gluTessEndPolygon( tess ); + startContour = 1; + } + } + + if( aThickness == 0 ) + break; + + // Prepare the bottom side of solid areas + zpos = ( aZpos - (aThickness / 2) ) * aBiuTo3DUnits; + g_Parm_3D_Visu.m_CurrentZpos = zpos; + v_data[2] = zpos; + // Now;, set normal to toward negative Z axis, for the solid object bottom side + glNormal3f( 0.0, 0.0, -1.0 ); + } + + gluDeleteTess( tess ); + + if( aThickness == 0 ) + return; + + // Build the 3D data : vertical sides + std::vector vertices; + vertices.resize( 4 ); + + vertices[0].z = aZpos + (aThickness / 2); + vertices[1].z = aZpos - (aThickness / 2); + vertices[2].z = vertices[1].z; + vertices[3].z = vertices[0].z; + + int startContour = 0; + for( unsigned ii = 0; ii < polylist.size(); ii++ ) + { + int jj = ii + 1; + + if( polylist[ii].end_contour == 1 ) + { + jj = startContour; + startContour = ii + 1; + } + + vertices[0].x = polylist[ii].x; + vertices[0].y = -polylist[ii].y; + vertices[1].x = vertices[0].x; + vertices[1].y = vertices[0].y; // Z only changes. + vertices[2].x = polylist[jj].x; + vertices[2].y = -polylist[jj].y; + vertices[3].x = vertices[2].x; + vertices[3].y = vertices[2].y; // Z only changes. + + Set_Object_Data( vertices, aBiuTo3DUnits ); + } + + glNormal3f( 0.0, 0.0, 1.0 ); +} + + +/* draw the solid polygon found in aPolysList + * The first polygonj is the main polygon, others are holes + * See Draw3D_SolidHorizontalPolyPolygons for more info + */ +void Draw3D_SolidHorizontalPolygonWithHoles( const std::vector& aPolysList, + int aZpos, int aThickness, double aBiuTo3DUnits ) +{ + std::vector polygon; + + ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon ); + Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits ); +} + + +/* draw a cylinder (a tube) using 3D primitives. + * the cylinder axis is parallel to the Z axis + * If aHeight = height of the cylinder is 0, only one ring will be drawn + * If aThickness = 0, only one cylinder will be drawn + */ +void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius, + int aHeight, int aThickness, + int aZpos, double aBiuTo3DUnits ) +{ + const int slice = 12; + std::vector outer_cornerBuffer; + + TransformCircleToPolygon( outer_cornerBuffer, aCenterPos, + aRadius + (aThickness / 2), slice ); + + std::vector coords; + coords.resize( 4 ); + + if( aHeight ) + { + // Draw the outer vertical side + + // Init Z position of the 4 points of a GL_QUAD + coords[0].z = aZpos; + coords[1].z = aZpos + aHeight; + coords[2].z = coords[1].z; + coords[3].z = coords[0].z; + + for( int ii = 0; ii < slice; ii++ ) + { + int jj = ii + 1; + + if( jj >= slice ) + jj = 0; + + // Build the 4 vertices of each GL_QUAD + coords[0].x = outer_cornerBuffer[jj].x; + coords[0].y = -outer_cornerBuffer[jj].y; + coords[1].x = coords[0].x; + coords[1].y = coords[0].y; // only z change + coords[2].x = outer_cornerBuffer[ii].x; + coords[2].y = -outer_cornerBuffer[ii].y; + coords[3].x = coords[2].x; + coords[3].y = coords[2].y; // only z change + + // Creates the GL_QUAD + Set_Object_Data( coords, aBiuTo3DUnits ); + } + + glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis + } + + if( aThickness == 0 ) + return; + + // draw top (front) and bottom (back) horizontal sides (rings) + S3D_VERTEX centerPos; + centerPos.x = aCenterPos.x * aBiuTo3DUnits; + centerPos.y = -aCenterPos.y * aBiuTo3DUnits; + + Draw3D_FlatRing( aCenterPos, aRadius + aThickness / 2, aRadius - aThickness / 2, + aZpos + aHeight, aBiuTo3DUnits ); + + + glNormal3f( 0.0, 0.0, -1.0 ); + Draw3D_FlatRing( aCenterPos, aRadius + aThickness / 2, aRadius - aThickness / 2, + aZpos, aBiuTo3DUnits ); + + + if( aHeight ) + { + // Draws the vertical inner side (hole) + std::vector inner_cornerBuffer; + TransformCircleToPolygon( inner_cornerBuffer, aCenterPos, + aRadius - (aThickness / 2), slice ); + + for( int ii = 0; ii < slice; ii++ ) + { + int jj = ii + 1; + + if( jj >= slice ) + jj = 0; + + // Build the 4 vertices of each GL_QUAD + coords[0].x = inner_cornerBuffer[ii].x; + coords[0].y = -inner_cornerBuffer[ii].y; + coords[1].x = coords[0].x; + coords[1].y = coords[0].y; // only z change + coords[2].x = inner_cornerBuffer[jj].x; + coords[2].y = -inner_cornerBuffer[jj].y; + coords[3].x = coords[2].x; + coords[3].y = coords[2].y; // only z change + + Set_Object_Data( coords, aBiuTo3DUnits ); + } + } + + glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis +} + + +/* + * Function Draw3D_ZaxisOblongCylinder: + * draw a segment with an oblong hole. + * Used to draw oblong holes + */ +void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos, + int aRadius, int aHeight, int aThickness, + int aZpos, double aBiuTo3DUnits ) +{ + const int slice = 12; + + // Build the points to approximate oblong cylinder by segments + std::vector cornerBuffer; + + TransformRoundedEndsSegmentToPolygon( cornerBuffer, aAxis1Pos, + aAxis2Pos, slice, aRadius * 2 ); + + // Draw the cylinder + std::vector coords; + coords.resize( 4 ); + + // Init Z position of the 4 points of a GL_QUAD + coords[0].z = aZpos; + coords[1].z = aZpos + aHeight; + coords[2].z = coords[1].z; + coords[3].z = coords[0].z; + + for( int ii = 0; ii < slice; ii++ ) + { + int jj = ii + 1; + + if( jj >= slice ) + jj = 0; + + // Build the 4 vertices of each GL_QUAD + coords[0].x = cornerBuffer[ii].x; + coords[0].y = -cornerBuffer[ii].y; + coords[1].x = coords[0].x; + coords[1].y = coords[0].y; // only z change + coords[2].x = cornerBuffer[jj].x; + coords[2].y = -cornerBuffer[jj].y; + coords[3].x = coords[2].x; + coords[3].y = coords[2].y; // only z change + + Set_Object_Data( coords, aBiuTo3DUnits ); + } + + glNormal3f( 0.0, 0.0, 1.0 ); // Normal is Z axis +} + + +/* draw a thick segment using 3D primitives, in a XY plane + * wxPoint aStart, wxPoint aEnd = YX position of end in board units + * aWidth = width of segment in board units + * aThickness = thickness of segment in board units + * aZpos = z position of segment in board units + */ +void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd, + int aWidth, int aThickness, int aZpos, double aBiuTo3DUnits ) +{ + std::vector cornerBuffer; + const int slice = 16; + + TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth ); + + Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits ); +} + + +void Draw3D_ArcSegment( const S3D_VERTEX& aCenterPos, + double aStartPointX, double aStartPointY, + double aArcAngle, double aWidth ) +{ + const int slice = 16; // Number of segments to approximate a circle by segments + double arcStart_Angle; + + arcStart_Angle = + (atan2( aStartPointX - aCenterPos.x, aStartPointY - aCenterPos.y ) * 1800 / M_PI ); + double radius = hypot( aStartPointX - aCenterPos.x, aStartPointY - aCenterPos.y ) + + ( aWidth / 2); + double hole = radius - aWidth; + + // Calculate the number of segments to approximate this arc + int imax = (int) ( (double) aArcAngle / ANGLE_INC( slice ) ); + + if( imax < 0 ) + imax = -imax; + + if( imax == 0 ) + imax = 1; + + // Adjust delta_angle to have exactly imax segments in arc_angle + // i.e. arc_angle = imax delta_agnle. + double delta_angle = (double) aArcAngle / imax; + + glBegin( GL_QUAD_STRIP ); + + for( int ii = 0; ii <= imax; ii++ ) + { + double angle = (double) ii * delta_angle; + angle += arcStart_Angle + 900; + double dx = hole; + double dy = 0.0; + RotatePoint( &dx, &dy, (int) angle ); + glVertex3f( dx + aStartPointX, dy + aStartPointY, aCenterPos.z ); + dx = radius; + dy = 0.0; + RotatePoint( &dx, &dy, (int) angle ); + glVertex3f( dx + aStartPointX, dy + aStartPointY, aCenterPos.z ); + } + + glEnd(); +} + + +/** draw a ring using 3D primitives, in a plane parallel to the XY plane + * @param aCenterPos = position of the center (Board internal units) + * @param aOuterRadius = radius of the external circle (Board internal units) + * @param aInnerRadius = radius of the circle (Board internal units) + * @param aZpos = z position in board internal units + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + */ +void Draw3D_FlatRing( wxPoint aCenterPos, int aOuterRadius, + int aInnerRadius, int aZpos, double aBiuTo3DUnits ) +{ + const int slice = 16; + const int rot_angle = ANGLE_INC( slice ); + double cposx = aCenterPos.x * aBiuTo3DUnits; + double cposy = - aCenterPos.y * aBiuTo3DUnits; + + glBegin( GL_QUAD_STRIP ); + + double zpos = aZpos * aBiuTo3DUnits; + + for( int ii = 0; ii <= slice; ii++ ) + { + double x = aInnerRadius * aBiuTo3DUnits; + double y = 0.0; + RotatePoint( &x, &y, ii * rot_angle ); + glVertex3f( x + cposx, y + cposy, zpos ); + x = aOuterRadius * aBiuTo3DUnits; + y = 0.0; + RotatePoint( &x, &y, ii * rot_angle ); + glVertex3f( x + cposx, y + cposy, zpos ); + } + + glEnd(); +} + + +/* draw one solid polygon + * aCornersList = a std::vector list of corners, in board internal units + * aZpos = z position in board internal units + * aThickness = thickness in board internal units + * aIu_to_3Dunits = board internal units to 3D units scaling value + */ +void Draw3D_HorizontalPolygon( std::vector& aCornersList, int aZpos, + int aThickness, double aBiuTo3DUnits ) +{ + GLUtesselator* tess = gluNewTess(); + + gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB ); + gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB ); + gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB ); + gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tesswxPoint2Vertex ); + + GLdouble v_data[3]; + v_data[2] = ( aZpos + (aThickness / 2) ) * aBiuTo3DUnits; + g_Parm_3D_Visu.m_CurrentZpos = v_data[2]; + + // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + + // Draw solid polygon + if( aThickness ) + glNormal3f( 0.0, 0.0, 1.0 ); + + for( int side = 0; side < 2; side++ ) + { + gluTessBeginPolygon( tess, NULL ); + gluTessBeginContour( tess ); + + for( unsigned ii = 0; ii < aCornersList.size(); ii++ ) + { + v_data[0] = aCornersList[ii].x * g_Parm_3D_Visu.m_BiuTo3Dunits; + v_data[1] = -aCornersList[ii].y * g_Parm_3D_Visu.m_BiuTo3Dunits; + // gluTessVertex store pointers on data, not data, so do not store + // different corners values in a temporary variable + // but send pointer on each corner value in aCornersList + gluTessVertex( tess, v_data, &aCornersList[ii] ); + } + + gluTessEndContour( tess ); + gluTessEndPolygon( tess ); + + if( aThickness == 0 ) + break; + + glNormal3f( 0.0, 0.0, -1.0 ); + v_data[2] = ( aZpos - (aThickness / 2) ) * aBiuTo3DUnits; + g_Parm_3D_Visu.m_CurrentZpos = v_data[2]; + } + + gluDeleteTess( tess ); + + if( aThickness == 0 ) + return; + + // Build the 3D data : vertical sides + std::vector vertices; + vertices.resize( 4 ); + + vertices[0].z = aZpos + (aThickness / 2); + vertices[1].z = aZpos - (aThickness / 2); + vertices[2].z = vertices[1].z; + vertices[3].z = vertices[0].z; + + int slice = (int) aCornersList.size(); + + for( int ii = 0; ii < slice; ii++ ) + { + int jj = ii + 1; + + if( jj >=slice ) + jj = 0; + + vertices[0].x = aCornersList[ii].x; + vertices[0].y = -aCornersList[ii].y; + vertices[1].x = vertices[0].x; + vertices[1].y = vertices[0].y; // Z only changes. + vertices[2].x = aCornersList[jj].x; + vertices[2].y = -aCornersList[jj].y; + vertices[3].x = vertices[2].x; + vertices[3].y = vertices[2].y; // Z only changes. + + Set_Object_Data( vertices, aBiuTo3DUnits ); + } +} + + +// ///////////////////////////////////////////////////////////////////////////// +// GLU_TESS CALLBACKS +// ///////////////////////////////////////////////////////////////////////////// + +void CALLBACK tessBeginCB( GLenum which ) +{ + glBegin( which ); +} + + +void CALLBACK tessEndCB() +{ + glEnd(); +} + + +void CALLBACK tessCPolyPt2Vertex( const GLvoid* data ) +{ + // cast back to double type + const CPolyPt* ptr = (const CPolyPt*) data; + + glVertex3f( ptr->x * g_Parm_3D_Visu.m_BiuTo3Dunits, + -ptr->y * g_Parm_3D_Visu.m_BiuTo3Dunits, + g_Parm_3D_Visu.m_CurrentZpos ); +} + + +void CALLBACK tesswxPoint2Vertex( const GLvoid* data ) +{ + const wxPoint* ptr = (const wxPoint*) data; + + glVertex3f( ptr->x * g_Parm_3D_Visu.m_BiuTo3Dunits, + -ptr->y * g_Parm_3D_Visu.m_BiuTo3Dunits, + g_Parm_3D_Visu.m_CurrentZpos ); +} + + +void CALLBACK tessErrorCB( GLenum errorCode ) +{ +#if defined(DEBUG) + const GLubyte* errorStr; + + errorStr = gluErrorString( errorCode ); + + // DEBUG // + D( printf( "Tess ERROR: %s\n", errorStr ); ) +#endif +} diff --git a/3d-viewer/3d_draw_basic_functions.h b/3d-viewer/3d_draw_basic_functions.h new file mode 100644 index 0000000000..8ec8550e8a --- /dev/null +++ b/3d-viewer/3d_draw_basic_functions.h @@ -0,0 +1,134 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 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_basic_functions.h + */ +#ifndef _3D_DRAW_BASIC_FUNCTIONS_H_ +#define _3D_DRAW_BASIC_FUNCTIONS_H_ + +// angle increment to draw a circle, approximated by segments +#define ANGLE_INC( x ) ( 3600 / (x) ) + + +/** + * Function Draw3D_HorizontalPolygon + * draw one solid polygon + * @param aCornersList = a std::vector list of corners, in board internal units + * @param aZpos = z position in board internal units + * @param aThickness = thickness in board internal units + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. + * If aThickness 1 0, a solid object is drawn. + * The top side is located at aZpos + aThickness / 2 + * The bottom side is located at aZpos - aThickness / 2 + */ +void Draw3D_HorizontalPolygon( std::vector& aCornersList, int aZpos, + int aThickness, double aBiuTo3DUnits ); + +/** draw all solid polygons found in aPolysList + * @param aPolysList = the poligon list to draw + * @param aZpos = z position in board internal units + * @param aThickness = thickness in board internal units + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. + * If aThickness 1 0, a solid object is drawn. + * The top side is located at aZpos + aThickness / 2 + * The bottom side is located at aZpos - aThickness / 2 + */ +void Draw3D_SolidHorizontalPolyPolygons( const std::vector& aPolysList, + int aZpos, int aThickness, double aBiuTo3DUnits ); + +/** draw the solid polygon found in aPolysList + * The first polygonj is the main polygon, others are holes + * @param aPolysList = the polygon with holes to draw + * @param aZpos = z position in board internal units + * @param aThickness = thickness in board internal units + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. + * If aThickness 1 0, a solid object is drawn. + * The top side is located at aZpos + aThickness / 2 + * The bottom side is located at aZpos - aThickness / 2 + */ +void Draw3D_SolidHorizontalPolygonWithHoles( const std::vector& aPolysList, + int aZpos, int aThickness, double aBiuTo3DUnits ); + +/** draw a thick segment using 3D primitives, in a XY plane + * @param wxPoint aStart = YX position of start point in board units + * @param wxPoint aEnd = YX position of end point in board units + * @param aWidth = width of segment in board units + * @param aThickness = thickness of segment in board units + * @param aZpos = z position of segment in board units + * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos. + * If aThickness 1 0, a solid object is drawn. + * The top side is located at aZpos + aThickness / 2 + * The bottom side is located at aZpos - aThickness / 2 + */ +void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd, + int aWidth, int aThickness, int aZpos, + double aBiuTo3DUnits ); + +/** draw an arc using 3D primitives, in a plane parallel to the XY plane + * @param aCenterPos = 3D position of the center + * @param aStartPointX, aStartPointY = start point coordinate of arc (3D units) + * @param aWidth = width of the circle (3D units) + * @param aArcAngle = arc angle in 1/10 degrees + * @param aWidth = thickness of arc + */ +void Draw3D_ArcSegment( const S3D_VERTEX& aCenterPos, + double aStartPointX, double aStartPointY, + double aArcAngle, double aWidth ); + + +/** draw a thick cylinder (a tube) using 3D primitives. + * the cylinder axis is parallel to the Z axis + * @param aCentPos = XY position of the axis cylinder ( board internal units) + * @param aRadius = radius of the cylinder ( board internal units) + * @param aHeight = height of the cylinder ( boardinternal units) + * @param aThickness = tichkness of tube ( boardinternal units) + * @param aZpos = Z position of the bottom side of the cylinder ( board internal units) + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + * + * If aHeight = height of the cylinder is 0, only one ring will be drawn + * If aThickness = 0, only one cylinder (not a tube) will be drawn + */ +void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius, + int aHeight, int aThickness, + int aZpos, double aBiuTo3DUnits ); + +/** draw an oblong cylinder (oblong tube) using 3D primitives. + * the cylinder axis are parallel to the Z axis + * @param aAxis1Pos = position of the first axis cylinder + * @param aAxis2Pos = position of the second axis cylinder + * @param aRadius = radius of the cylinder ( board internal units ) + * @param aHeight = height of the cylinder ( board internal units ) + * @param aThickness = tichkness of tube ( board internal units ) + * @param aZpos = Z position of the bottom side of the cylinder ( board internal units ) + * @param aBiuTo3DUnits = board internal units to 3D units scaling value + */ +void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos, + int aRadius, int aHeight, int aThickness, + int aZpos, double aBiuTo3DUnits ); + +#endif // _3D_DRAW_BASIC_FUNCTIONS_H_ diff --git a/3d-viewer/3d_frame.cpp b/3d-viewer/3d_frame.cpp index 21be897582..18e9f2ab5b 100644 --- a/3d-viewer/3d_frame.cpp +++ b/3d-viewer/3d_frame.cpp @@ -37,8 +37,6 @@ #include <3d_viewer_id.h> INFO3D_VISU g_Parm_3D_Visu; -double DataScale3D; // 3D conversion units. - BEGIN_EVENT_TABLE( EDA_3D_FRAME, wxFrame ) EVT_ACTIVATE( EDA_3D_FRAME::OnActivate ) @@ -130,6 +128,13 @@ void EDA_3D_FRAME::OnCloseWindow( wxCloseEvent& Event ) Destroy(); } +static const wxString keyPosx( wxT( "Pos_x" ) ); +static const wxString keyPosy( wxT( "Pos_y" ) ); +static const wxString keySizex( wxT( "Size_x" ) ); +static const wxString keySizey( wxT( "Size_y" ) ); +static const wxString keyBgColor_Red( wxT( "BgColor_Red" ) ); +static const wxString keyBgColor_Green( wxT( "BgColor_Green" ) ); +static const wxString keyBgColor_Blue( wxT( "BgColor_Blue" ) ); void EDA_3D_FRAME::GetSettings() { @@ -138,17 +143,17 @@ void EDA_3D_FRAME::GetSettings() if( config ) { - text = m_FrameName + wxT( "Pos_x" ); + text = m_FrameName + keyPosx; config->Read( text, &m_FramePos.x ); - text = m_FrameName + wxT( "Pos_y" ); + text = m_FrameName + keyPosy; config->Read( text, &m_FramePos.y ); - text = m_FrameName + wxT( "Size_x" ); + text = m_FrameName + keySizex; config->Read( text, &m_FrameSize.x, 600 ); - text = m_FrameName + wxT( "Size_y" ); + text = m_FrameName + keySizey; config->Read( text, &m_FrameSize.y, 400 ); - config->Read( wxT( "BgColor_Red" ), &g_Parm_3D_Visu.m_BgColor.m_Red, 0.0 ); - config->Read( wxT( "BgColor_Green" ), &g_Parm_3D_Visu.m_BgColor.m_Green, 0.0 ); - config->Read( wxT( "BgColor_Blue" ), &g_Parm_3D_Visu.m_BgColor.m_Blue, 0.0 ); + config->Read( keyBgColor_Red, &g_Parm_3D_Visu.m_BgColor.m_Red, 0.0 ); + config->Read( keyBgColor_Green, &g_Parm_3D_Visu.m_BgColor.m_Green, 0.0 ); + config->Read( keyBgColor_Blue, &g_Parm_3D_Visu.m_BgColor.m_Blue, 0.0 ); } #if defined( __WXMAC__ ) // for macOSX, the window must be below system (macOSX) toolbar @@ -166,9 +171,9 @@ void EDA_3D_FRAME::SaveSettings() if( !Config ) return; - Config->Write( wxT( "BgColor_Red" ), g_Parm_3D_Visu.m_BgColor.m_Red ); - Config->Write( wxT( "BgColor_Green" ), g_Parm_3D_Visu.m_BgColor.m_Green ); - Config->Write( wxT( "BgColor_Blue" ), g_Parm_3D_Visu.m_BgColor.m_Blue ); + Config->Write( keyBgColor_Red, g_Parm_3D_Visu.m_BgColor.m_Red ); + Config->Write( keyBgColor_Green, g_Parm_3D_Visu.m_BgColor.m_Green ); + Config->Write( keyBgColor_Blue, g_Parm_3D_Visu.m_BgColor.m_Blue ); if( IsIconized() ) return; @@ -176,13 +181,13 @@ void EDA_3D_FRAME::SaveSettings() m_FrameSize = GetSize(); m_FramePos = GetPosition(); - text = m_FrameName + wxT( "Pos_x" ); + text = m_FrameName + keyPosx; Config->Write( text, (long) m_FramePos.x ); - text = m_FrameName + wxT( "Pos_y" ); + text = m_FrameName + keyPosy; Config->Write( text, (long) m_FramePos.y ); - text = m_FrameName + wxT( "Size_x" ); + text = m_FrameName + keySizex; Config->Write( text, (long) m_FrameSize.x ); - text = m_FrameName + wxT( "Size_y" ); + text = m_FrameName + keySizey; Config->Write( text, (long) m_FrameSize.y ); } @@ -322,6 +327,11 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event ) NewDisplay(); return; + case ID_MENU3D_USE_COPPER_THICKNESS: + g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_USE_COPPER_THICKNESS] = isChecked; + NewDisplay(); + return; + case ID_MENU3D_ZONE_ONOFF: g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_ZONE] = isChecked; NewDisplay(); diff --git a/3d-viewer/3d_read_mesh.cpp b/3d-viewer/3d_read_mesh.cpp index 3a07a4d083..2cfe1c7b1c 100644 --- a/3d-viewer/3d_read_mesh.cpp +++ b/3d-viewer/3d_read_mesh.cpp @@ -34,6 +34,10 @@ #include #include <3d_viewer.h> +#include + +// Imported function: +extern void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits ); // separator chars static const char* sep_chars = " \t\n\r"; @@ -400,6 +404,7 @@ int S3D_MASTER::ReadGeometry( FILE* file, int* LineNum ) int err = 1; std::vector< double > points; std::vector< double > list; + double vrmlunits_to_3Dunits = g_Parm_3D_Visu.m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB; while( GetLine( file, line, LineNum, 512 ) ) { @@ -545,7 +550,7 @@ int S3D_MASTER::ReadGeometry( FILE* file, int* LineNum ) } Set_Object_Coords( vertices ); - Set_Object_Data( vertices ); + Set_Object_Data( vertices, vrmlunits_to_3Dunits ); vertices.clear(); coordIndex.clear(); } diff --git a/3d-viewer/3d_toolbar.cpp b/3d-viewer/3d_toolbar.cpp index 848014f494..2ab028f7aa 100644 --- a/3d-viewer/3d_toolbar.cpp +++ b/3d-viewer/3d_toolbar.cpp @@ -169,6 +169,10 @@ void EDA_3D_FRAME::ReCreateMenuBar() if( full_options ) { + item = AddMenuItem( prefsMenu, ID_MENU3D_USE_COPPER_THICKNESS, + _( "Show Copper Thickness" ), KiBitmap( use_3D_copper_thickness_xpm ), wxITEM_CHECK ); + item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_USE_COPPER_THICKNESS]); + item = AddMenuItem( prefsMenu, ID_MENU3D_MODULE_ONOFF, _( "Show 3D F&ootprints" ), KiBitmap( shape_3d_xpm ), wxITEM_CHECK ); item->Check(g_Parm_3D_Visu.m_DrawFlags[g_Parm_3D_Visu.FL_MODULE]); diff --git a/3d-viewer/3d_viewer.h b/3d-viewer/3d_viewer.h index 73c17c8432..7af89351df 100644 --- a/3d-viewer/3d_viewer.h +++ b/3d-viewer/3d_viewer.h @@ -30,8 +30,9 @@ #ifndef __3D_VIEWER_H__ #define __3D_VIEWER_H__ -#include // m_auimanager member. +#include // for m_auimanager member. #include // Layers id definitions +#include // fot CPolyPt #if !wxUSE_GLCANVAS #error Please set wxUSE_GLCANVAS to 1 in setup.h. @@ -149,24 +150,6 @@ public: */ void Draw3D_Zone( ZONE_CONTAINER* aZone ); - /** - * Function Draw3D_SolidPolygonsInZones - * draw all solid polygons used as filled areas in a zone - * Function used by Draw3D_Zone - * Note: polygons are drawn, but not the thick polygon outlines - * Use Draw3D_Zone to draw aZone - * @param aZone = the zone to draw - */ - void Draw3D_SolidPolygonsInZones( ZONE_CONTAINER* aZone ); - - /** - * Function Draw3D_Polygon - * draw one solid polygon - * @param aCornersList = a std::vector list of corners, in physical coordinates - * @param aZpos = the z position in 3D units - */ - void Draw3D_Polygon( std::vector& aCornersList, double aZpos ); - /** * Function Draw3D_DrawText * draws 3D segments to create text objects. @@ -258,7 +241,4 @@ private: DECLARE_EVENT_TABLE() }; -void SetGLColor( int color ); -void Set_Object_Data( std::vector< S3D_VERTEX >& aVertices ); - #endif /* __3D_VIEWER_H__ */ diff --git a/3d-viewer/3d_viewer_id.h b/3d-viewer/3d_viewer_id.h index 440322e624..447bad55b4 100644 --- a/3d-viewer/3d_viewer_id.h +++ b/3d-viewer/3d_viewer_id.h @@ -29,6 +29,7 @@ enum id_3dview_frm ID_MOVE3D_DOWN, ID_ORTHO, ID_MENU3D_BGCOLOR_SELECTION, + ID_MENU3D_USE_COPPER_THICKNESS, ID_MENU3D_AXIS_ONOFF, ID_MENU3D_MODULE_ONOFF, ID_MENU3D_ZONE_ONOFF, diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index 81d45213e0..c48af8613b 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -13,9 +13,11 @@ set(3D-VIEWER_SRCS 3d_canvas.cpp 3d_class.cpp 3d_draw.cpp + 3d_draw_basic_functions.cpp 3d_frame.cpp 3d_read_mesh.cpp 3d_toolbar.cpp + info3d_visu.cpp trackball.cpp ) diff --git a/3d-viewer/info3d_visu.cpp b/3d-viewer/info3d_visu.cpp new file mode 100644 index 0000000000..2a61f0ca04 --- /dev/null +++ b/3d-viewer/info3d_visu.cpp @@ -0,0 +1,194 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2011 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 info3d_visu.cpp + */ + +#include + +#include + +#include +#include + +#include <3d_viewer.h> +#include +#include + +// Thickness of copper +// TODO: define the actual copper thickness by user +#define COPPER_THICKNESS (int)(0.035 * IU_PER_MM) // for 35 u +#define TECH_LAYER_THICKNESS (int)(0.04 * IU_PER_MM) +#define EPOXY_THICKNESS (int)(1.6 * IU_PER_MM) // for 1.6 mm + + +/* INFO3D_VISU in an helper class to store parameters like scaling factors, + * board size, Z coordinates of layers ... + * to create the 3D GLList + */ +INFO3D_VISU::INFO3D_VISU() +{ + int ii; + + m_Beginx = m_Beginy = 0.0; // position of mouse + m_Zoom = 1.0; + m_3D_Grid = 10.0; // Grid value in mm + trackball( m_Quat, 0.0, 0.0, 0.0, 0.0 ); + + for( ii = 0; ii < 4; ii++ ) + m_Rot[ii] = 0.0; + + m_CopperLayersCount = 2; + m_BoardSettings = NULL; + m_CopperThickness = 0; + m_EpoxyThickness = 0; + m_NonCopperLayerThickness = 0; + + // default all special item layers Visible + for( ii = 0; ii < FL_LAST; ii++ ) + m_DrawFlags[ii] = true; + + m_DrawFlags[FL_GRID] = false; + m_DrawFlags[FL_USE_COPPER_THICKNESS] = false; +} + + +INFO3D_VISU::~INFO3D_VISU() +{ +} + + +/* Initialize info 3D Parameters from aBoard + */ +void INFO3D_VISU::InitSettings( BOARD* aBoard ) +{ + EDA_RECT bbbox = aBoard->ComputeBoundingBox( false ); + + if( bbbox.GetWidth() == 0 && bbbox.GetHeight() == 0 ) + { + bbbox.SetWidth( 100 * IU_PER_MM ); + bbbox.SetHeight( 100 * IU_PER_MM ); + } + + m_BoardSettings = &aBoard->GetDesignSettings(); + + m_BoardSize = bbbox.GetSize(); + m_BoardPos = bbbox.Centre(); + + m_BoardPos.y = -m_BoardPos.y; + m_CopperLayersCount = aBoard->GetCopperLayerCount(); + + // Ensure the board has 2 sides for 3D views, because it is hard to find + // a *really* single side board in the true life... + if( m_CopperLayersCount < 2 ) + m_CopperLayersCount = 2; + + m_BiuTo3Dunits = 2.0 / std::max( m_BoardSize.x, m_BoardSize.y ); + + m_EpoxyThickness = aBoard->GetDesignSettings().GetBoardThickness() * m_BiuTo3Dunits; + + // TODO use value defined by user (currently use default values by ctor + m_CopperThickness = COPPER_THICKNESS * m_BiuTo3Dunits; + m_NonCopperLayerThickness = TECH_LAYER_THICKNESS * m_BiuTo3Dunits; + + // Init Z position of each layer + // calculate z position for each copper layer + int layer; + int copper_layers_cnt = m_CopperLayersCount; + + for( layer = 0; layer < copper_layers_cnt; layer++ ) + { + m_LayerZcoord[layer] = + m_EpoxyThickness * layer / (copper_layers_cnt - 1); + } + + double zpos_copper_back = m_LayerZcoord[0]; + double zpos_copper_front = m_EpoxyThickness; + + // Fill remaining unused copper layers and front layer zpos + // with m_EpoxyThickness + for( ; layer <= LAST_COPPER_LAYER; layer++ ) + { + m_LayerZcoord[layer] = m_EpoxyThickness; + } + + // calculate z position for each non copper layer + for( int layer_id = FIRST_NO_COPPER_LAYER; layer_id < NB_LAYERS; layer_id++ ) + { + double zpos; + #define NonCopperLayerThicknessMargin 1.1 + + switch( layer_id ) + { + case ADHESIVE_N_BACK: + zpos = zpos_copper_back - + 4 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case ADHESIVE_N_FRONT: + zpos = zpos_copper_front + + 4 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SOLDERPASTE_N_BACK: + zpos = zpos_copper_back - + 3 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SOLDERPASTE_N_FRONT: + zpos = zpos_copper_front + + 3 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SOLDERMASK_N_BACK: + zpos = zpos_copper_back - + 1 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SOLDERMASK_N_FRONT: + zpos = zpos_copper_front + + 1 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SILKSCREEN_N_BACK: + zpos = zpos_copper_back - + 2 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + case SILKSCREEN_N_FRONT: + zpos = zpos_copper_front + + 2 * m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + + default: + zpos = zpos_copper_front + + (layer_id - FIRST_NO_COPPER_LAYER + 5) * + m_NonCopperLayerThickness * NonCopperLayerThicknessMargin; + break; + } + + m_LayerZcoord[layer_id] = zpos; + } +} diff --git a/3d-viewer/info3d_visu.h b/3d-viewer/info3d_visu.h index 0ef7c3177b..73f798d16b 100644 --- a/3d-viewer/info3d_visu.h +++ b/3d-viewer/info3d_visu.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * @@ -24,7 +24,7 @@ */ /** - * @file 3d_viewer.h + * @file info3d_visu.h */ #ifndef __INFO3D_VISU_H__ @@ -33,10 +33,6 @@ #include // m_auimanager member. #include // Layers id definitions -#if !wxUSE_GLCANVAS -#error Please set wxUSE_GLCANVAS to 1 in setup.h. -#endif - #include #ifdef __WXMAC__ @@ -74,34 +70,74 @@ public: FL_AXIS=0, FL_MODULE, FL_ZONE, FL_COMMENTS, FL_DRAWINGS, FL_ECO1, FL_ECO2, FL_GRID, + FL_USE_COPPER_THICKNESS, FL_LAST }; - double m_Beginx, m_Beginy; // position of mouse - double m_Quat[4]; // orientation of object - double m_Rot[4]; // man rotation of object - double m_Zoom; // field of view in degrees - double m_3D_Grid; // 3D grid valmue, in mm + double m_Beginx, m_Beginy; // position of mouse (used in drag commands) + double m_Quat[4]; // orientation of 3D view + double m_Rot[4]; // rotation parameters of 3D view + double m_Zoom; // 3D zoom value + double m_3D_Grid; // 3D grid valmue, in mm S3D_COLOR m_BgColor; - bool m_DrawFlags[FL_LAST]; // show these special items - wxPoint m_BoardPos; - wxSize m_BoardSize; + bool m_DrawFlags[FL_LAST]; // Enable/disable flags (see DISPLAY3D_FLG list) + wxPoint m_BoardPos; // center board actual position in board units + wxSize m_BoardSize; // board actual size in board units int m_CopperLayersCount; // Number of copper layers actually used by the board const BOARD_DESIGN_SETTINGS* m_BoardSettings; // Link to current board design settings + double m_BiuTo3Dunits; // Normalization scale to convert board + // internal units to 3D units + // to scale 3D units between -1.0 and +1.0 + double m_LayerZcoord[LAYER_COUNT]; // Z position of each layer (normalized) + double m_CurrentZpos; // temporary storage of current value of Z position, + // used in some calculation +private: + double m_CopperThickness; // Copper thickness (normalized) double m_EpoxyThickness; // Epoxy thickness (normalized) double m_NonCopperLayerThickness; // Non copper layers thickness - double m_BoardScale; /* Normalization scale for coordinates: - * when scaled between -1.0 and +1.0 */ - double m_LayerZcoord[LAYER_COUNT]; // Z position of each layer (normalized) - double m_ActZpos; public: INFO3D_VISU(); ~INFO3D_VISU(); + + /** + * Function InitSettings + * Initialize info 3D Parameters from aBoard + * @param aBoard: the board to display + */ + void InitSettings( BOARD* aBoard ); + + /** + * function m_BiuTo3Dunits + * @return the Z coordinate of the layer aLayer, in Board Internal Units + * @param aLayer: the layer number + */ + int GetLayerZcoordBIU( int aLayer ) + { + return (int) (m_LayerZcoord[aLayer] / m_BiuTo3Dunits ); + } + + int GetCopperThicknessBIU() const + { + return m_DrawFlags[FL_USE_COPPER_THICKNESS] ? + (int) (m_CopperThickness / m_BiuTo3Dunits ) + : 0; + } + + int GetEpoxyThicknessBIU() const + { + return (int) (m_EpoxyThickness / m_BiuTo3Dunits ); + } + + int GetNonCopperLayerThicknessBIU() const + { + return m_DrawFlags[FL_USE_COPPER_THICKNESS] ? + (int) (m_NonCopperLayerThickness / m_BiuTo3Dunits ) + : 0; + } }; -extern INFO3D_VISU g_Parm_3D_Visu; -extern double DataScale3D; // 3D scale units. +extern INFO3D_VISU g_Parm_3D_Visu; #endif /* __INFO3D_VISU_H__ */ diff --git a/bitmaps_png/CMakeLists.txt b/bitmaps_png/CMakeLists.txt index 9212c0611c..d12cb92d38 100644 --- a/bitmaps_png/CMakeLists.txt +++ b/bitmaps_png/CMakeLists.txt @@ -485,6 +485,7 @@ set( BMAPS_MID unzip update_module_board up + use_3D_copper_thickness via via_sketch warning diff --git a/bitmaps_png/cpp_26/use_3D_copper_thickness.cpp b/bitmaps_png/cpp_26/use_3D_copper_thickness.cpp new file mode 100644 index 0000000000..344f169823 --- /dev/null +++ b/bitmaps_png/cpp_26/use_3D_copper_thickness.cpp @@ -0,0 +1,43 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x01, 0xa6, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xbd, 0xd5, 0xbf, 0x4b, 0xc3, + 0x50, 0x10, 0x07, 0xf0, 0x4b, 0xfa, 0xde, 0x8b, 0x4e, 0x16, 0x71, 0x12, 0x2b, 0x0e, 0x2e, 0xa5, + 0x43, 0x71, 0x12, 0x1c, 0xc4, 0xa5, 0xe8, 0x22, 0x76, 0x71, 0xd0, 0xa1, 0xa3, 0x4b, 0x41, 0x6c, + 0x5a, 0x7f, 0x80, 0x08, 0x2e, 0x82, 0xe0, 0xa2, 0x83, 0xae, 0x2a, 0x45, 0x11, 0x9c, 0x15, 0x5c, + 0x0a, 0x8a, 0xe0, 0xe0, 0xa0, 0x50, 0xf0, 0x0f, 0x28, 0x2a, 0x16, 0xc4, 0x22, 0x0e, 0x6a, 0xa1, + 0x3d, 0xbf, 0x95, 0x0e, 0x6a, 0x92, 0xa9, 0x87, 0x90, 0x6f, 0x08, 0x21, 0xe4, 0x93, 0xbb, 0xe4, + 0x5d, 0x88, 0x99, 0xe9, 0x3f, 0x42, 0xd8, 0x1c, 0xa4, 0x4d, 0x28, 0xa1, 0x60, 0xc8, 0x98, 0x3c, + 0xc2, 0x22, 0x71, 0x9c, 0x0b, 0xdc, 0xd2, 0x0e, 0xaa, 0x28, 0x8c, 0x8b, 0xee, 0x05, 0x31, 0xd7, + 0x17, 0xca, 0x11, 0xed, 0xec, 0xda, 0x76, 0x59, 0x0c, 0x32, 0xe6, 0x1d, 0x89, 0x7a, 0xa0, 0x05, + 0xa2, 0x6e, 0x60, 0x2f, 0x57, 0x4a, 0xb1, 0x20, 0x76, 0x8d, 0x5b, 0xab, 0xdf, 0xad, 0xc3, 0x0e, + 0xd0, 0xf4, 0x32, 0x0e, 0x9f, 0xb5, 0x96, 0xc4, 0x56, 0x3c, 0x50, 0x13, 0x3b, 0xde, 0xb6, 0x2c, + 0xae, 0xcb, 0x41, 0x55, 0xd6, 0x7a, 0xc0, 0x03, 0x65, 0x89, 0xba, 0xe6, 0x89, 0x9e, 0xce, 0x43, + 0x21, 0xc9, 0xaa, 0x8a, 0xdf, 0xcb, 0xe7, 0x27, 0xd4, 0xac, 0x6a, 0x62, 0x09, 0xa7, 0xca, 0xb2, + 0x2d, 0x5c, 0xf7, 0x40, 0x4d, 0x6c, 0x6f, 0x0b, 0x2d, 0xac, 0xc9, 0x41, 0x35, 0x56, 0x6a, 0xc8, + 0x03, 0x2d, 0x12, 0x75, 0x00, 0x2b, 0xed, 0xdb, 0x36, 0x9f, 0xa0, 0x8d, 0xad, 0xe6, 0x46, 0xa9, + 0x53, 0x60, 0x93, 0xbe, 0xe3, 0x02, 0xef, 0x2b, 0x01, 0xac, 0x8e, 0xb0, 0x40, 0x3e, 0xf0, 0xf0, + 0xb1, 0xc0, 0x21, 0x88, 0x0b, 0xdc, 0x46, 0x1b, 0x85, 0x32, 0x4b, 0x59, 0x56, 0xc3, 0x19, 0x76, + 0xc6, 0x64, 0x62, 0x62, 0x81, 0x43, 0xd5, 0x65, 0x27, 0xed, 0xb2, 0x61, 0xa1, 0x54, 0x5c, 0x6e, + 0x8f, 0xf8, 0x42, 0x3d, 0xe3, 0x14, 0x4d, 0xbf, 0xe9, 0x4b, 0x39, 0x4c, 0x17, 0x30, 0xa9, 0x2d, + 0x3f, 0x28, 0xd7, 0x9f, 0xb2, 0x38, 0xfd, 0x2a, 0x56, 0x15, 0xe2, 0xe4, 0xfc, 0x20, 0x0b, 0x29, + 0x0c, 0xae, 0xd9, 0x82, 0x90, 0xf9, 0x44, 0x65, 0x71, 0xcf, 0xac, 0x03, 0x14, 0x41, 0x2a, 0xc9, + 0x33, 0x25, 0x89, 0x15, 0x57, 0x19, 0x7f, 0xdd, 0xbf, 0xb3, 0x0e, 0xd0, 0x54, 0x1f, 0x96, 0xd5, + 0xcc, 0xa3, 0x16, 0xc3, 0x32, 0xac, 0x37, 0x3d, 0x50, 0x13, 0x3b, 0x88, 0xe7, 0x2c, 0xce, 0xd4, + 0xc4, 0xaa, 0xaa, 0x67, 0xd9, 0x49, 0xf8, 0x41, 0x61, 0xa4, 0x34, 0x7a, 0x18, 0x92, 0x6c, 0xe1, + 0x43, 0x86, 0xa9, 0xd3, 0xf3, 0xbd, 0x03, 0x1a, 0xe9, 0x4d, 0x52, 0x2d, 0x75, 0xa7, 0x79, 0xae, + 0x6a, 0x5a, 0x8e, 0x5b, 0x37, 0x55, 0x60, 0x79, 0xdf, 0x55, 0x0c, 0x6c, 0x03, 0x61, 0xa1, 0x94, + 0x1a, 0x9d, 0x0a, 0x82, 0x0c, 0x72, 0x2b, 0x88, 0x1d, 0x7d, 0x01, 0xbf, 0xeb, 0x9b, 0xb8, 0x05, + 0x3e, 0x9f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE use_3D_copper_thickness_xpm[1] = {{ png, sizeof( png ), "use_3D_copper_thickness_xpm" }}; + +//EOF diff --git a/bitmaps_png/sources/use_3D_copper_thickness.svg b/bitmaps_png/sources/use_3D_copper_thickness.svg new file mode 100644 index 0000000000..079dfae905 --- /dev/null +++ b/bitmaps_png/sources/use_3D_copper_thickness.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 1f16d74dc4..17173008ac 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -306,49 +306,6 @@ PARAM_CFG_ARRAY& SCH_EDIT_FRAME::GetProjectFileParameters() &g_HPGL_Pen_Descr.m_Pen_Num, 1, 1, 8 ) ); -/* these globals don't exist - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A4" ), - &g_Sheet_A4.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A4" ), - &g_Sheet_A4.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A3" ), - &g_Sheet_A3.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A3" ), - &g_Sheet_A3.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A2" ), - &g_Sheet_A2.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A2" ), - &g_Sheet_A2.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A1" ), - &g_Sheet_A1.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A1" ), - &g_Sheet_A1.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A0" ), - &g_Sheet_A0.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A0" ), - &g_Sheet_A0.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_A" ), - &g_Sheet_A.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_A" ), - &g_Sheet_A.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_B" ), - &g_Sheet_B.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_B" ), - &g_Sheet_B.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_C" ), - &g_Sheet_C.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_C" ), - &g_Sheet_C.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_D" ), - &g_Sheet_D.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_D" ), - &g_Sheet_D.m_Offset.y ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offX_E" ), - &g_Sheet_E.m_Offset.x ) ); - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "offY_E" ), - &g_Sheet_E.m_Offset.y ) ); -*/ - m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "RptD_X" ), &g_RepeatStep.x, 0, -1000, +1000 ) ); diff --git a/include/bitmaps.h b/include/bitmaps.h index 69d78d789b..c68842cb05 100644 --- a/include/bitmaps.h +++ b/include/bitmaps.h @@ -458,6 +458,7 @@ EXTERN_BITMAP( unlocked_xpm ) EXTERN_BITMAP( unzip_xpm ) EXTERN_BITMAP( update_module_board_xpm ) EXTERN_BITMAP( up_xpm ) +EXTERN_BITMAP( use_3D_copper_thickness_xpm ) EXTERN_BITMAP( via_xpm ) EXTERN_BITMAP( via_sketch_xpm ) EXTERN_BITMAP( viewlibs_icon_xpm )