Commit 5c2efcbf authored by jean-pierre charras's avatar jean-pierre charras

3D viewer: allows import of models created with openscad and convertedvia...

3D viewer: allows  import of models created with openscad and convertedvia meshconv to wrl (thanks to Georg Gast <georg@schorsch-tech.de>)
Export VRML: fix scaling issue for pcbnew - nanometers.
parent 0fedf6b3
...@@ -93,7 +93,7 @@ int S3D_MASTER::ReadData() ...@@ -93,7 +93,7 @@ int S3D_MASTER::ReadData()
{ {
text = strtok( line, sep_chars ); text = strtok( line, sep_chars );
if( stricmp( text, "DEF" ) == 0 ) if( stricmp( text, "DEF" ) == 0 || stricmp( text, "Group" ) == 0)
{ {
while( GetLine( file, line, &LineNum, 512 ) ) while( GetLine( file, line, &LineNum, 512 ) )
{ {
...@@ -144,7 +144,7 @@ int S3D_MASTER::ReadMaterial( FILE* file, int* LineNum ) ...@@ -144,7 +144,7 @@ int S3D_MASTER::ReadMaterial( FILE* file, int* LineNum )
return 0; return 0;
} }
if( stricmp( command, "DEF" ) == 0 ) if( stricmp( command, "DEF" ) == 0 || stricmp( command, "Material") == 0)
{ {
material = new S3D_MATERIAL( this, mat_name ); material = new S3D_MATERIAL( this, mat_name );
...@@ -478,6 +478,12 @@ int S3D_MASTER::ReadGeometry( FILE* file, int* LineNum ) ...@@ -478,6 +478,12 @@ int S3D_MASTER::ReadGeometry( FILE* file, int* LineNum )
continue; continue;
} }
if( stricmp( text, "solid" ) == 0 )
{
// ignore solid
continue;
}
if( stricmp( text, "colorIndex" ) == 0 ) if( stricmp( text, "colorIndex" ) == 0 )
{ {
while( GetLine( file, line, LineNum, 512 ) ) while( GetLine( file, line, LineNum, 512 ) )
......
...@@ -96,6 +96,52 @@ public: ...@@ -96,6 +96,52 @@ public:
} }
}; };
/**
* Function OnExportVRML
* will export the current BOARD to a VRML file.
*/
void PCB_EDIT_FRAME::OnExportVRML( wxCommandEvent& event )
{
wxFileName fn;
static wxString subDirFor3Dshapes = wxT("shapes3D");
// The general VRML scale factor
// Assuming the VRML default unit is the mm
// this is the mm to VRML scaling factor for inch, mm and meter
double scaleList[3] = { 1.0/25.4, 1, 0.001 };
// Build default file name
wxString ext = wxT( "wrl" );
fn = GetBoard()->GetFileName();
fn.SetExt( ext );
DIALOG_EXPORT_3DFILE dlg( this );
dlg.FilePicker()->SetPath( fn.GetFullPath() );
dlg.SetSubdir( subDirFor3Dshapes );
if( dlg.ShowModal() != wxID_OK )
return;
double scale = scaleList[dlg.GetUnits( )]; // final scale export
bool export3DFiles = dlg.Get3DFilesOption( ) == 0;
wxBusyCursor dummy;
wxString fullFilename = dlg.FilePicker()->GetPath();
subDirFor3Dshapes = dlg.GetSubdir();
if( ! wxDirExists( subDirFor3Dshapes ) )
wxMkdir( subDirFor3Dshapes );
if( ! ExportVRML_File( fullFilename, scale, export3DFiles, subDirFor3Dshapes ) )
{
wxString msg = _( "Unable to create " ) + fullFilename;
wxMessageBox( msg );
return;
}
}
// I use this a lot... // I use this a lot...
static const double PI2 = M_PI / 2; static const double PI2 = M_PI / 2;
...@@ -1050,7 +1096,8 @@ static void compose_quat( double q1[4], double q2[4], double qr[4] ) ...@@ -1050,7 +1096,8 @@ static void compose_quat( double q1[4], double q2[4], double qr[4] )
static void export_vrml_module( BOARD* aPcb, MODULE* aModule, static void export_vrml_module( BOARD* aPcb, MODULE* aModule,
FILE* aOutputFile, double aScalingFactor, FILE* aOutputFile,
double aVRMLModelsToBiu,
bool aExport3DFiles, const wxString & a3D_Subdir ) bool aExport3DFiles, const wxString & a3D_Subdir )
{ {
// Reference and value // Reference and value
...@@ -1146,16 +1193,10 @@ static void export_vrml_module( BOARD* aPcb, MODULE* aModule, ...@@ -1146,16 +1193,10 @@ static void export_vrml_module( BOARD* aPcb, MODULE* aModule,
fprintf( aOutputFile, " rotation %g %g %g %g\n", rot[0], rot[1], rot[2], rot[3] ); fprintf( aOutputFile, " rotation %g %g %g %g\n", rot[0], rot[1], rot[2], rot[3] );
} }
fprintf( aOutputFile, " scale %g %g %g\n", // adjust 3D shape offset position
vrmlm->m_MatScale.x * aScalingFactor, int offsetx = vrmlm->m_MatPosition.x;
vrmlm->m_MatScale.y * aScalingFactor, int offsety = vrmlm->m_MatPosition.y;
vrmlm->m_MatScale.z * aScalingFactor ); double offsetz = vrmlm->m_MatPosition.z;
// adjust 3D shape offset position (offset is given in inch)
#define UNITS_3D_TO_PCB_UNITS (IU_PER_MILS*1000)
int offsetx = KiROUND( vrmlm->m_MatPosition.x * UNITS_3D_TO_PCB_UNITS );
int offsety = KiROUND( vrmlm->m_MatPosition.y * UNITS_3D_TO_PCB_UNITS );
double offsetz = vrmlm->m_MatPosition.z * UNITS_3D_TO_PCB_UNITS;
if ( isFlipped ) if ( isFlipped )
NEGATE(offsetz); NEGATE(offsetz);
...@@ -1168,6 +1209,12 @@ static void export_vrml_module( BOARD* aPcb, MODULE* aModule, ...@@ -1168,6 +1209,12 @@ static void export_vrml_module( BOARD* aPcb, MODULE* aModule,
(double) (offsetx + aModule->m_Pos.x), (double) (offsetx + aModule->m_Pos.x),
- (double)(offsety + aModule->m_Pos.y), // Y axis is reversed in Pcbnew - (double)(offsety + aModule->m_Pos.y), // Y axis is reversed in Pcbnew
offsetz + layer_z[aModule->GetLayer()] ); offsetz + layer_z[aModule->GetLayer()] );
fprintf( aOutputFile, " scale %g %g %g\n",
vrmlm->m_MatScale.x * aVRMLModelsToBiu,
vrmlm->m_MatScale.y * aVRMLModelsToBiu,
vrmlm->m_MatScale.z * aVRMLModelsToBiu );
fprintf( aOutputFile, fprintf( aOutputFile,
" children [\n Inline {\n url \"%s\"\n } ]\n", " children [\n Inline {\n url \"%s\"\n } ]\n",
TO_UTF8( fname ) ); TO_UTF8( fname ) );
...@@ -1185,64 +1232,32 @@ static void write_and_empty_triangle_bag( FILE* output_file, TriangleBag& triang ...@@ -1185,64 +1232,32 @@ static void write_and_empty_triangle_bag( FILE* output_file, TriangleBag& triang
} }
} }
/**
* Function OnExportVRML
* will export the current BOARD to a VRML file.
*/
void PCB_EDIT_FRAME::OnExportVRML( wxCommandEvent& event )
{
wxFileName fn;
static wxString subDirFor3Dshapes = wxT("shapes3D");
double scaleList[3] = { 1.0, 25.4, 25.4/1000 };
// Build default file name
wxString ext = wxT( "wrl" );
fn = GetBoard()->GetFileName();
fn.SetExt( ext );
DIALOG_EXPORT_3DFILE dlg( this );
dlg.FilePicker()->SetPath( fn.GetFullPath() );
dlg.SetSubdir( subDirFor3Dshapes );
if( dlg.ShowModal() != wxID_OK )
return;
double scale = scaleList[dlg.GetUnits( )]; // final scale export
bool export3DFiles = dlg.Get3DFilesOption( ) == 0;
wxBusyCursor dummy;
wxString fullFilename = dlg.FilePicker()->GetPath();
subDirFor3Dshapes = dlg.GetSubdir();
if( ! wxDirExists( subDirFor3Dshapes ) )
wxMkdir( subDirFor3Dshapes );
if( ! ExportVRML_File( fullFilename, scale, export3DFiles, subDirFor3Dshapes ) )
{
wxString msg = _( "Unable to create " ) + fullFilename;
wxMessageBox( msg );
return;
}
}
/** /**
* Function ExportVRML_File * Function ExportVRML_File
* Creates the file(s) exporting current BOARD to a VRML file. * Creates the file(s) exporting current BOARD to a VRML file.
* @param aFullFileName = the full filename of the file to create * @param aFullFileName = the full filename of the file to create
* @param aScale = the general scaling factor. 1.0 to export in inch * @param aMMtoWRMLunit = the general scaling factor. 1.0 to export in mm
* @param aExport3DFiles = true to copy 3D shapes in the subdir a3D_Subdir * @param aExport3DFiles = true to copy 3D shapes in the subdir a3D_Subdir
* @param a3D_Subdir = sub directory where 3D shapes files are copied * @param a3D_Subdir = sub directory where 3D shapes files are copied
* used only when aExport3DFiles == true * used only when aExport3DFiles == true
* @return true if Ok. * @return true if Ok.
*/ */
/* When copying 3D shapes files, the new filename is build from /* Note1:
* When copying 3D shapes files, the new filename is build from
* the full path name, changing the separators by underscore. * the full path name, changing the separators by underscore.
* this is needed because files with the same shortname can exist in different directories * 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, bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName,
double aScale, bool aExport3DFiles, double aMMtoWRMLunit, bool aExport3DFiles,
const wxString & a3D_Subdir ) const wxString & a3D_Subdir )
{ {
wxString msg; wxString msg;
...@@ -1266,42 +1281,30 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName, ...@@ -1266,42 +1281,30 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName,
" title \"%s - Generated by Pcbnew\"\n" " title \"%s - Generated by Pcbnew\"\n"
"}\n", TO_UTF8( name ) ); "}\n", TO_UTF8( name ) );
/* The would be in decimils and not in meters, as the standard wants. /* The would be in BIU and not in meters, as the standard wants.
* It is trivial to embed everything in a transform node to * It is trivial to embed everything in a transform node to
* fix it. For example here we build the world in inches... * fix it. For example here we build the world in inches...
*/ */
/* scaling factor to convert internal units (decimils) to inches // Global VRML scale to export to a different scale.
*/ // (aMMtoWRMLScale = 1.0 to export in mm)
double board_scaling_factor = 0.001*MILS_PER_IU; double boardIU2WRML = aMMtoWRMLunit / MM_PER_IU;
/* auxiliary scale to export to a different scale.
*/
double general_scaling_factor = board_scaling_factor * aScale;
fprintf( output_file, "Transform {\n" ); fprintf( output_file, "Transform {\n" );
fprintf( output_file, " scale %g %g %g\n", fprintf( output_file, " scale %g %g %g\n",
general_scaling_factor, general_scaling_factor, general_scaling_factor ); boardIU2WRML , boardIU2WRML, boardIU2WRML );
/* Define the translation to have the board centre to the 2D axis origin /* Define the translation to have the board centre to the 2D axis origin
* more easy for rotations... * more easy for rotations...
*/ */
EDA_RECT bbbox = pcb->ComputeBoundingBox(); EDA_RECT bbbox = pcb->ComputeBoundingBox();
double dx = board_scaling_factor * bbbox.Centre().x * aScale; double dx = boardIU2WRML * bbbox.Centre().x;
double dy = board_scaling_factor * bbbox.Centre().y * aScale; double dy = boardIU2WRML * bbbox.Centre().y;
fprintf( output_file, " translation %g %g 0.0\n", -dx, dy ); fprintf( output_file, " translation %g %g 0.0\n", -dx, dy );
fprintf( output_file, " children [\n" ); fprintf( output_file, " children [\n" );
/* 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
* So the scaling factor from 0.1 inch to board units
* is 0.1 / board_scaling_factor
*/
double wrml_3D_models_scaling_factor = 0.1 / board_scaling_factor;
// Preliminary computation: the z value for each layer // Preliminary computation: the z value for each layer
compute_layer_Zs( pcb ); compute_layer_Zs( pcb );
...@@ -1315,6 +1318,13 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName, ...@@ -1315,6 +1318,13 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString & aFullFileName,
/* TODO export_vrml_zones(pcb); /* 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 0.1 / general_scaling_factor
*/
double wrml_3D_models_scaling_factor = 2.54 / boardIU2WRML;
// Export footprints // Export footprints
for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() ) for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() )
export_vrml_module( pcb, module, output_file, export_vrml_module( pcb, module, output_file,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment