bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName,
        double aMMtoWRMLunit, bool aExport3DFiles,
        const wxString& a3D_Subdir )
{
    wxString        msg;
    BOARD*          pcb = GetBoard();
    bool            ok  = true;

    MODEL_VRML model3d;

    model_vrml = &model3d;
    std::ofstream output_file;

    try
    {
        output_file.exceptions( std::ofstream::failbit );
        output_file.open( TO_UTF8( aFullFileName ), std::ios_base::out );

        // Switch the locale to standard C (needed to print floating point numbers like 1.3)
        SetLocaleTo_C_standard();

        // Begin with the usual VRML boilerplate
        wxString name = aFullFileName;

        name.Replace( wxT( "\\" ), wxT( "/" ) );
        ChangeIllegalCharacters( name, false );

        output_file << "#VRML V2.0 utf8\n";
        output_file << "WorldInfo {\n";
        output_file << "  title \"" << TO_UTF8( name ) << " - Generated by Pcbnew\"\n";
        output_file << "}\n";

        // Set the VRML world scale factor
        model3d.SetScale( aMMtoWRMLunit );

        output_file << "Transform {\n";

        // compute the offset to center the board on (0, 0, 0)
        // XXX - NOTE: we should allow the user a GUI option to specify the offset
        EDA_RECT bbbox = pcb->ComputeBoundingBox();

        model3d.SetOffset( -model3d.scale * bbbox.Centre().x,
                           model3d.scale * bbbox.Centre().y );

        output_file << "  children [\n";

        // Preliminary computation: the z value for each layer
        compute_layer_Zs( model3d, pcb );

        // board edges and cutouts
        export_vrml_board( model3d, pcb );

        // Drawing and text on the board
        export_vrml_drawings( model3d, pcb );

        // Export vias and trackage
        export_vrml_tracks( model3d, pcb );

        // Export zone fills
        export_vrml_zones( model3d, pcb);

        /* scaling factor to convert 3D models to board units (decimils)
         * Usually we use Wings3D to create thems.
         * One can consider the 3D units is 0.1 inch (2.54 mm)
         * So the scaling factor from 0.1 inch to board units
         * is 2.54 * aMMtoWRMLunit
         */
        double wrml_3D_models_scaling_factor = 2.54 * aMMtoWRMLunit;

        // Export footprints
        for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() )
            export_vrml_module( model3d, pcb, module, output_file,
                                wrml_3D_models_scaling_factor,
                                aExport3DFiles, a3D_Subdir );

            // write out the board and all layers
            write_layers( model3d, output_file, pcb );

        // Close the outer 'transform' node
        output_file << "]\n}\n";
    }
    catch( const std::exception& e )
    {
        wxString msg;
        msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( e.what() );
        wxMessageBox( msg );

        ok = false;
    }

    // End of work
    output_file.exceptions( std::ios_base::goodbit );
    output_file.close();
    SetLocaleTo_Default();       // revert to the current  locale

    return ok;
}
/* Note1:
 * When copying 3D shapes files, the new filename is build from
 * the full path name, changing the separators by underscore.
 * this is needed because files with the same shortname can exist in different directories
 * Note 2:
 * ExportVRML_File generates coordinates in board units (BIU) inside the file.
 * (TODO: use mm inside the file)
 * A general scale transform is applied to the whole file
 * (1.0 to have the actual WRML unit im mm, 0.001 to have the actual WRML unit im meter
 * Note 3:
 * For 3D models built by a 3D modeler, the unit is 0,1 inch
 * A specfic scale is applied to 3D models to convert them to BIU
 *
 */
bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName,
                                      double aMMtoWRMLunit, bool aExport3DFiles,
                                      const wxString & a3D_Subdir )
{
    wxString   msg;
    FILE*      output_file;
    BOARD*     pcb = GetBoard();

    output_file = wxFopen( aFullFileName, wxT( "wt" ) );
    if( output_file == NULL )
        return false;

    // Switch the locale to standard C (needed to print floating point numbers like 1.3)
    SetLocaleTo_C_standard();

    // Begin with the usual VRML boilerplate
    wxString name = aFullFileName;

    name.Replace(wxT("\\"), wxT("/" ) );
    ChangeIllegalCharacters( name, false );
    fprintf( output_file, "#VRML V2.0 utf8\n"
                          "WorldInfo {\n"
                          "  title \"%s - Generated by Pcbnew\"\n"
                          "}\n", TO_UTF8( name ) );

    /* The would be in BIU and not in meters, as the standard wants.
     * It is trivial to embed everything in a transform node to
     * fix it. For example here we build the world in inches...
    */

    // Global VRML scale to export to a different scale.
    // (aMMtoWRMLScale = 1.0 to export in mm)
    double boardIU2WRML = aMMtoWRMLunit / MM_PER_IU;
    fprintf( output_file, "Transform {\n" );

    /* Define the translation to have the board centre to the 2D axis origin
     * more easy for rotations...
     */
    EDA_RECT bbbox = pcb->ComputeBoundingBox();

    double dx = boardIU2WRML * bbbox.Centre().x;
    double dy = boardIU2WRML * bbbox.Centre().y;

    fprintf( output_file, "  translation %g %g 0.0\n", -dx, dy );
    fprintf( output_file, "  children [\n" );

    // Preliminary computation: the z value for each layer
    compute_layer_Zs( pcb );

    // Drawing and text on the board, and edges which are special
    export_vrml_drawings( pcb );

    // Export vias and trackage
    export_vrml_tracks( pcb );

    // Export zone fills
/* TODO    export_vrml_zones(pcb);
*/

    /* scaling factor to convert 3D models to board units (decimils)
     * Usually we use Wings3D to create thems.
     * One can consider the 3D units is 0.1 inch (2.54 mm)
     * So the scaling factor from 0.1 inch to board units
     * is 2.54 * aMMtoWRMLunit
     */
    double wrml_3D_models_scaling_factor = 2.54 * aMMtoWRMLunit;
    // Export footprints
    for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() )
        export_vrml_module( pcb, module, output_file,
                            wrml_3D_models_scaling_factor,
                            aExport3DFiles, a3D_Subdir,
                            boardIU2WRML );

    /* Output the bagged triangles for each layer
     * Each layer will be a separate shape */
    for( int layer = 0; layer < LAYER_COUNT; layer++ )
        write_and_empty_triangle_bag( output_file,
                                      layer_triangles[layer],
                                      pcb->GetLayerColor(layer),
                                      boardIU2WRML );

    // Same thing for the via layers
    for( int i = 0; i < 4; i++ )
        write_and_empty_triangle_bag( output_file,
                                      via_triangles[i],
                                      pcb->GetVisibleElementColor( VIAS_VISIBLE + i ),
                                      boardIU2WRML );

    // Close the outer 'transform' node
    fputs( "]\n}\n", output_file );

    // End of work
    fclose( output_file );
    SetLocaleTo_Default();       // revert to the current  locale

    return true;
}