← Back to team overview

kicad-developers team mailing list archive

small fix to 3D export

 

Due to the combination of very large scale factors and very small scale factors in the exported VRML file, truncation errors in VRML viewers (whitedune and lookat) caused problems; for example whitedune would render correctly when exported in mm but gives bad results when exporting to inch or meter.  I have changed the code to scale the point coordinates rather than specifying a global scale + counteracting local scales and this appears to solve the problem.  When tested with the pic_programmer demo, the resulting file size was smaller by almost 2MB (~7.7MB rather than ~9.5MB) due to space saved in writing the text representation of coordinates.

Other changes made:
1. removed unnecessary translation/rotation/scale parameters within the VRML Transform block
2. corrected the URL file syntax

I am aware of at least one bug but it is one that requires some thought before deciding how to address it: if relative filenames are used, the URL points to invalid relative locations. I believe relative file URLs should only be allowed when the 3D models are copied to a directory (this allows people to give their board VRML model to others), and absolute file URLs should be used when the models are not being copied.

There is also a problem with thru-hole pads; for the resistors and diodes (in pic_programmer) it seems pads are rendered, but for the DILs only the first pad is rendered. I haven't had time yet to look into this.

Regards,
Cirilo
=== modified file 'pcbnew/export_vrml.cpp'
--- pcbnew/export_vrml.cpp	2013-01-12 10:35:08 +0000
+++ pcbnew/export_vrml.cpp	2013-01-13 09:18:58 +0000
@@ -303,16 +303,14 @@
 
 
 static void write_triangle_bag( FILE* output_file, int color_index, //{{{
-                                const TriangleBag& triangles )
+                                const TriangleBag& triangles,
+                                double boardIU2WRML )
 {
     /* A lot of nodes are not required, but blender sometimes chokes
      * without them */
     static const char* shape_boiler[] =
     {
         "Transform {\n",
-        "  translation 0.0 0.0 0.0\n",
-        "  rotation 1.0 0.0 0.0 0.0\n",
-        "  scale 1.0 1.0 1.0\n",
         "  children [\n",
         "    Group {\n",
         "      children [\n",
@@ -379,12 +377,15 @@
                      i != triangles.end();
                      i++ )
                 {
-                    fprintf( output_file, "%g %g %g\n",
-                             i->p1.x, -i->p1.y, i->p1.z );
-                    fprintf( output_file, "%g %g %g\n",
-                             i->p2.x, -i->p2.y, i->p2.z );
-                    fprintf( output_file, "%g %g %g\n",
-                             i->p3.x, -i->p3.y, i->p3.z );
+                    fprintf( output_file, "%.8g %.8g %.8g\n",
+                             i->p1.x * boardIU2WRML, -i->p1.y * boardIU2WRML,
+                             i->p1.z * boardIU2WRML );
+                    fprintf( output_file, "%.8g %.8g %.8g\n",
+                             i->p2.x * boardIU2WRML, -i->p2.y * boardIU2WRML,
+                             i->p2.z * boardIU2WRML );
+                    fprintf( output_file, "%.8g %.8g %.8g\n",
+                             i->p3.x * boardIU2WRML, -i->p3.y * boardIU2WRML,
+                             i->p3.z * boardIU2WRML );
                 }
             }
             break;
@@ -1098,7 +1099,8 @@
 static void export_vrml_module( BOARD* aPcb, MODULE* aModule,
                                 FILE* aOutputFile,
                                 double aVRMLModelsToBiu,
-                                bool aExport3DFiles, const wxString & a3D_Subdir )
+                                bool aExport3DFiles, const wxString & a3D_Subdir,
+                                double boardIU2WRML )
 {
     // Reference and value
     export_vrml_text_module( aModule->m_Reference );
@@ -1206,9 +1208,9 @@
         RotatePoint(&offsetx, &offsety, aModule->GetOrientation());
 
         fprintf( aOutputFile, "  translation %g %g %g\n",
-                 (double) (offsetx + aModule->m_Pos.x),
-                 - (double)(offsety + aModule->m_Pos.y),    // Y axis is reversed in Pcbnew
-                 offsetz + layer_z[aModule->GetLayer()] );
+                 (double) (offsetx + aModule->m_Pos.x) * boardIU2WRML,
+                 - (double)(offsety + aModule->m_Pos.y) * boardIU2WRML,    // Y axis is reversed in Pcbnew
+                 offsetz + layer_z[aModule->GetLayer()] * boardIU2WRML);
 
         fprintf( aOutputFile, "  scale %g %g %g\n",
                  vrmlm->m_MatScale.x * aVRMLModelsToBiu,
@@ -1216,18 +1218,19 @@
                  vrmlm->m_MatScale.z * aVRMLModelsToBiu );
 
         fprintf( aOutputFile,
-                 "  children [\n    Inline {\n      url \"%s\"\n    } ]\n",
+                 "  children [\n    Inline {\n      url \"file://%s\"\n    } ]\n",
                  TO_UTF8( fname ) );
         fprintf( aOutputFile, "  }\n" );
     }
 }
 
 
-static void write_and_empty_triangle_bag( FILE* output_file, TriangleBag& triangles, int color )
+static void write_and_empty_triangle_bag( FILE* output_file, TriangleBag& triangles,
+                                          int color, double boardIU2WRML )
 {
     if( !triangles.empty() )
     {
-        write_triangle_bag( output_file, color, triangles );
+        write_triangle_bag( output_file, color, triangles, boardIU2WRML );
         triangles.clear( );
     }
 }
@@ -1290,8 +1293,6 @@
     // (aMMtoWRMLScale = 1.0 to export in mm)
     double boardIU2WRML = aMMtoWRMLunit / MM_PER_IU;
     fprintf( output_file, "Transform {\n" );
-    fprintf( output_file, "  scale %g %g %g\n",
-            boardIU2WRML , boardIU2WRML, boardIU2WRML );
 
     /* Define the translation to have the board centre to the 2D axis origin
      * more easy for rotations...
@@ -1324,25 +1325,28 @@
      * 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;
+    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 );
+                            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) );
+                                      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 ) );
+                                      pcb->GetVisibleElementColor( VIAS_VISIBLE + i ),
+                                      boardIU2WRML );
 
     // Close the outer 'transform' node
     fputs( "]\n}\n", output_file );


Follow ups