/* Draw3D_VerticalPolygonalCylinder is a helper function.
 *
 * draws a "vertical cylinder" having a polygon shape
 * from Z position = aZpos to aZpos + aHeight
 * Used to create the vertical sides of 3D horizontal shapes with thickness.
 */
static void Draw3D_VerticalPolygonalCylinder( const CPOLYGONS_LIST& aPolysList,
        int aHeight, int aZpos,
        bool aInside, double aBiuTo3DUnits )
{
    if( aHeight == 0 )
        return;

    std::vector<S3D_VERTEX> coords;
    coords.resize( 4 );

    // Init Z position of the 4 points of a GL_QUAD
    if( aInside )
    {
        coords[0].z = aZpos;
        coords[1].z = aZpos + aHeight;
    }
    else
    {
        coords[0].z = aZpos + aHeight;
        coords[1].z = aZpos;
    }
    coords[2].z = coords[1].z;
    coords[3].z = coords[0].z;

    // Draw the vertical polygonal side
    int startContour = 0;
    for( unsigned ii = 0; ii < aPolysList.GetCornersCount(); ii++ )
    {
        unsigned jj = ii + 1;

        if( aPolysList.IsEndContour( ii ) || jj >= aPolysList.GetCornersCount() )
        {
            jj = startContour;
            startContour = ii + 1;
        }

        // Build the 4 vertices of each GL_QUAD
        coords[0].x = aPolysList.GetX( ii );
        coords[0].y = -aPolysList.GetY( ii );
        coords[1].x = coords[0].x;
        coords[1].y = coords[0].y;              // only z change
        coords[2].x = aPolysList.GetX( jj );
        coords[2].y = -aPolysList.GetY( jj );
        coords[3].x = coords[2].x;
        coords[3].y = coords[2].y;              // only z change

        // Creates the GL_QUAD
        TransfertToGLlist( coords, aBiuTo3DUnits );
    }
}
Example #2
0
const SHAPE_POLY_SET ConvertPolyListToPolySet( const CPOLYGONS_LIST& aList )
{
    SHAPE_POLY_SET rv;

    unsigned corners_count = aList.GetCornersCount();

    // Enter main outline: this is the first contour
    unsigned ic = 0;

    if( !corners_count )
        return rv;

    int index = 0;

    while( ic < corners_count )
    {
        int hole = -1;

        if( index == 0 )
        {
            rv.NewOutline();
            hole = -1;
        }
        else
        {
            hole = rv.NewHole();
        }

        while( ic < corners_count )
        {
            rv.Append( aList.GetX( ic ), aList.GetY( ic ), 0, hole );

            if( aList.IsEndContour( ic ) )
                break;

            ic++;
        }
        ic++;

        index++;
    }

    return rv;
}
/* 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 > 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 CPOLYGONS_LIST& aPolysList,
        int aZpos, int aThickness, double aBiuTo3DUnits,
        bool aUseTextures )
{
    // for Tess callback functions:
    s_biuTo3Dunits = aBiuTo3DUnits;
    s_useTextures = aUseTextures;

    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.0) ) * aBiuTo3DUnits;
    s_currentZpos = zpos;     // for Tess callback functions
    v_data[2] = aZpos + (aThickness / 2.0);

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

    // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

    // Draw solid areas contained in this list
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex

    int startContour;

    for( int side = 0; side < 2; side++ )
    {
        startContour = 1;

        for( unsigned ii = 0; ii < polylist.GetCornersCount(); ii++ )
        {
            if( startContour == 1 )
            {
                gluTessBeginPolygon( tess, NULL );
                gluTessBeginContour( tess );
                startContour = 0;
            }

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


            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * 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.IsEndContour( ii ) )
            {
                gluTessEndContour( tess );
                gluTessEndPolygon( tess );
                startContour = 1;
            }
        }

        if( aThickness == 0 )
            break;

        // Prepare the bottom side of solid areas
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        s_currentZpos = zpos;     // for Tess callback functions
        v_data[2] = zpos;
        // Set normal toward negative Z axis, for a solid object on bottom side
        SetNormalZneg();
    }

    if( startContour == 0 )
    {
        gluTessEndContour( tess );
        gluTessEndPolygon( tess );
    }

    gluDeleteTess( tess );

    if( aThickness == 0 )
    {
        return;
    }

    // Build the 3D data : vertical side
    Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), false, aBiuTo3DUnits );
}