Commit d40ea8ad authored by unknown's avatar unknown Committed by jean-pierre charras
Browse files

3D viewer: fix issues with transparencies in some models (material issues in VRML2 parser)

Fix some issues in filling zones normals.
Fix an issue with some models that have materials but didn't defined the diffuse color.
Workaround for Bug #1443431.
Implement some missing "code logic" for pervertexperface normals.
Remove some not used functions.
Calculate normals using double type.
parent b85ed89e
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -95,7 +95,7 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
    m_ZBottom = 0.0;
    m_ZBottom = 0.0;
    m_ZTop = 0.0;
    m_ZTop = 0.0;


    m_lightPos = S3D_VERTEX(0.0f, 0.0f, 50.0f);
    m_lightPos = S3D_VERTEX(0.0f, 0.0f, 30.0f);


    // Clear all gl list identifiers:
    // Clear all gl list identifiers:
    for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
    for( int ii = GL_ID_BEGIN; ii < GL_ID_END; ii++ )
@@ -591,7 +591,7 @@ void EDA_3D_CANVAS::SetLights()
    light_color[3] = 1.0;
    light_color[3] = 1.0;


    // Light above the xy plane
    // Light above the xy plane
    light_color[0] = light_color[1] = light_color[2] = 0.2;
    light_color[0] = light_color[1] = light_color[2] = 0.0;
    glLightfv( GL_LIGHT0, GL_AMBIENT, light_color );
    glLightfv( GL_LIGHT0, GL_AMBIENT, light_color );


    light_color[0] = light_color[1] = light_color[2] = 1.0;
    light_color[0] = light_color[1] = light_color[2] = 1.0;
@@ -605,6 +605,8 @@ void EDA_3D_CANVAS::SetLights()
    light_color[0] = light_color[1] = light_color[2] = 0.2;
    light_color[0] = light_color[1] = light_color[2] = 0.2;
    glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color );
    glLightModelfv( GL_LIGHT_MODEL_AMBIENT, light_color );


    glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );

    glEnable( GL_LIGHT0 );      // White spot on Z axis ( top )
    glEnable( GL_LIGHT0 );      // White spot on Z axis ( top )
    glEnable( GL_LIGHTING );
    glEnable( GL_LIGHTING );
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -85,7 +85,7 @@ S3D_MASTER:: ~S3D_MASTER()
    {
    {
        nextmat = m_Materials->Next();
        nextmat = m_Materials->Next();
        delete m_Materials;
        delete m_Materials;
        m_Materials = 0;
        m_Materials = NULL;
    }
    }
}
}


+37 −10
Original line number Original line Diff line number Diff line
@@ -446,6 +446,8 @@ void EDA_3D_CANVAS::Redraw()
    glEnable( GL_COLOR_MATERIAL );
    glEnable( GL_COLOR_MATERIAL );
    SetOpenGlDefaultMaterial();
    SetOpenGlDefaultMaterial();


    //glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, FALSE );

    // Board Body
    // Board Body


    GLint shininess_value = 32;
    GLint shininess_value = 32;
@@ -497,6 +499,7 @@ void EDA_3D_CANVAS::Redraw()
        glCallList( m_glLists[GL_ID_AUX_LAYERS] );
        glCallList( m_glLists[GL_ID_AUX_LAYERS] );
    }
    }


    //glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, TRUE );


    // Draw Component Shadow
    // Draw Component Shadow


@@ -583,6 +586,7 @@ void EDA_3D_CANVAS::Redraw()
    // non transparent objects
    // non transparent objects
    if(  isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] )
    if(  isEnabled( FL_MODULE ) && m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] )
    {
    {
        glEnable( GL_COLOR_MATERIAL );
        glEnable( GL_BLEND );
        glEnable( GL_BLEND );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] );
        glCallList( m_glLists[GL_ID_3DSHAPES_TRANSP_FRONT] );
@@ -926,6 +930,14 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
        int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
        int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
        int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
        int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
        
        
        float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted)

        // If we are not using thickness, then the znormal must face the layer direction
        // because it will draw just one plane
        if( !thickness )
            zNormal = Get3DLayer_Z_Orientation( layer );


        if( realistic_mode )
        if( realistic_mode )
        {
        {
            setGLCopperColor();
            setGLCopperColor();
@@ -941,17 +953,17 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,


        // If holes are removed from copper zones, bufferPolys contains all polygons
        // If holes are removed from copper zones, bufferPolys contains all polygons
        // to draw (tracks+zones+texts).
        // to draw (tracks+zones+texts).
        glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness,
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness,
                                            GetPrm3DVisu().m_BiuTo3Dunits, useTextures );
                                            GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
                                            zNormal );


        // If holes are not removed from copper zones (for calculation time reasons,
        // If holes are not removed from copper zones (for calculation time reasons,
        // the zone polygons are stored in bufferZonesPolys and have to be drawn now:
        // the zone polygons are stored in bufferZonesPolys and have to be drawn now:
        if( bufferZonesPolys.GetCornersCount() )
        if( bufferZonesPolys.GetCornersCount() )
        {
        {
            glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
            Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos, thickness,
            Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos, thickness,
                                    GetPrm3DVisu().m_BiuTo3Dunits, useTextures );
                                    GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
                                    zNormal );
        }
        }


        throughHolesListBuilt = true;
        throughHolesListBuilt = true;
@@ -1016,7 +1028,6 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
    zpos += (copper_thickness + epsilon) / 2.0f;
    zpos += (copper_thickness + epsilon) / 2.0f;
    board_thickness -= copper_thickness + epsilon;
    board_thickness -= copper_thickness + epsilon;


    glNormal3f( 0.0f, 0.0f, Get3DLayer_Z_Orientation( F_Cu ) );
    KI_POLYGON_SET  currLayerPolyset;
    KI_POLYGON_SET  currLayerPolyset;
    KI_POLYGON_SET  polysetHoles;
    KI_POLYGON_SET  polysetHoles;


@@ -1035,7 +1046,8 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
    if( bufferPcbOutlines.GetCornersCount() )
    if( bufferPcbOutlines.GetCornersCount() )
    {
    {
        Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0,
        Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0,
                                            board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures );
                                            board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
                                            1.0f );
    }
    }


    glEndList();
    glEndList();
@@ -1256,10 +1268,18 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
        bufferPolys.RemoveAllContours();
        bufferPolys.RemoveAllContours();
        bufferPolys.ImportFrom( currLayerPolyset );
        bufferPolys.ImportFrom( currLayerPolyset );


        float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted)

        // If we are not using thickness, then the znormal must face the layer direction
        // because it will draw just one plane
        if( !thickness )
            zNormal = Get3DLayer_Z_Orientation( layer );


        setGLTechLayersColor( layer );
        setGLTechLayersColor( layer );
        glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
                thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures );
                thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures,
                zNormal );
    }
    }
}
}


@@ -1361,10 +1381,17 @@ void EDA_3D_CANVAS::buildBoard3DAuxLayers( REPORTER* aErrorMessages, REPORTER* a
        bufferPolys.RemoveAllContours();
        bufferPolys.RemoveAllContours();
        bufferPolys.ImportFrom( currLayerPolyset );
        bufferPolys.ImportFrom( currLayerPolyset );


        float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted)

        // If we are not using thickness, then the znormal must face the layer direction
        // because it will draw just one plane
        if( !thickness )
            zNormal = Get3DLayer_Z_Orientation( layer );

        setGLTechLayersColor( layer );
        setGLTechLayersColor( layer );
        glNormal3f( 0.0, 0.0, Get3DLayer_Z_Orientation( layer ) );
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
        Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos,
                                            thickness, GetPrm3DVisu().m_BiuTo3Dunits, false );
                                            thickness, GetPrm3DVisu().m_BiuTo3Dunits, false,
                                            zNormal );
    }
    }
}
}


+25 −42
Original line number Original line Diff line number Diff line
@@ -54,17 +54,6 @@ static void CALLBACK tessEndCB();
static void CALLBACK    tessErrorCB( GLenum errorCode );
static void CALLBACK    tessErrorCB( GLenum errorCode );
static void CALLBACK    tessCPolyPt2Vertex( const GLvoid* data );
static void CALLBACK    tessCPolyPt2Vertex( const GLvoid* data );


// 2 helper functions to set the current normal vector for gle items
static inline void SetNormalZpos()
{
    glNormal3f( 0.0, 0.0, 1.0 );
}

static inline void SetNormalZneg()
{
    glNormal3f( 0.0, 0.0, -1.0 );
}

void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits );
void TransfertToGLlist( std::vector< S3D_VERTEX >& aVertices, double aBiuTo3DUnits );


/* Draw3D_VerticalPolygonalCylinder is a helper function.
/* Draw3D_VerticalPolygonalCylinder is a helper function.
@@ -160,7 +149,8 @@ void SetGLTexture( GLuint text_id, float scale )
 */
 */
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
                                         int aZpos, int aThickness, double aBiuTo3DUnits,
                                         int aZpos, int aThickness, double aBiuTo3DUnits,
                                         bool aUseTextures )
                                         bool aUseTextures,
                                         float aNormal_Z_Orientation )
{
{
    // for Tess callback functions:
    // for Tess callback functions:
    s_biuTo3Dunits = aBiuTo3DUnits;
    s_biuTo3Dunits = aBiuTo3DUnits;
@@ -176,14 +166,15 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
    GLdouble v_data[3];
    GLdouble v_data[3];
    double   zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
    double   zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
    s_currentZpos = zpos;     // for Tess callback functions
    s_currentZpos = zpos;     // for Tess callback functions
    v_data[2] = aZpos + (aThickness / 2.0);
    v_data[2]     = zpos;


    // Set normal toward positive Z axis, for a solid object on the top side
    // Set normal toward positive Z axis, for a solid object on the top side
    if( aThickness )
        SetNormalZpos();


    //gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE );
    //gluTessProperty( tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD );
    //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
    // Draw solid areas contained in this list
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex


@@ -202,11 +193,6 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
                startContour = 0;
                startContour = 0;
            }
            }


            // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
            if( !aThickness )
                gluTessNormal( tess, 0.0, 0.0, 0.0 );


            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * aBiuTo3DUnits;
            // gluTessVertex store pointers on data, not data, so do not store
            // gluTessVertex store pointers on data, not data, so do not store
@@ -231,9 +217,8 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        s_currentZpos = zpos;     // for Tess callback functions
        s_currentZpos = zpos;     // for Tess callback functions
        v_data[2] = zpos;
        v_data[2] = zpos;
        // Set normal toward negative Z axis, for a solid object on bottom side

        if( aThickness )
        glNormal3f( 0.0, 0.0, -aNormal_Z_Orientation );
            SetNormalZneg();
    }
    }


    if( startContour == 0 )
    if( startContour == 0 )
@@ -259,12 +244,14 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
 */
 */
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
void Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
                                             int aZpos, int aThickness,
                                             int aZpos, int aThickness,
                                             double aBiuTo3DUnits, bool aUseTextures )
                                             double aBiuTo3DUnits, bool aUseTextures,
                                             float aNormal_Z_Orientation )
{
{
    CPOLYGONS_LIST polygon;
    CPOLYGONS_LIST polygon;


    ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon );
    ConvertPolysListWithHolesToOnePolygon( aPolysList, polygon );
    Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures );
    Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, aThickness, aBiuTo3DUnits, aUseTextures,
                                        aNormal_Z_Orientation );
}
}




@@ -307,23 +294,21 @@ void Draw3D_ZaxisCylinder( wxPoint aCenterPos, int aRadius,
    if( aThickness )
    if( aThickness )
    {
    {
        // draw top (front) and bottom (back) horizontal sides (rings)
        // draw top (front) and bottom (back) horizontal sides (rings)
        SetNormalZpos();
        outer_cornerBuffer.Append( inner_cornerBuffer );
        outer_cornerBuffer.Append( inner_cornerBuffer );
        CPOLYGONS_LIST polygon;
        CPOLYGONS_LIST polygon;


        ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
        ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
        // draw top (front) horizontal ring
        // draw top (front) horizontal ring
        Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false );
        Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false,
                                            1.0f );


        if( aHeight )
        if( aHeight )
        {
        {
            // draw bottom (back) horizontal ring
            // draw bottom (back) horizontal ring
            SetNormalZneg();
            Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false,
            Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false );
                                                -1.0f );
        }
        }
    }
    }

    SetNormalZpos();
}
}




@@ -372,18 +357,16 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos,
        ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );
        ConvertPolysListWithHolesToOnePolygon( outer_cornerBuffer, polygon );


        // draw top (front) horizontal side (ring)
        // draw top (front) horizontal side (ring)
        SetNormalZpos();
        Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false,
        Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos + aHeight, 0, aBiuTo3DUnits, false );
                                            1.0f );


        if( aHeight )
        if( aHeight )
        {
        {
            // draw bottom (back) horizontal side (ring)
            // draw bottom (back) horizontal side (ring)
            SetNormalZneg();
            Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false,
            Draw3D_SolidHorizontalPolyPolygons( polygon, aZpos, 0, aBiuTo3DUnits, false );
                                                -1.0f );
        }
        }
    }
    }

    SetNormalZpos();
}
}




@@ -401,7 +384,7 @@ void Draw3D_SolidSegment( const wxPoint& aStart, const wxPoint& aEnd,


    TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth );
    TransformRoundedEndsSegmentToPolygon( cornerBuffer, aStart, aEnd, slice, aWidth );


    Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false );
    Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f );
}
}




@@ -415,7 +398,7 @@ void Draw3D_ArcSegment( const wxPoint& aCenterPos, const wxPoint& aStartPoint,
    TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle,
    TransformArcToPolygon( cornerBuffer, aCenterPos, aStartPoint, aArcAngle,
                           slice, aWidth );
                           slice, aWidth );


    Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false );
    Draw3D_SolidHorizontalPolyPolygons( cornerBuffer, aZpos, aThickness, aBiuTo3DUnits, false, 1.0f );
}
}




+6 −2
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
 * @param aThickness = thickness in board internal units
 * @param aThickness = thickness in board internal units
 * @param aBiuTo3DUnits = board internal units to 3D units scaling value
 * @param aBiuTo3DUnits = board internal units to 3D units scaling value
 * @param aUseTextures = true to use textxures for the polygons
 * @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 polygon area is drawn in a XY plane at Z position = aZpos.
 * If aThickness > 0, a solid object is drawn.
 * If aThickness > 0, a solid object is drawn.
 *  The top side is located at aZpos + aThickness / 2
 *  The top side is located at aZpos + aThickness / 2
@@ -44,7 +45,8 @@
 */
 */
void    Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
void    Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
                                            int aZpos, int aThickness, double aBiuTo3DUnits,
                                            int aZpos, int aThickness, double aBiuTo3DUnits,
                                            bool aUseTextures );
                                            bool aUseTextures,
                                            float aNormal_Z_Orientation );


/** draw the solid polygon found in aPolysList
/** draw the solid polygon found in aPolysList
 * The first polygonj is the main polygon, others are holes
 * The first polygonj is the main polygon, others are holes
@@ -53,6 +55,7 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
 * @param aThickness = thickness in board internal units
 * @param aThickness = thickness in board internal units
 * @param aBiuTo3DUnits = board internal units to 3D units scaling value
 * @param aBiuTo3DUnits = board internal units to 3D units scaling value
 * @param aUseTextures = true to use textxures for the polygons
 * @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 polygon area is drawn in a XY plane at Z position = aZpos.
 * If aThickness > 0, a solid object is drawn.
 * If aThickness > 0, a solid object is drawn.
 *  The top side is located at aZpos + aThickness / 2
 *  The top side is located at aZpos + aThickness / 2
@@ -60,7 +63,8 @@ void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
 */
 */
void    Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
void    Draw3D_SolidHorizontalPolygonWithHoles( const CPOLYGONS_LIST& aPolysList,
                                                int aZpos, int aThickness, double aBiuTo3DUnits,
                                                int aZpos, int aThickness, double aBiuTo3DUnits,
                                                bool aUseTextures );
                                                bool aUseTextures,
                                                float aNormal_Z_Orientation );


/** draw a thick segment using 3D primitives, in a XY plane
/** draw a thick segment using 3D primitives, in a XY plane
 * @param aStart = YX position of start point in board units
 * @param aStart = YX position of start point in board units
Loading