3D viewer: optimizations in code to build the 3D view.

Remove no more used code.
Building the 3D view is now faster.
This commit is contained in:
jean-pierre charras 2015-08-10 17:17:10 +02:00
parent 8b46c4eb8f
commit 7a51a502b4
5 changed files with 72 additions and 130 deletions

View File

@ -87,27 +87,34 @@ static void Draw3D_VerticalPolygonalCylinder( const SHAPE_POLY_SET& aPolysList,
coords[3].z = coords[0].z;
// Draw the vertical polygonal side
for( int ii = 0; ii < aPolysList.OutlineCount(); ii++ )
for( int idx = 0; idx < aPolysList.OutlineCount(); idx++ )
{
const SHAPE_LINE_CHAIN& path = aPolysList.COutline( ii );
// Each polygon in aPolysList is a polygon with holes
const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aPolysList.CPolygon( idx );
for( int jj = 0; jj < path.PointCount(); jj++ )
// Draw the outline of each simple polygon inside the polygon with holes:
for( unsigned ipoly = 0; ipoly < curr_polywithholes.size(); ipoly++ )
{
const VECTOR2I& a = path.CPoint( jj );
const VECTOR2I& b = path.CPoint( jj + 1 );
const SHAPE_LINE_CHAIN& path = curr_polywithholes[ipoly]; // a simple polygon
// Build the 4 vertices of each GL_QUAD
coords[0].x = a.x;
coords[0].y = -a.y;
coords[1].x = coords[0].x;
coords[1].y = coords[0].y; // only z change
coords[2].x = b.x;
coords[2].y = -b.y;
coords[3].x = coords[2].x;
coords[3].y = coords[2].y; // only z change
for( int jj = 0; jj < path.PointCount(); jj++ )
{
const VECTOR2I& a = path.CPoint( jj );
const VECTOR2I& b = path.CPoint( jj + 1 );
// Creates the GL_QUAD
TransfertToGLlist( coords, aBiuTo3DUnits );
// Build the 4 vertices of each GL_QUAD
coords[0].x = a.x;
coords[0].y = -a.y;
coords[1].x = coords[0].x;
coords[1].y = coords[0].y; // only z change
coords[2].x = b.x;
coords[2].y = -b.y;
coords[3].x = coords[2].x;
coords[3].y = coords[2].y; // only z change
// Creates the GL_QUAD
TransfertToGLlist( coords, aBiuTo3DUnits );
}
}
}
}
@ -169,46 +176,47 @@ void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
// Set normal toward positive Z axis, for a solid object on the top side
//gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE );
//gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
//gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE );
gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
glNormal3f( 0.0, 0.0, aNormal_Z_Orientation );
// Draw solid areas contained in this list
SHAPE_POLY_SET polylist = aPolysList; // temporary copy for gluTessVertex
int startContour;
for( int side = 0; side < 2; side++ )
{
startContour = 1;
for ( SHAPE_POLY_SET::ITERATOR ii = polylist.Iterate(); ii; ++ii )
for ( int idx = 0; idx < polylist.OutlineCount(); ++idx )
{
if( startContour == 1 )
gluTessBeginPolygon( tess, NULL );
SHAPE_POLY_SET::POLYGON& curr_polywithholes = polylist.Polygon( idx ); // a polygon with holes
for( unsigned ipoly = 0; ipoly < curr_polywithholes.size(); ipoly++ )
{
gluTessBeginPolygon( tess, NULL );
SHAPE_LINE_CHAIN& curr_poly = curr_polywithholes[ipoly]; // a simple polygon
gluTessBeginContour( tess );
startContour = 0;
}
v_data[0] = ii->x * aBiuTo3DUnits;
v_data[1] = -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, &ii.Get() );
for( int ipt = 0; ipt < curr_poly.PointCount(); ipt++ )
{
v_data[0] = curr_poly.Point( ipt ).x * aBiuTo3DUnits;
v_data[1] = -curr_poly.Point( ipt ).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, &curr_poly.Point( ipt ) );
}
if( ii.IsEndContour() )
{
gluTessEndContour( tess );
gluTessEndPolygon( tess );
startContour = 1;
}
gluTessEndPolygon( tess );
}
if( aThickness == 0 )
break;
@ -220,12 +228,6 @@ void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
glNormal3f( 0.0, 0.0, -aNormal_Z_Orientation );
}
if( startContour == 0 )
{
gluTessEndContour( tess );
gluTessEndPolygon( tess );
}
gluDeleteTess( tess );
if( aThickness == 0 )
@ -237,24 +239,6 @@ void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
}
/* draw the solid polygon found in aPolysList
* The first polygon is the main polygon, others are holes
* See Draw3D_SolidHorizontalPolyPolygons for more info
*/
void Draw3D_SolidHorizontalPolygonWithHoles( const SHAPE_POLY_SET& aPolysList,
int aZpos, int aThickness,
double aBiuTo3DUnits, bool aUseTextures,
float aNormal_Z_Orientation )
{
SHAPE_POLY_SET polygon( aPolysList );
polygon.Fracture();
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures,
aNormal_Z_Orientation );
}
/* 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
@ -274,6 +258,7 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
coords.resize( 4 );
SHAPE_POLY_SET inner_cornerBuffer;
if( aThickness ) // build the the vertical inner polygon (hole)
TransformCircleToPolygon( inner_cornerBuffer, aCenterPos,
aRadius - (aThickness / 2), slice );
@ -283,31 +268,28 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
// Draw the vertical outer side
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer,
aHeight, aZpos, false, aBiuTo3DUnits );
aHeight, aZpos, false, aBiuTo3DUnits );
if( aThickness )
// Draws the vertical inner side (hole)
Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer,
aHeight, aZpos, true, aBiuTo3DUnits );
aHeight, aZpos, true, aBiuTo3DUnits );
}
if( aThickness )
{
// draw top (front) and bottom (back) horizontal sides (rings)
outer_cornerBuffer.AddHole( inner_cornerBuffer.COutline( 0 ) );
SHAPE_POLY_SET polygon = outer_cornerBuffer;
polygon.Fracture();
// draw top (front) horizontal ring
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false,
1.0f );
Draw3D_SolidHorizontalPolyPolygons( outer_cornerBuffer, aZpos + aHeight,
0, aBiuTo3DUnits, false, 1.0f );
if( aHeight )
{
// draw bottom (back) horizontal ring
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false,
-1.0f );
Draw3D_SolidHorizontalPolyPolygons( outer_cornerBuffer, aZpos,
0, aBiuTo3DUnits, false, -1.0f );
}
}
}
@ -327,15 +309,15 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
const int slice = SEGM_PER_CIRCLE;
// Build the points to approximate oblong cylinder by segments
SHAPE_POLY_SET outer_cornerBuffer;
SHAPE_POLY_SET cornerBuffer;
int segm_width = (aRadius * 2) + aThickness;
TransformRoundedEndsSegmentToPolygon( outer_cornerBuffer, aAxis1Pos,
TransformRoundedEndsSegmentToPolygon( cornerBuffer, aAxis1Pos,
aAxis2Pos, slice, segm_width );
// Draw the oblong outer cylinder
if( aHeight )
Draw3D_VerticalPolygonalCylinder( outer_cornerBuffer, aHeight, aZpos,
Draw3D_VerticalPolygonalCylinder( cornerBuffer, aHeight, aZpos,
false, aBiuTo3DUnits );
if( aThickness )
@ -352,19 +334,16 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
// Build the horizontal full polygon shape
// (outer polygon shape - inner polygon shape)
outer_cornerBuffer.AddHole( inner_cornerBuffer.COutline( 0 ) );
SHAPE_POLY_SET polygon( outer_cornerBuffer );
polygon.Fracture();
cornerBuffer.AddHole( inner_cornerBuffer.COutline( 0 ) );
// draw top (front) horizontal side (ring)
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false,
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos + aHeight, 0, aBiuTo3DUnits, false,
1.0f );
if( aHeight )
{
// draw bottom (back) horizontal side (ring)
Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false,
Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, 0, aBiuTo3DUnits, false,
-1.0f );
}
}

View File

@ -48,24 +48,6 @@ void Draw3D_SolidHorizontalPolyPolygons( const SHAPE_POLY_SET& aPolysList,
bool aUseTextures,
float aNormal_Z_Orientation );
/** 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
* @param aUseTextures = true to use textxures for the polygons
* @param aNormal_Z_Orientation = the normal Z orientation to apply
* If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
* If aThickness > 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 SHAPE_POLY_SET& aPolysList,
int aZpos, int aThickness, double aBiuTo3DUnits,
bool aUseTextures,
float aNormal_Z_Orientation );
/** draw a thick segment using 3D primitives, in a XY plane
* @param aStart = YX position of start point in board units
* @param aEnd = YX position of end point in board units

View File

@ -85,11 +85,8 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES );
// Number of segments to convert a circle to polygon
// Boost polygon (at least v1.57 and previous) in very rare cases crashes
// when using 16 segments to approximate a circle.
// So using 18 segments is a workaround to try to avoid these crashes
// ( We already used this trick in plot_board_layers.cpp,
// see PlotSolderMaskLayer() )
// We use 2 values: the first gives a good shape
// the second is used to speed up calculations, when a poor approximation is acceptable (holes)
const int segcountforcircle = 18;
double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) );
const int segcountLowQuality = 12; // segments to draw a circle with low quality
@ -119,22 +116,11 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
}
bool throughHolesListBuilt = false; // flag to build the through hole polygon list only once
LSET cu_set = LSET::AllCuMask( GetPrm3DVisu().m_CopperLayersCount );
#if 1
LAYER_ID cu_seq[MAX_CU_LAYERS]; // preferred sequence, could have called CuStack()
// but I assume that's backwards
glNewList( aBoardList, GL_COMPILE );
for( unsigned i=0; i < DIM( cu_seq ); ++i )
cu_seq[i] = ToLAYER_ID( B_Cu - i );
for( LSEQ cu = cu_set.Seq( cu_seq, DIM(cu_seq) ); cu; ++cu )
#else
for( LSEQ cu = cu_set.CuStack(); cu; ++cu )
#endif
{
LAYER_ID layer = *cu;
@ -283,6 +269,9 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
}
}
if( !throughHolesListBuilt )
allLayerHoles.Simplify();
// bufferPolys contains polygons to merge. Many overlaps .
// Calculate merged polygons
if( bufferPolys.IsEmpty() )
@ -290,12 +279,10 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
// Use Clipper lib to subtract holes to copper areas
bufferPolys.Simplify();
currLayerHoles.Append(allLayerHoles);
currLayerHoles.Simplify();
allLayerHoles.Simplify();
bufferPolys.BooleanSubtract( allLayerHoles );
bufferPolys.Fracture();
bufferPolys.BooleanSubtract( currLayerHoles );
int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
@ -339,7 +326,6 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
if( aActivity )
aActivity->Report( _( "Build board body" ) );
// Draw plated vertical holes inside the board, but not always. They are drawn:
// - if the board body is not shown, to show the holes.
// - or if the copper thickness is shown
@ -396,7 +382,6 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
board_thickness -= copper_thickness + epsilon;
bufferPcbOutlines.BooleanSubtract( allLayerHoles );
bufferPcbOutlines.Fracture();
if( !bufferPcbOutlines.IsEmpty() )
{
@ -469,6 +454,8 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
segcountLowQuality );
}
allLayerHoles.Simplify();
// draw graphic items, on technical layers
static const LAYER_ID teckLayerList[] = {
@ -496,7 +483,6 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
if( aActivity )
aActivity->Report( wxString::Format( _( "Build layer %s" ), LSET::Name( layer ) ) );
bufferPolys.RemoveAllContours();
for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() )
@ -565,8 +551,6 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
if( bufferPolys.IsEmpty() )
continue;
allLayerHoles.Simplify();
// Solder mask layers are "negative" layers.
// Shapes should be removed from the full board area.
if( layer == B_Mask || layer == F_Mask )
@ -586,10 +570,6 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
bufferPolys.BooleanSubtract( allLayerHoles );
}
// Convert each polygon with holes to
// a polygon with its holes linked to the main outline
bufferPolys.Fracture();
int thickness = 0;
if( layer != B_Mask && layer != F_Mask )

View File

@ -644,7 +644,7 @@ void EDA_3D_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MENU3D_SOLDER_PASTE_ONOFF:
GetPrm3DVisu().SetFlag( FL_SOLDERPASTE, isChecked );
NewDisplay();
NewDisplay( GL_ID_TECH_LAYERS );
return;
case ID_MENU3D_COMMENTS_ONOFF:

View File

@ -206,7 +206,8 @@ const SHAPE_LINE_CHAIN SHAPE_POLY_SET::convertFromClipper( const Path& aPath )
return lc;
}
#include <common.h>
#include <wx/wx.h>
void SHAPE_POLY_SET::booleanOp( ClipType type, const SHAPE_POLY_SET& b )
{
Clipper c;
@ -497,7 +498,7 @@ void SHAPE_POLY_SET::fractureSingle( POLYGON& paths )
void SHAPE_POLY_SET::Fracture()
{
Simplify(); // remove overlallping holes/degeneracy
Simplify(); // remove overlapping holes/degeneracy
BOOST_FOREACH( POLYGON& paths, m_polys )
{