diff --git a/Fltk/fileDialogs.cpp b/Fltk/fileDialogs.cpp
index f288d7d1bf0735aaef4e4cc58e17d0df0f068527..f41eb646171200d9be930cab587e5d5056c6782c 100644
--- a/Fltk/fileDialogs.cpp
+++ b/Fltk/fileDialogs.cpp
@@ -859,6 +859,8 @@ int mshFileDialog(const char *name)
     {"Version 1", 0, 0, 0},
     {"Version 2 ASCII", 0, 0, 0},
     {"Version 2 Binary", 0, 0, 0},
+    {"Version 3 ASCII (Experimental)", 0, 0, 0},
+    {"Version 3 Binary (Experimental)", 0, 0, 0},
     {0}
   };
 
@@ -889,8 +891,12 @@ int mshFileDialog(const char *name)
     dialog->window->hotspot(dialog->window);
   }
 
-  dialog->c->value((CTX::instance()->mesh.mshFileVersion == 1.0) ? 0 :
-                   CTX::instance()->mesh.binary ? 2 : 1);
+  if(CTX::instance()->mesh.mshFileVersion == 1.0)
+    dialog->c->value(0);
+  else if(CTX::instance()->mesh.mshFileVersion < 3.0)
+    dialog->c->value(!CTX::instance()->mesh.binary ? 1 : 2);
+  else
+    dialog->c->value(!CTX::instance()->mesh.binary ? 3 : 4);
   dialog->b[0]->value(CTX::instance()->mesh.saveAll ? 1 : 0);
   dialog->b[1]->value(CTX::instance()->mesh.saveParametric ? 1 : 0);
   dialog->b[2]->value(CTX::instance()->mesh.mshFilePartitioned ? 1 : 0);
@@ -903,7 +909,8 @@ int mshFileDialog(const char *name)
       if (!o) break;
       if (o == dialog->ok) {
         opt_mesh_msh_file_version(0, GMSH_SET | GMSH_GUI,
-                                  (dialog->c->value() == 0) ? 1.0 : 2.2);
+                                  (dialog->c->value() == 0) ? 1.0 :
+                                  (dialog->c->value() < 3) ? 2.2 : 3.0);
         opt_mesh_binary(0, GMSH_SET | GMSH_GUI, (dialog->c->value() == 2) ? 1 : 0);
         opt_mesh_save_all(0, GMSH_SET | GMSH_GUI, dialog->b[0]->value() ? 1 : 0);
         opt_mesh_save_parametric(0, GMSH_SET | GMSH_GUI, dialog->b[1]->value() ? 1 : 0);
diff --git a/Geo/GModelIO_MSH.cpp b/Geo/GModelIO_MSH.cpp
index aa1210406db94c14df499eca95540312f02b93aa..e7913105cf7be424c206f010a12477fc3c02483c 100644
--- a/Geo/GModelIO_MSH.cpp
+++ b/Geo/GModelIO_MSH.cpp
@@ -16,36 +16,6 @@
 #include "MPyramid.h"
 #include "StringUtils.h"
 
-static bool getVertices(int num, const std::vector<int> &indices,
-                        std::map<int, MVertex*> &map,
-                        std::vector<MVertex*> &vertices)
-{
-  for(int i = 0; i < num; i++){
-    if(!map.count(indices[i])){
-      Msg::Error("Wrong vertex index %d", indices[i]);
-      return false;
-    }
-    else
-      vertices.push_back(map[indices[i]]);
-  }
-  return true;
-}
-
-static bool getVertices(int num, const std::vector<int> &indices,
-                        std::vector<MVertex*> &vec,
-                        std::vector<MVertex*> &vertices, int minVertex = 0)
-{
-  for(int i = 0; i < num; i++){
-    if(indices[i] < minVertex || indices[i] > (int)(vec.size() - 1 + minVertex)){
-      Msg::Error("Wrong vertex index %d", indices[i]);
-      return false;
-    }
-    else
-      vertices.push_back(vec[indices[i]]);
-  }
-  return true;
-}
-
 int GModel::readMSH(const std::string &name)
 {
   FILE *fp = fopen(name.c_str(), "rb");
@@ -138,8 +108,8 @@ int GModel::readMSH(const std::string &name)
         double xyz[3];
         MVertex *vertex = 0;
         if(!binary){
-          if(fscanf(fp, "%d %lf %lf %lf %d %d", &num, &xyz[0], &xyz[1], &xyz[2],
-                    &entity, &dim) != 6)
+          if(fscanf(fp, "%d %lf %lf %lf %d", &num, &xyz[0], &xyz[1], &xyz[2],
+                    &entity) != 5)
             return 0;
         }
         else{
@@ -149,10 +119,18 @@ int GModel::readMSH(const std::string &name)
           if(swap) SwapBytes((char*)xyz, sizeof(double), 3);
           if(fread(&entity, sizeof(int), 1, fp) != 1) return 0;
           if(swap) SwapBytes((char*)&entity, sizeof(int), 1);
-          if(fread(&dim, sizeof(int), 1, fp) != 1) return 0;
-          if(swap) SwapBytes((char*)&dim, sizeof(int), 1);
         }
-        if(entity){
+        if(!entity){
+          vertex = new MVertex(xyz[0], xyz[1], xyz[2], 0, num);
+        }
+        else{
+          if(!binary){
+            if(fscanf(fp, "%d", &entity) != 1) return 0;
+          }
+          else{
+            if(fread(&dim, sizeof(int), 1, fp) != 1) return 0;
+            if(swap) SwapBytes((char*)&dim, sizeof(int), 1);
+          }
           switch(dim){
           case 0:
             {
@@ -455,7 +433,7 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
   fprintf(fp, "%d\n", numVertices);
   for(unsigned int i = 0; i < entities.size(); i++)
     for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++)
-      entities[i]->mesh_vertices[j]->writeMSH(fp, binary, scalingFactor);
+      entities[i]->mesh_vertices[j]->writeMSH(fp, binary, saveParametric, scalingFactor);
 
   if(binary) fprintf(fp, "\n");
   fprintf(fp, "$EndNodes\n");
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index 8f19943ff4d94bd0a3d84059cd465728571534f6..d0c540e160f49236b86e125f6a16b6a011706241 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -67,7 +67,7 @@ void MVertex::forceNum(int num)
   }
 }
 
-void MVertex::writeMSH(FILE *fp, bool binary, double scalingFactor)
+void MVertex::writeMSH(FILE *fp, bool binary, bool saveParametric, double scalingFactor)
 {
   if(_index < 0) return; // negative index vertices are never saved
 
@@ -82,7 +82,7 @@ void MVertex::writeMSH(FILE *fp, bool binary, double scalingFactor)
   }
 
   int zero = 0;
-  if(!onWhat()){
+  if(!onWhat() || !saveParametric){
     if(!binary)
       fprintf(fp, "0\n");
     else
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index c14769ca824f65f72477db115f4ceebfe8f2d038..1bcb2ef29314407c72d0816ed633a6b99415081e 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -110,7 +110,8 @@ class MVertex{
   linearSearch(std::set<MVertex*, MVertexLessThanLexicographic> &pos);
 
   // IO routines
-  void writeMSH(FILE *fp, bool binary=false, double scalingFactor=1.0);
+  void writeMSH(FILE *fp, bool binary=false, bool saveParametric=false,
+                double scalingFactor=1.0);
   void writeMSH2(FILE *fp, bool binary=false, bool saveParametric=false,
                  double scalingFactor=1.0);
   void writePLY2(FILE *fp);