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; }