Index: Copyright
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/Copyright,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- Copyright	27 Jan 2006 19:53:18 -0000	1.1.1.1
+++ Copyright	20 Oct 2006 20:26:35 -0000	1.4
@@ -19,3 +19,16 @@
 along with EasyAnim; see the file COPYING.  If not, write to the Free
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+
+
+Portions Copyright (C) 2006 Pierangelo MASARATI
+	Dipartimento di Ingegneria Aerospaziale
+	Politecnico di Milano
+	via La Masa 34, 20156 MILANO (Italy)
+	masarati@aero.polimi.it
+
+EasyAnim has been modified by Pierangelo Masarati for better 
+interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+The same version of the GNU General Public License of the original 
+software applies.
+
Index: NEWS
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/NEWS,v
retrieving revision 1.1.1.1
retrieving revision 1.12
diff -u -r1.1.1.1 -r1.12
--- NEWS	27 Jan 2006 19:53:18 -0000	1.1.1.1
+++ NEWS	28 Sep 2006 13:28:55 -0000	1.12
@@ -1,3 +1,30 @@
+Modifications to version 1.3 for use with MBDyn (1.3-polimi.1)
+-----------------------------------------------
+
+No difference for the user; the .vol syntax has been extended
+in a way that __should be__ fully compatible with 1.3 files.
+
+Use std::string to handle (most) strings
+Fix delete of uninitialized stuff
+Fix buffer overruns in messages (no more sprintf, strcpy, strcat)
+Introduce node props: color, [signed|null]radius
+Introduce edge props: color, [signed|null]radius
+Introduce side props: color
+Use std::vector for data
+Node and Edge radius is changed by the buttons, but ratios are preserved
+Negative radii in properties are not changed by the buttons
+Store van data in memory, for __much__ faster rendering
+Introduce capability to generate MPEG movies via ffmpeg (needs work)
+Introduce capability to generate PPM screenshots (needs work)
+Allow to save "repere" (reference triad) status in config file
+Add "reload" capability
+Add streamed van capability: node position updates from inet/local
+	default: 	{$TMPDIR|/tmp}/easyanim.sock
+	local:		path
+	inet:		inet://[ip(127.0.0.1)][:port(9011)]
+
+Compatibility with Windows is not guaranteed, pending review.
+
 From version 1.2 to version 1.3
 -------------------------------
 
Index: README
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/README,v
retrieving revision 1.1.1.1
retrieving revision 1.6
diff -u -r1.1.1.1 -r1.6
--- README	27 Jan 2006 19:53:18 -0000	1.1.1.1
+++ README	28 Sep 2006 21:07:58 -0000	1.6
@@ -101,23 +101,50 @@
 
 The format of the file is the following
 
-A comment line
+A comment line (mandatory)
+
+an (optional) sequence of node property definitions, with the format
+"prop" name color radius
+where name is whatever printable, color is between 0-15 and radius 
+is an arbitrary float; the value of the radius is relative to the
+value set from the GUI, so that the radii of the nodes preserve their
+ratio when scaled; a negative value makes the radius absolute, i.e.
+it is not scaled by the GUI.  A radius of 0.0 turns off the node.
+
 Nn               # the number of nodes
 node1 X1 Y1 Z1   # the name (alphanumeric) of the node and its coordinates
-node2 X2 Y2 Z2
+node2 X2 Y2 Z2   # optionally followed by the name of the property
 :
 nodeNn XNn YNn ZNn
+
+an (optional) sequence of edge property definitions, with the same format
+of the node properties above.  The name of the property is used as last 
+argument in each edge definition; a set of default properties whose
+names are the integers in 0-15 is predefined; their relative radius is 1.0
+and their color is indicated by their name.
+
 Ne               # the number of edges
 edge1 iname1 jname1 color1  # the name of the edge, the names of the edge
 edge2 iname2 jname2 color2  # nodes, and the color (cf. later)
 :
 edgeNe inameNe jnameNe colorNe
+
+an (optional) sequence of side property definitions, with the format
+"prop" name color
+The name if the property is used as last argument in each side definition;
+a set of default properties whose names are the integers in 0-15 
+is predefined; their color is indicated by their name.
+
 Np               # the number of polygons
 poly1 N1 iname1 jname1 kname1 ... color1 # the name of the polygon, the number
 poly2 N2 iname2 jname2 kname2 ... color2 # of perimeter nodes, the names of the
 :                                # perimeter nodes and the color of the surface
 polyNp Nep inameNp jnameNp ... colorNp
 
+Except for the first, mandatory comment line (regarded as a title),
+the rest of the .vol file can be arbitrarily interspersed with comment
+lines that start with a `#'.
+
 You will find data files related to simple scenes (square and pyramid)
 in the examples directory. The most often, the names correspond to the
 number of the item. Have a look at square.vol in the examples to see
@@ -130,6 +157,10 @@
 12:lightred, 13:lightmagenta, 14: yellow, 15:white). It is foreseen to
 switch later to a description in RGB.
 
+The format of the file is fully compatible with that of version 1.3;
+it is believed that the extensions will make automatic generation
+and editing of model files easier and more versatile.
+
 Format of the .van file
 -----------------------
 
@@ -143,8 +174,15 @@
 :
 XNn YNn ZNn
 
-When running the animation, the images are successfully read and
-represented on the screen.
+The .vol and .van files are both loaded when the former is selected;
+data to generate each step of the simulation are stored in memory.
+The size is sizeof(double) * 3 * Nnodes * Nimages; for quite large
+simulations this can be quite memory intensive.
+When running the animation, the images are represented on the screen.
+
+The simulation can be acquired online instead of being read from a .van
+file by using the streamed .van input mode.  In this case, the data
+for each image is read from a socket, either inet or local.
 
 Format of the .vmo file
 -----------------------
@@ -157,7 +195,7 @@
 Xr1 Yr1 Zr1
 Xr2 Yr2 Zr2
 :
-XiNn YrNn ZrNn
+XrNn YrNn ZrNn
 Xi1 Yi1 Zi1
 Xi2 Yi2 Zi2
 :
@@ -213,6 +251,10 @@
 From the options menu, you can change the background colour and load a
 different mode if you loaded a modal analysis.
 
+You can generate screenshots (ppm) and movies (mpeg; needs ffmpeg).
+Set the TMPDIR environment variable to the directory to be used
+for temporary storage (/tmp by default).
+
 Acknowledgements
 ----------------
 
@@ -230,3 +272,22 @@
 31, Bd Dolez; 7000 MONS (BELGIUM)
 E-mail: Olivier.Verlinden@fpms.ac.be
 
+This version of EasyAnim has been modified by Pierangelo Masarati
+to imrpove interoperation with MBDyn, a multibody dynamics software;
+here are my coordinates
+
+Dr. Pierangelo MASARATI
+Politecnico di Milano
+Dipartimento di Ingegneria Aerospaziale
+Campus Bovisa, via La Masa 34, 20156 MILANO (ITALY)
+E-mail: pierangelo.masarati@polimi.it
+http://www.aero.polimi.it/~masarati/
+
+and here are those of MBDyn:
+
+http://www.mbdyn.org/
+http://www.aero.polimi.it/~mbdyn/
+mailto:mbdyn-users@mbdyn.org (need to subscribe)
+
+EasyAnim at Politecnico di Milano is mainly used and developed on Linux;
+please don't ask questions about compiling under Windows.
Index: src/EasyAnim.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnim.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.5
diff -u -r1.1.1.1 -r1.5
--- src/EasyAnim.cpp	27 Jan 2006 19:53:27 -0000	1.1.1.1
+++ src/EasyAnim.cpp	30 Oct 2006 12:31:25 -0000	1.5
@@ -1,122 +1,131 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-#include <stdio.h>
-#include <fstream>
-#include "EasyAnim.h"              // Header file
-
-myCmdWindow* _myCmdWin;
-//=========================>>> myApp::myApp <<<==========================
-  myApp::myApp(char* name, int sdi) : vApp(name, sdi)
-  {
-	  // Constructor
-  }
-
-//=====================>>> myApp::NewAppWin <<<==========================
-  vWindow* myApp::NewAppWin(vWindow* win, char* name,
-    int w, int h, vAppWinInfo* winInfo)
-  {
-	vWindow* _myCmdWin = win;
-	vAppWinInfo* awinfo = winInfo;
-    char *appname = name;
-
-    if (!*name)
-      {
-	 appname = "EasyAnim 1.3 - Faculte Polytechnique de Mons (www.mecara.fpms.ac.be)";		// Default name
-      }
-	
-    UserDebug1(Build,"myApp::NewAppWin(%s)\n",appname);
-
-    // Create the first window using provided CmdWindow
-
-	if (!_myCmdWin)
-      {
-	_myCmdWin = new myCmdWindow(appname, w, h);
-      }
-	
-	if (!awinfo)
-	awinfo = new vAppWinInfo(appname);
-
-    return vApp::NewAppWin(_myCmdWin, appname, w, h, awinfo);
-  }
-
-//============================>>> myApp::Exit <<<===========================
-  void myApp::Exit(void)
-  {
-    // This is called to close all windows.
-
-    UserDebug(Build,"myApp::Exit()\n");
-
-    vApp::Exit();		// Default behavior
-  }
-
-//======================>>> myApp::CloseAppWin <<<===========================
-  int myApp::CloseAppWin(vWindow* win)
-  {
-    // This will be called BEFORE a window has been unregistered or
-    // closed.  Default behavior: unregister and close the window.
-
-    UserDebug(Build,"myApp::CloseAppWin()\n");
-
-    return vApp::CloseAppWin(win);
-  }
-
-//=====================>>> myApp::AppCommand <<<==============================
-  void myApp::AppCommand(vWindow* win, ItemVal id, ItemVal val, CmdType cType)
-  {
-    // Commands not processed by the window will be passed here
-
-    UserDebug1(Build,"myApp::AppCmd(ID: %d)\n",id);
-    vApp::AppCommand(win, id, val, cType);
-  }
-
-//=========================>>> myApp::KeyIn <<<==============================
-  void myApp::KeyIn(vWindow* win, vKey key, unsigned int shift)
-  {
-    // Key strokes not processed by the window will be passed here
-
-    vApp::KeyIn(win, key, shift);
-  }
-
-//###########################################################################
-
-  static myApp my_App(" ",1);	// The instance of the app
-
-//============================>>> AppMain <<<==============================
-  int AppMain(int argc, char** argv)
-  {
-    // Use AppMain to create the main window
-
-    myCmdWindow* cw = (myCmdWindow*) theApp->NewAppWin(0,"",700,550);
-
-  if (argc == 2)
-  {
-  	char *fichier_tmp = argv[1];
-	_myCmdWin->Lecture(fichier_tmp);
-  }
-
-   return 0;           // 0 means OK 
-  }
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <fstream>
+#include "EasyAnim.h"              // Header file
+
+static myCmdWindow* easyAnimCmdWin;
+
+//=========================>>> myApp::myApp <<<==========================
+myApp::myApp(char* name, int sdi)
+: vApp(name, sdi)
+{
+	// Constructor
+}
+
+//=====================>>> myApp::NewAppWin <<<==========================
+vWindow*
+myApp::NewAppWin(vWindow* win, char* name,
+	int w, int h, vAppWinInfo* winInfo)
+{
+	easyAnimCmdWin = dynamic_cast<myCmdWindow *>(win);
+	vAppWinInfo* awinfo = winInfo;
+	char *appname = name;
+
+	if (!*name) {
+		// Default name
+		appname = "EasyAnim " EASYANIM_VERSIONSTR " - "
+			"Faculte Polytechnique de Mons "
+			"(http://www.mecara.fpms.ac.be/) - "
+			"Modified at Politecnico di Milano "
+			"(http://www.aero.polimi.it/~mbdyn/)";
+	}
+
+	UserDebug1(Build, "myApp::NewAppWin(%s)\n", appname);
+
+	// Create the first window using provided CmdWindow
+	if (!easyAnimCmdWin) {
+		easyAnimCmdWin = new myCmdWindow(appname, w, h);
+	}
+
+	if (!awinfo) {
+		awinfo = new vAppWinInfo(appname);
+	}
+
+	return vApp::NewAppWin(easyAnimCmdWin, appname, w, h, awinfo);
+}
+
+//============================>>> myApp::Exit <<<===========================
+void
+myApp::Exit(void)
+{
+	// This is called to close all windows.
+	UserDebug(Build, "myApp::Exit()\n");
+
+	vApp::Exit();		// Default behavior
+}
+
+//======================>>> myApp::CloseAppWin <<<===========================
+int
+myApp::CloseAppWin(vWindow* win)
+{
+	// This will be called BEFORE a window has been unregistered or
+	// closed.  Default behavior: unregister and close the window.
+	UserDebug(Build,"myApp::CloseAppWin()\n");
+
+	return vApp::CloseAppWin(win);
+}
+
+//=====================>>> myApp::AppCommand <<<==============================
+void
+myApp::AppCommand(vWindow* win, ItemVal id, ItemVal val, CmdType cType)
+{
+	// Commands not processed by the window will be passed here
+	UserDebug1(Build,"myApp::AppCmd(ID: %d)\n",id);
+	vApp::AppCommand(win, id, val, cType);
+}
+
+//=========================>>> myApp::KeyIn <<<==============================
+void
+myApp::KeyIn(vWindow* win, vKey key, unsigned int shift)
+{
+	// Key strokes not processed by the window will be passed here
+	vApp::KeyIn(win, key, shift);
+}
+
+//###########################################################################
+
+static myApp my_App(" ", 1);	// The instance of the app
+
+//============================>>> AppMain <<<==============================
+int
+AppMain(int argc, char** argv)
+{
+	// Use AppMain to create the main window
+
+#if 0
+	myCmdWindow* cw = (myCmdWindow*)
+#endif
+	theApp->NewAppWin(0, "", 700, 550);
+
+	if (argc == 2) {
+		char *fichier_tmp = argv[1];
+		easyAnimCmdWin->Lecture(fichier_tmp);
+	}
+
+	return 0;           // 0 means OK
+}
Index: src/EasyAnim.h
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnim.h,v
retrieving revision 1.1.1.1
retrieving revision 1.5
diff -u -r1.1.1.1 -r1.5
--- src/EasyAnim.h	27 Jan 2006 19:53:23 -0000	1.1.1.1
+++ src/EasyAnim.h	16 Nov 2006 22:07:21 -0000	1.5
@@ -1,72 +1,84 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-//      EasyAnim.h:        Header for myApp class
-//=======================================================================
-
-#ifndef Easyanim_H
-#define Easyanim_H
-
-// Include standard V files as needed
-
-#ifdef vDEBUG
-#include <v/vdebug.h>
-#endif
-
-#include <v/vapp.h>
-#include <v/vawinfo.h>
-
-#include "EasyAnimcmdw.h"     // we use myCommandWindow
-    class myApp : public vApp
-      {
-	friend int AppMain(int, char**);	// allow AppMain access
-
-      public:		//---------------------------------------- public
-
-	myApp(char* name, int sdi = 1);
-
-	// Routines from vApp that are normally overridden
-
-	virtual vWindow* NewAppWin(vWindow* win, char* name, int w, int h,
-		vAppWinInfo* winInfo);
-	
-	virtual void Exit(void);
-
-	virtual int CloseAppWin(vWindow*);
-
-	virtual void AppCommand(vWindow* win, ItemVal id, ItemVal val, CmdType cType);
-
-	virtual void KeyIn(vWindow*, vKey, unsigned int);
-	void Change_Couleur_Fond(int c);
-
-	// New routines for this particular app
-
-      protected:	//--------------------------------------- protected
-
-      private:		//--------------------------------------- private
-
-	};
-#endif
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+//      EasyAnim.h:        Header for myApp class
+//=======================================================================
+
+#ifndef EasyAnim_h
+#define EasyAnim_h
+
+#define EASYANIM_VERSIONSTR	"1.3-polimi.1"
+
+// Include standard V files as needed
+
+#ifdef vDEBUG
+#include <v/vdebug.h>
+#endif
+
+#include <v/vapp.h>
+#include <v/vawinfo.h>
+
+#include "EasyAnimcmdw.h"     // we use myCommandWindow
+class myApp : public vApp
+{
+	friend int AppMain(int, char**);	// allow AppMain access
+
+public:		//---------------------------------------- public
+	myApp(char* name, int sdi = 1);
+
+	// Routines from vApp that are normally overridden
+
+	virtual vWindow* NewAppWin(vWindow* win, char* name, int w, int h,
+		vAppWinInfo* winInfo);
+	
+	virtual void Exit(void);
+
+	virtual int CloseAppWin(vWindow*);
+
+	virtual void AppCommand(vWindow* win, ItemVal id, ItemVal val, CmdType cType);
+
+	virtual void KeyIn(vWindow*, vKey, unsigned int);
+	void Change_Couleur_Fond(int c);
+
+	// New routines for this particular app
+
+protected:	//--------------------------------------- protected
+private:	//--------------------------------------- private
+};
+#endif // EasyAnim_h
Index: src/EasyAnimGL.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimGL.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.36
diff -u -r1.1.1.1 -r1.36
--- src/EasyAnimGL.cpp	27 Jan 2006 19:53:23 -0000	1.1.1.1
+++ src/EasyAnimGL.cpp	28 Nov 2006 00:35:05 -0000	1.36
@@ -1,1303 +1,2217 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-// EasyAnimGL.cpp: the core routines for viewing with GL
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef WINDOWS
-  #include <windows.h>
-  #include <wingdi.h>
-#endif
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <math.h>
-#include <fstream>
-#include <iostream>
-
-#include "EasyAnimGL.h"
-
-// Declarations and initializations
-int i;
-
-float PI =3.141592654f;
-float PI_2 =1.570796327f;
-float PI_10 = 0.3141592654f;
-
-// Variables related to the view
-
-GLfloat _EYE_X=2886.75f,_EYE_Y=2886.75f,_EYE_Z=2886.75f;
-GLfloat _CENTER_X=0.0f,_CENTER_Y=0.0f,_CENTER_Z=0.0f;
-GLfloat _THETA=PI*0.25f,_PHI=0.6154797;
-GLfloat _GAMMA=0.0f;
-GLfloat _UP_X=-0.408f,_UP_Y=-0.408f,_UP_Z=0.577f;
-GLfloat _RIGHT_X=-0.707f,_RIGHT_Y=0.707f,_RIGHT_Z=0.0f;
-GLfloat _DIST=5000.0f;
-static GLsizei _GLOB_W=0;
-static GLsizei _GLOB_H=0;
-static GLfloat _LARGEUR=10;
-
-GLfloat COULEUR[16][3];
-GLfloat MATERIAU[16][3][3];
-
-int SHOWNODES=0;
-int SHOWEDGES=1;
-int SHOWSIDES=1;
-int _ORTHO=1;
-int _COULEUR_FOND = 0;
-static int _N_SKIP_IMAGE=0;
-
-// Variables controlling aspect of edges and nodes
-GLdouble NodeRadius=0.1;
-GLdouble EdgeRadius=0.05;
-
-// Variables controlling animation and type of view
-int _ANIME = 0;
-int _MULTI;
-
-// Variables related to the scenes
-def_scene *SCENE[10];
-int n_scene=0;
-
-// Routine to normalize a vector
-void ReduceToUnit(float vector[3])
-	{
-	float length;
-	
-	// Calculate the length of the vector		
-	length = (float)sqrt((vector[0]*vector[0]) + 
-						(vector[1]*vector[1]) +
-						(vector[2]*vector[2]));
-
-	// Keep the program from blowing up by providing an exceptable
-	// value for vectors that may calculated too close to zero.
-	if(length == 0.0f)
-		length = 1.0f;
-
-	// Dividing each element by the length will result in a
-	// unit normal vector.
-	vector[0] /= length;
-	vector[1] /= length;
-	vector[2] /= length;
-	}
-
-/*---------------------------------------------------------------------*/
-
-// routine de calcul du vecteur normal d'une surface
-void calcNormal(float v[3][3], float out[3])
-	{
-	float v1[3],v2[3];
-	static const int x = 0;
-	static const int y = 1;
-	static const int z = 2;
-
-	// Calcul deux vecteurs à partir des trois points
-	v1[x] = v[0][x] - v[1][x];
-	v1[y] = v[0][y] - v[1][y];
-	v1[z] = v[0][z] - v[1][z];
-
-	v2[x] = v[1][x] - v[2][x];
-	v2[y] = v[1][y] - v[2][y];
-	v2[z] = v[1][z] - v[2][z];
-
-	// Take the cross product of the two vectors to get
-	// the normal vector which will be stored in out
-	out[x] = v1[y]*v2[z] - v1[z]*v2[y];
-	out[y] = v1[z]*v2[x] - v1[x]*v2[z];
-	out[z] = v1[x]*v2[y] - v1[y]*v2[x];
-
-	// normalise le vecteur
-	ReduceToUnit(out);
-	}
-
-/*---------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------*/
-/*     Premiere partie: procedures generales relatives aux scenes      */
-/*---------------------------------------------------------------------*/
-
-// destructeur
-def_scene::def_scene()
-  {
-  NbrImages=0;
-  CurImage=0;
-  hidden=0;
-  NbrNodes=0;
-  NbrEdges=0;
-  NbrSides=0;
-  node=NULL;
-  edge=NULL;
-  side=NULL;
-  xmin=0.0;
-  xmax=0.0;
-  ymin=0.0;
-  ymax=0.0;
-  zmin=0.0;
-  zmax=0.0;
-  }	
-
-/*---------------------------------------------------------------------*/
-
-// destructeur
-def_scene::~def_scene()
-  {
-  int i;
-  if (NbrNodes) delete node;
-  if (NbrEdges) delete edge;
-  if (NbrSides)
-    {
-    for (i=0;i<NbrSides;i++) delete side[i].NumNode;
-    delete side;
-    }
-  NbrNodes = 0;
-  NbrEdges = 0;
-  NbrSides = 0;
-  }	
-
-/*---------------------------------------------------------------------*/
-
-// Lecture des fichiers
-int def_scene::Set(int npoint, float **point,int narr, int **arrete, 
-                    int nface, int **face)
-  {
-  int i,j,k,l;
-  float long_max=0.0f;
-  if (npoint<=0) return 1;
-  NbrNodes=npoint;
-  node=new NodeStruct[NbrNodes];
-  if (node==NULL) return 2;
-  xmin=point[0][0]; xmax=point[0][0];
-  ymin=point[0][1]; ymax=point[0][1];
-  zmin=point[0][2]; zmax=point[0][2];
-  for (i=0;i<NbrNodes;i++)
-	{
-	node[i].x=point[i][0];
-	node[i].y=point[i][1];
-	node[i].z=point[i][2];
-	if(node[i].x<xmin) xmin=node[i].x;
-	if(node[i].x>xmax) xmax=node[i].x;
-	if(node[i].y<ymin) ymin=node[i].y;
-	if(node[i].y>ymax) ymax=node[i].y;
-	if(node[i].z<zmin) zmin=node[i].z;
-	if(node[i].z>zmax) zmax=node[i].z;
-	}/*endfor i*/
-  // Memory allocation for the spheres representing the nodes
-   NodeSphere=gluNewQuadric();
-   gluQuadricNormals(NodeSphere,GLU_FLAT);
-   gluQuadricTexture(NodeSphere,GL_FALSE);
-   gluQuadricOrientation(NodeSphere,GLU_OUTSIDE);
-   gluQuadricDrawStyle(NodeSphere,GLU_FILL);
-
-  // Managing the edges
-  if (narr<=0) return 3;
-  NbrEdges=narr;
-  edge=new EdgeStruct[NbrEdges];
-  if (edge==NULL) return 5;
-  for (i=0;i<NbrEdges;i++)
-      {
-      edge[i].node1=arrete[i][0];edge[i].node2=arrete[i][1];
-      edge[i].color=arrete[i][2];
-      if ((edge[i].node1<0)||(edge[i].node1>NbrNodes)) return 6;
-      if ((edge[i].node2<0)||(edge[i].node2>NbrNodes)) return 7;
-      }
-  if (nface<0) return 8;
-  NbrSides=nface;
-  if (NbrSides!=0)
-      {
-      side = new SideStruct[NbrSides];
-      if (side==NULL) return 9;
-      for (i=0;i<NbrSides;i++)
-	  {
-	  side[i].NbrNodes=face[i][0];/*nombre de sommets*/
-          side[i].NumNode = new int [side[i].NbrNodes];
-          if (side[i].NumNode==NULL) return 10;
-          for (k=0;k<=side[i].NbrNodes;k++)
-            {
-            side[i].NumNode[k]=face[i][k+1];/*numero des sommets*/
-            if ((side[i].NumNode[k]<0)||(side[i].NumNode[k]>NbrNodes)) 
-               return 11;
-            }
-          side[i].color=face[i][face[i][0]+1];/*numero de la couleur*/
-          }/*endfor i*/
-      }/*endif*/
-  }
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::GetDim(float &x1,float &x2,float &y1,float &y2,
-                       float &z1,float &z2)
-  {
-  x1=xmin; x2=xmax; y1=ymin; y2=ymax; z1=zmin; z2=zmax;
-  }
-
-/*---------------------------------------------------------------------*/
-
-int def_scene::Hidden()	
-  {
-  return hidden;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::Hide()	
-  {
-  hidden=1;
-  }  
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::Show()	
-  {
-  hidden=0;
-  }  
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::Homothetie(float MULT)	
-// Homothétie de la scène
-  {
-  int i;
-  //modification de la taille de l'image
-  if (MULT>0.0f)
-    {
-    for (i=0;i<NbrNodes;i++)
-	{
-	node[i].x*=MULT;
-	node[i].y*=MULT;
-	node[i].z*=MULT;
-	}
-    xmin*=MULT; xmax*=MULT;
-    ymin*=MULT; ymax*=MULT;
-    zmin*=MULT; zmax*=MULT;
-    }
-	
-}
-
-/*---------------------------------------------------------------------*/
-
-int def_scene::GetNumNodeOfName(const char *NodeName)
-  {
-  int i,num=-1;
-  for (i=0;i<NbrNodes;i++) if (!strcmp(NodeName,node[i].name)) num=i;
-  return num;
-  }
-
-/*---------------------------------------------------------------------*/
-
-//coordonnees d'un point de l'image
-/*void def_scene::Get_Point(int num,float Pt[3])	
-  {
-  Pt[0]=0.0;
-  Pt[1]=0.0;
-  Pt[2]=0.0;
-  if ((num>=0)&&(num<NbrNodes))
-      {
-      Pt[0]=POINT[num][0];
-      Pt[1]=POINT[num][1];
-      Pt[2]=POINT[num][2];
-      }
-      }*/
-
-/*---------------------------------------------------------------------*/
-
-int def_scene::GetNbrImages()	
-  {
-    return NbrImages;
-  }
-
-/*---------------------------------------------------------------------*/
-
-int def_scene::GetCurImage()	
-  {
-    return CurImage;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::Next()	
-  {
-  }
-
-/*---------------------------------------------------------------------*/
-
-void def_scene::LoadImage(int NumImage)	
-  {
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine de dessin
-void def_scene::Trace()
-  {
-  //creation de la liste GL
-  int i,j,k;
-  GLfloat  mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f};
-  GLfloat  mat_diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f};
-  GLfloat  mat_gray[] = { 0.2f, 0.2f, 0.2f, 1.0f};
-  GLfloat  mat_lightgray[] = { 0.4f, 0.4f, 0.4f, 0.0f};
-  GLfloat  mat_black[] = { 0.0f, 0.0f, 0.0f, 0.0f};
-
-  if (!hidden)
-    {
-    // Display the spheres at the nodes
-    if (SHOWNODES)
-	{
-        glPushMatrix();
-	mat_ambient[0]=0.2f; mat_ambient[1]=0.2f; mat_ambient[2]=0.6f;
-        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
-	mat_diffuse[0]=0.2f; mat_diffuse[1]=0.2f; mat_diffuse[2]=0.6f;
-        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
-        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_lightgray);
-        for (i=0; i<NbrNodes; i++)
-          {
-          glTranslatef(node[i].x,node[i].y,node[i].z);
-          gluSphere(NodeSphere,NodeRadius,10,10);
-          glTranslatef(-node[i].x,-node[i].y,-node[i].z);
-          }
-        glPopMatrix();
-	}
-      //glBegin(GL_LINES);
-    if (SHOWEDGES)
-        {
-        float angle, dx, dy, dz, le;
-        for (i=0;i<NbrEdges;i++) 
-          {
-	  ///mat_ambient[0]=COULEUR[edge[i].color][0];
-	  ///mat_ambient[1]=COULEUR[edge[i].color][1];
-	  ///mat_ambient[2]=COULEUR[edge[i].color][2];
-          mat_ambient[0]=0.6*COULEUR[edge[i].color][0];
-          mat_ambient[1]=0.6*COULEUR[edge[i].color][1];
-          mat_ambient[2]=0.6*COULEUR[edge[i].color][2];
-          mat_diffuse[0]=0.4*COULEUR[edge[i].color][0];
-          mat_diffuse[1]=0.4*COULEUR[edge[i].color][1];
-          mat_diffuse[2]=0.4*COULEUR[edge[i].color][2];
-          glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
-          //glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_black);
-          glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
-          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_black);
-          //glVertex3f(node[edge[i].node1].x,node[edge[i].node1].y,
-          //          node[edge[i].node1].z);/*origine*/
-          //glVertex3f(node[edge[i].node2].x,node[edge[i].node2].y,
-          //           node[edge[i].node2].z);/*extremite*/
-          dx=node[edge[i].node2].x-node[edge[i].node1].x;
-          dy=node[edge[i].node2].y-node[edge[i].node1].y;
-          dz=node[edge[i].node2].z-node[edge[i].node1].z;
-          le=sqrt(dx*dx+dy*dy+dz*dz);
-          if (le>1E-6)
-	    {
-            glPushMatrix();
-            glTranslatef(node[edge[i].node1].x,node[edge[i].node1].y,
-                         node[edge[i].node1].z);
-            if (fabs(dz/le)>0.99999) 
-                {
-		angle=90*(1-dz/le);
-		glRotatef(angle,1.0,0.0,0.0);
-                }
-            else
-	        {
-		angle=57.29578*acos(dz/le);
-                if (dy<0) glRotatef(angle,-dy,dx,0);
-                else glRotatef(-angle,dy,-dx,0);
-                }
-            gluCylinder(NodeSphere, EdgeRadius, EdgeRadius,le,8,1);
-            glPopMatrix();
-            }
-	  }
-	}
-
-    //glEnd();
-    if (SHOWSIDES)
-      {
-      float normal[3];
-      for (i=0;i<NbrSides;i++) 
-        {
-        mat_ambient[0]=0.6*COULEUR[side[i].color][0];
-        mat_ambient[1]=0.6*COULEUR[side[i].color][1];
-        mat_ambient[2]=0.6*COULEUR[side[i].color][2];
-        mat_diffuse[0]=0.4*COULEUR[side[i].color][0];
-        mat_diffuse[1]=0.4*COULEUR[side[i].color][1];
-        mat_diffuse[2]=0.4*COULEUR[side[i].color][2];
-        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
-        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
-        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_gray);
-        glBegin(GL_POLYGON);
-        float v[3][3]=
-        {{node[side[i].NumNode[0]].x,node[side[i].NumNode[0]].y,
-          node[side[i].NumNode[0]].z},
-         {node[side[i].NumNode[1]].x,node[side[i].NumNode[1]].y,
-          node[side[i].NumNode[1]].z},
-         {node[side[i].NumNode[2]].x,node[side[i].NumNode[2]].y,
-	  node[side[i].NumNode[2]].z}};
-        calcNormal(v,normal);
-        for (k=0;k<side[i].NbrNodes;k++)
-	  {
-          glNormal3fv(normal);
-	  glVertex3f(node[side[i].NumNode[k]].x,node[side[i].NumNode[k]].y,
-                     node[side[i].NumNode[k]].z);/*sommet*/
-	  }
-        glEnd();
-        }
-      }
-    glFlush();
-    }
-  }
-
-/*---------------------------------------------------------------------*/
-
-void Add_Scene(def_scene *sc)
-  {
-  n_scene++;
-  SCENE[n_scene-1]=sc;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void Remove_Scene()
-  {
-  if (n_scene)
-    {
-    n_scene--;
-    //SCENE[n_scene]=0;
-    }
-  }
-
-/*---------------------------------------------------------------------*/
-/* Deuxieme partie: procedures relatives a la visualisation des scenes */
-/*---------------------------------------------------------------------*/
-
-//initialisation des couleurs;
-void Init_Couleur()
-{
-	//Noir			0
-	COULEUR[0][0]=COULEUR[0][1]=COULEUR[0][2]=0.0f;
-	//Bleu			1
-	COULEUR[1][0]=COULEUR[1][1]=0.0f;COULEUR[1][2]=1.0f;
-	//Vert			2
-	COULEUR[2][0]=0.0f;COULEUR[2][1]=1.0f;COULEUR[2][2]=0.0f;
-	//Cyan			3
-	COULEUR[3][0]=0.0f;COULEUR[3][1]=1.0f;COULEUR[3][2]=1.0f;
-	//Rouge			4
-	COULEUR[4][0]=1.0f;COULEUR[4][1]=0.0f;COULEUR[4][2]=0.0f;
-	//magenta		5
-	COULEUR[5][0]=1.0f;COULEUR[5][1]=0.0f;COULEUR[5][2]=1.0f;
-	//Brun			6 
-	COULEUR[6][0]=0.50f;COULEUR[6][1]=0.2f;COULEUR[6][2]=0.0f;
-	//Gris clair	7
-	COULEUR[7][0]=0.8f;COULEUR[7][1]=0.8f;COULEUR[7][2]=0.8f;
-	//Gris foncé	8
-	COULEUR[8][0]=0.25f;COULEUR[8][1]=0.25f;COULEUR[8][2]=0.25f;
-	//Bleu clair	9
-	COULEUR[9][0]=0.0f;COULEUR[9][1]=0.5f;COULEUR[9][2]=1.0f;
-	//vert clair	10
-	COULEUR[10][0]=0.0f;COULEUR[10][1]=1.0f;COULEUR[10][2]=0.5f;
-	//Cyan clair	11
-	COULEUR[11][0]=0.5f;COULEUR[11][1]=1.0f;COULEUR[11][2]=1.0f;
-	//rouge clair	12
-	 COULEUR[12][0]=1.0f;COULEUR[12][1]=0.5f;COULEUR[12][2]=0.5f;
-	//Magenta clair	13
-	COULEUR[13][0]=1.0f;COULEUR[13][1]=0.5f;COULEUR[13][2]=1.0f;
-	//Jaune		14
-	COULEUR[14][0]=1.0f;COULEUR[14][1]=1.0f;COULEUR[14][2]=0.0f;
-	//Blanc		15
-	COULEUR[15][0]=1.0f;COULEUR[15][1]=1.0f;COULEUR[15][2]=1.0f;
-}
-
-/*---------------------------------------------------------------------*/
-
-// changement de la couleur du canvas
-void Change_Couleur_Fond(int c)
-{
-	if ((c<0)||(c>15)) 
-	{
-		std::cout<<"couleur de fond illicite";
-		return;
-	}
-	glClearColor(COULEUR[c][0],COULEUR[c][1],COULEUR[c][2],0.0f);
-	_COULEUR_FOND=c;
-}										   
-
-/*---------------------------------------------------------------------*/
-
-// Routine de calcul des nouvelles coordonnées
-void rotation_phi_theta()
-  {
-  float cst,csf,snt,snf,csr,snr;
-  cst=(float)cos((double)_THETA);snt=(float)sin((double)_THETA);
-  csf=(float)cos((double)_PHI);snf=(float)sin((double)_PHI);
-  _EYE_X=_CENTER_X+cst*csf*_DIST;
-  _EYE_Y=_CENTER_Y+csf*snt*_DIST;
-  _EYE_Z=_CENTER_Z+snf*_DIST;
-  csr=(float)cos((double)_GAMMA);snr=(float)sin((double)_GAMMA);
-  _UP_X=snr*snt-csr*cst*snf;
-  _UP_Y=-snr*cst-csr*snf*snt;
-  _UP_Z=csr*csf;
-  _RIGHT_X=-snt*csr-cst*snf*snr;
-  _RIGHT_Y=cst*csr-snt*snf*snr;
-  _RIGHT_Z=csf*snr;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// Routine contenant les initialisations OpenGL
-void GLSetupRC() 
-  {
-  Init_Couleur();			//initialisation des couleurs
-  rotation_phi_theta();
-  glEnable(GL_DEPTH_TEST);//permet l'utilisation du Z buffer
-  GLint depth;
-  /*std::ofstream ftmp("del.del");
-  glGetIntegerv(GL_DEPTH_BITS,&depth);
-  ftmp << "depth=" << depth << "\n";
-  glGetIntegerv(GL_RED_BITS,&depth);
-  ftmp << "red_bits=" << depth << "\n";
-  glGetIntegerv(GL_GREEN_BITS,&depth);
-  ftmp << "green_bits=" << depth << "\n";
-  glGetIntegerv(GL_BLUE_BITS,&depth);
-  ftmp << "blue_bits=" << depth << "\n";
-  glGetIntegerv(GL_ALPHA_BITS,&depth);
-  ftmp << "alpha_bits=" << depth << "\n";
-  ftmp.close();*/
-
-
-  // Activation des valeurs pour les lumieres
-  // Par defaut, toutes les composantes de la lumiere sont blanches
-  glEnable(GL_LIGHTING);
-  GLfloat  ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
-  glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
-  GLfloat  diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
-  glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
-  GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 0.6f};
-  glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
-  GLfloat  lightPos[] = { 0.0f, 150.0f, 150.0f, 0.0f };
-  glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
-  glEnable(GL_LIGHT0);
-
-  // Pour que les deux faces soient traitees sur le meme pied
-  // glMightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE);
-
-  // Defintion de la brillance (les couleurs sont gerees durant le trace)
-  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
-
-  glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
-  _COULEUR_FOND=0;
-  glShadeModel (GL_FLAT);
-  } 
-
-/*---------------------------------------------------------------------*/
-
-// Routine de dessin
-void GLRenderScene()
-  {
-  // declarations
-  int i;
-  //efface l'ecran et le buffer Z
-  glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-  glLoadIdentity ();             // Nettoie la matrice courante
-  // transformation de vue
-  gluLookAt(_EYE_X,_EYE_Y,_EYE_Z,_CENTER_X,_CENTER_Y,_CENTER_Z,
-            _UP_X,_UP_Y,_UP_Z); 
-
-  // Dessin de la scène
-  for (i=0;i<n_scene;i++)
-    {
-    if (_MULTI!=0) // pour les vues multiples
-	{
-	// Vue globale 
-	glViewport(0,0,_GLOB_W/2,_GLOB_H/2); //changement de la zone de dessin
-	glLoadIdentity(); //Nettoyage de la matrice courante
-        // transformation de vue
-        gluLookAt(_EYE_X,_EYE_Y,_EYE_Z,_CENTER_X,_CENTER_Y,_CENTER_Z,
-                  _UP_X,_UP_Y,_UP_Z);
-	SCENE[i]->Trace(); // tracé de la scène
-        // Vue selon X
-	glViewport(0,_GLOB_H/2,_GLOB_W/2,_GLOB_H/2);
-	glLoadIdentity();
-        gluLookAt(_CENTER_X+_DIST,_CENTER_Y,_CENTER_Z,_CENTER_X,_CENTER_Y,
-                  _CENTER_Z,0.0,0.0,1.0);
-	SCENE[i]->Trace();
-	// Vue selon Y
-	glViewport(_GLOB_W/2,_GLOB_H/2,_GLOB_W/2,_GLOB_H/2);
-	glLoadIdentity();
-        gluLookAt(_CENTER_X,_CENTER_Y+_DIST,_CENTER_Z,_CENTER_X,_CENTER_Y,
-                  _CENTER_Z,0.0,0.0,1.0);
-	SCENE[i]->Trace();
-	// Vue selon Z
-	glViewport(_GLOB_W/2,0,_GLOB_W/2,_GLOB_H/2);
-	glLoadIdentity();
-        gluLookAt(_CENTER_X,_CENTER_Y,_CENTER_Z+_DIST,_CENTER_X,_CENTER_Y,
-                  _CENTER_Z,0.0,1.0,0.0);
-	SCENE[i]->Trace();
-	// retour a la vue de départ
-	glLoadIdentity();
-        gluLookAt(_EYE_X,_EYE_Y,_EYE_Z,_CENTER_X,_CENTER_Y,_CENTER_Z,_UP_X,
-                  _UP_Y,_UP_Z);
-	}
-    else // une seule vue 
-	{
-        // zone de vue correspondant à tout l'écran
-	glViewport(0, 0, _GLOB_W, _GLOB_H); 
-	SCENE[i]->Trace();
-        }
-     //    glPopMatrix();//on va chercher la matrice
-}
-
-glFlush(); // oblige le tracé de la scène et du repère avant de continuer    
-
-}
-
-/*---------------------------------------------------------------------*/
-
-// Routine utilisée lors du redimensionnement du canvas
-void GLResize(GLsizei w, GLsizei h)
-  {
-  _GLOB_W=w;
-  _GLOB_H=h;
-  ortho_perspective();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// Routine passant de la projection parallèle à la projection avec perspective et inversément
-void ortho_perspective() 
-  {
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity ();
-  if (_ORTHO)
-	{
-	glOrtho(-_LARGEUR/2,_LARGEUR/2,-_LARGEUR*_GLOB_H/(_GLOB_W*2),
-                _LARGEUR*_GLOB_H/(_GLOB_W*2),0.5*_DIST,1.5*_DIST);
-	}
-    else
-	{
-	glFrustum(-_LARGEUR/2,_LARGEUR/2,-_LARGEUR*_GLOB_H/(_GLOB_W*2),
-                          _LARGEUR*_GLOB_H/(_GLOB_W*2),0.5*_DIST,1.5*_DIST);
-	}
-  glMatrixMode (GL_MODELVIEW);
-  }
-
-/*---------------------------------------------------------------------*/
-
-// Routines de zoom
-
-void zoom_plus() 
-  {
-  _LARGEUR*=1.1;
-  ortho_perspective();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void zoom_moins() 
-  {
-  _LARGEUR/=1.1;
-  ortho_perspective();
-  }
-
-/*---------------------------------------------------------------------*/
-
-//Routines de changement de vue
-
-void vue_selon_x_plus() 
-  {
-  _THETA=0.0f;_PHI=0.0f;_GAMMA=0; // affectation des nouvelles valeurs
-  rotation_phi_theta(); // calcul des nouvelles coordonnées
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_selon_x_moins() 
-  {
-  _THETA=PI;_PHI=0.0;_GAMMA=0;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_selon_y_plus() 
-  {
-  _THETA=PI_2;_PHI=0.0f;_GAMMA=0;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_selon_y_moins() 
-  {
-  _THETA=-PI_2;_PHI=0.0f;_GAMMA=0;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_selon_z_plus() 
-  {
-  _THETA=0.0f;_PHI=PI_2;_GAMMA=-PI_2;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_selon_z_moins() 
-  {
-  _THETA=0.0f;_PHI=-PI_2;_GAMMA=-PI_2;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routines pour les déplacements de la caméra
-void distance_plus() 
-  {
-  _DIST*=1.1;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void distance_moins() 
-  {
-  if (_DIST>1.0) _DIST/=1.1;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void distance_plus_plus()
-  {
-  _DIST*=2;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void distance_moins_moins()
-  {
-  _DIST/=2;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routines pour un changement de vue plus fin
-void phi_plus() 
-  {
-  _PHI+=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void phi_moins() 
-  {
-  _PHI-=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void theta_plus() 
-  {
-  _THETA+=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void theta_moins() 
-  {
-  _THETA-=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void gamma_plus() 
-  {
-  _GAMMA+=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void gamma_moins() 
-  {
-  _GAMMA-=PI_10;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour definir le rayon des spheres representant les noeuds
-void SetNodeRadius(double NewRadius)
-  {
-  NodeRadius=NewRadius;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour multiplier le rayon des spheres representant les noeuds
-void MultNodeRadius(double Factor)
-  {
-  NodeRadius*=Factor;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour definir le rayon des cylindres representant les lignes
-void SetEdgeRadius(double NewRadius)
-  {
-  EdgeRadius=NewRadius;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour multiplier le rayon des cylindres representant les lignes
-void MultEdgeRadius(double Factor)
-  {
-  EdgeRadius*=Factor;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des noeuds
-void SetShowNodesOn()
-  {
-  SHOWNODES=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des noeuds
-void SetShowNodesOff()
-  {
-  SHOWNODES=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des noeuds
-void SwitchShowNodes()
-  {
-  if (SHOWNODES==0) SHOWNODES=1;
-  else SHOWNODES=0;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine renvoyant le drapeau d'affichage des noeuds
-int GetShowNodes()
-  {
-  return SHOWNODES;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des aretes
-void SetShowEdgesOn()
-  {
-  SHOWEDGES=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des aretes
-void SetShowEdgesOff()
-  {
-  SHOWEDGES=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des aretes
-void SwitchShowEdges()
-  {
-  if (SHOWEDGES==0) SHOWEDGES=1;
-  else SHOWEDGES=0;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine renvoyant le drapeau d'affichage des aretes
-int GetShowEdges()
-  {
-  return SHOWEDGES;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des faces
-void SetShowSidesOn()
-  {
-  SHOWSIDES=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des faces
-void SetShowSidesOff()
-  {
-  SHOWSIDES=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'affichage ou le masquage des faces
-void SwitchShowSides()
-  {
-  if (SHOWSIDES==0) SHOWSIDES=1;
-  else SHOWSIDES=0;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine renvoyant le drapeau d'affichage des faces
-int GetShowSides()
-  {
-  return SHOWSIDES;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routines de déplacement de la scène par rapport aux axes
-void depl_x_plus()
-  {
-  _CENTER_X-=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_x_moins()
-  {
-  _CENTER_X+=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_y_plus()
-  {_CENTER_Y-=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_y_moins()
-  {
-  _CENTER_Y+=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_z_plus()
-  {
-  _CENTER_Z-=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_z_moins()
-  {
-  _CENTER_Z+=0.1f*(float)sqrt(_LARGEUR);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routines de déplacement de la scène par rapport à l'écran 
-void depl_haut()
-  {
-  _EYE_X-=_UP_X*(_LARGEUR)*0.02;
-  _EYE_Y-=_UP_Y*(_LARGEUR)*0.02;
-  _EYE_Z-=_UP_Z*(_LARGEUR)*0.02;
-  _CENTER_X-=_UP_X*(_LARGEUR)*0.02;
-  _CENTER_Y-=_UP_Y*(_LARGEUR)*0.02;
-  _CENTER_Z-=_UP_Z*(_LARGEUR)*0.02;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_bas()
-  {
-  _EYE_X+=_UP_X*(_LARGEUR)*0.02;
-  _EYE_Y+=_UP_Y*(_LARGEUR)*0.02;
-  _EYE_Z+=_UP_Z*(_LARGEUR)*0.02;
-  _CENTER_X+=_UP_X*(_LARGEUR)*0.02;
-  _CENTER_Y+=_UP_Y*(_LARGEUR)*0.02;
-  _CENTER_Z+=_UP_Z*(_LARGEUR)*0.02;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_gauche()
-  {
-  _EYE_X+=_RIGHT_X*(_LARGEUR)*0.02;
-  _EYE_Y+=_RIGHT_Y*(_LARGEUR)*0.02;
-  _EYE_Z+=_RIGHT_Z*(_LARGEUR)*0.02;
-  _CENTER_X+=_RIGHT_X*(_LARGEUR)*0.02;
-  _CENTER_Y+=_RIGHT_Y*(_LARGEUR)*0.02;
-  _CENTER_Z+=_RIGHT_Z*(_LARGEUR)*0.02;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void depl_droite()
-  {
-  _EYE_X-=_RIGHT_X*(_LARGEUR)*0.02;
-  _EYE_Y-=_RIGHT_Y*(_LARGEUR)*0.02;
-  _EYE_Z-=_RIGHT_Z*(_LARGEUR)*0.02;
-  _CENTER_X-=_RIGHT_X*(_LARGEUR)*0.02;
-  _CENTER_Y-=_RIGHT_Y*(_LARGEUR)*0.02;
-  _CENTER_Z-=_RIGHT_Z*(_LARGEUR)*0.02;
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour l'animation
-void anime()
- { 
- int j,i;
- if (_ANIME)
-     {
-     for (j=1;j<n_scene;j++) for (i=-1;i<_N_SKIP_IMAGE;i++) SCENE[j]->Next();
-     GLRenderScene();
-     }
-  }
-
-/*---------------------------------------------------------------------*/
-
-void start_anime()
-  {
-  _ANIME=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void stop_anime()
-  {
-  _ANIME=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine de démarrage et d'arrêt de l'animation
-void start_stop_anime()
-  {
-  if(_ANIME) _ANIME=0;
-  else _ANIME=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void SetOneView()
-  {
-  _MULTI=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-void SetMultiView()
-  {
-  _MULTI=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine de démarrage et d'arrêt de l'animation
-void SwitchView()
-  {
-  if(_MULTI) _MULTI=0;
-  else _MULTI=1;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour passer à l'image suivante
-void image_suivante()
-  {
-  int j;
-  _ANIME=0;
-  for (j=1;j<n_scene;j++) SCENE[j]->Next();
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine pour passer à l'image suivante
-void image_precedente()
-  {
-  int j;
-  _ANIME=0;
-  for (j=1;j<n_scene;j++) if (SCENE[j]->GetCurImage()>1) 
-      SCENE[j]->LoadImage(SCENE[j]->GetCurImage()-1);
-  GLRenderScene();
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine utilisée pour revenir en arrière dans l'animation
-
-// routines changeant la vitesse de l'animation
-void skip_image_plus()
-  {
-  _N_SKIP_IMAGE+=2; // diminue le nombre d'images affichées
-  }
-
-/*---------------------------------------------------------------------*/
-
-void skip_image_moins()
-  {
-  _N_SKIP_IMAGE-=2; // augmente le nombre d'images affichées
-  if(_N_SKIP_IMAGE<0) _N_SKIP_IMAGE=0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine permettant de revenir à la vue de départ
-void vue_depart()
-  {
-  _THETA= 0.785398f; _PHI= 0.6154797f; _GAMMA= 0.0f;
-  rotation_phi_theta();
-  }
-
-/*---------------------------------------------------------------------*/
-
-void vue_centre()
-  {
-  if (n_scene)
-    {
-    int j;
-    float xmin,xmax,ymin,ymax,zmin,zmax;
-    float xmin2,xmax2,ymin2,ymax2,zmin2,zmax2;
-    SCENE[0]->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-    for (j=1; j<n_scene; j++)
-      {
-      SCENE[j]->GetDim(xmin2,xmax2,ymin2,ymax2,zmin2,zmax2);
-      if (xmin2<xmin) xmin=xmin2;
-      if (xmax2>xmax) xmax=xmax2;
-      if (ymin2<ymin) ymin=ymin2;
-      if (ymax2>ymax) ymax=ymax2;
-      if (zmin2<zmin) zmin=zmin2;
-      if (zmax2>zmax) zmax=zmax2;
-      }
-    _LARGEUR=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                  +(zmax-zmin)*(zmax-zmin));
-    ortho_perspective();
-    _CENTER_X=0.5*(xmax+xmin);
-    _CENTER_Y=0.5*(ymax+ymin);
-    _CENTER_Z=0.5*(zmax+zmin);
-    rotation_phi_theta();
-    GLRenderScene();
-    }
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine de sauvegarde de configuration
-int Sauve_Config(const char *nom)
-  {
-  if (nom==NULL) return 1;
-  std::ofstream fout(nom);
-  if(!fout) return 2;
-  fout<<"_ORTHO " << _ORTHO<< " SHOWNODES " << SHOWNODES
-      <<" SHOWEDGES " << SHOWEDGES << " SHOWSIDES " << SHOWSIDES << "\n";
-  fout << "NodeRadius " << NodeRadius << " EdgeRadius " << EdgeRadius << "\n";
-  fout<<"_CENTER_X "<<_CENTER_X<<" _CENTER_Y "<<_CENTER_Y
-      <<" _CENTER_Z "<<_CENTER_Z<<"\n";
-  fout<<"_THETA "<<_THETA<<" _PHI "<<_PHI<<" _GAMMA "<<_GAMMA<<"\n";
-  fout<<"_DIST "<<_DIST<<"\n";
-  fout<<" _LARGEUR "<<_LARGEUR<<"\n";
-  fout<<"_N_SKIP_IMAGE "<<_N_SKIP_IMAGE<<"\n";
-  fout<<"_COULEUR_FOND "<<_COULEUR_FOND<<"\n";
-  fout.close();
-  return 0;
-  }
-
-/*---------------------------------------------------------------------*/
-
-// routine de lecture d'une configuration
-int Lecture_Config(const char *nom_fichier)
-  {
-  char mot[1000];
-  int _FILAIRE, OK;
-  std::ifstream fin(nom_fichier);
-  if(!fin) return 1;
-  _FILAIRE=2;
-  while (!fin.rdstate())
-      {
-      fin >> mot;
-      if (!fin.rdstate())
-        {
-	OK=0;
-        if (!strcmp(mot,"_ORTHO")) { fin >> _ORTHO; OK=1; }
-        if (!strcmp(mot,"_FILAIRE")) { fin >> _FILAIRE; OK=1; }
-        if (!strcmp(mot,"SHOWNODES")) { fin >> SHOWNODES; OK=1; }
-        if (!strcmp(mot,"SHOWEDGES")) { fin >> SHOWEDGES; OK=1; }
-        if (!strcmp(mot,"SHOWSIDES")) { fin >> SHOWSIDES; OK=1; }
-        if (!strcmp(mot,"NodeRadius")) { fin >> NodeRadius; OK=1; }
-        if (!strcmp(mot,"EdgeRadius")) { fin >> EdgeRadius; OK=1; }
-        if (!strcmp(mot,"_CENTER_X")) { fin >> _CENTER_X; OK=1; }
-        if (!strcmp(mot,"_CENTER_Y")) { fin >> _CENTER_Y; OK=1; }
-        if (!strcmp(mot,"_CENTER_Z")) { fin >> _CENTER_Z; OK=1; }
-        if (!strcmp(mot,"_THETA")) { fin >> _THETA; OK=1; }
-        if (!strcmp(mot,"_PHI")) { fin >> _PHI; OK=1; }
-        if (!strcmp(mot,"_GAMMA")) { fin >> _GAMMA; OK=1; }
-        if (!strcmp(mot,"_DIST")) { fin >> _DIST; OK=1; }
-        if (!strcmp(mot,"_LARGEUR")) { fin >> _LARGEUR; OK=1; }
-        if (!strcmp(mot,"_N_SKIP_IMAGE")) { fin >> _N_SKIP_IMAGE; OK=1; }
-        if (!strcmp(mot,"_COULEUR_FOND")) { fin >> _COULEUR_FOND; OK=1; }
-        if (fin.rdstate()) OK=0;
-        }
-      }
-  fin.close();
-  if (!OK) return 2;
-  if (_FILAIRE==0) 
-      { 
-      SHOWNODES=0; SHOWEDGES=1; SHOWSIDES=1; 
-      NodeRadius=0.005*_LARGEUR; EdgeRadius=0.003*_LARGEUR;
-      }
-  if (_FILAIRE==1) 
-      { 
-      SHOWNODES=0; SHOWEDGES=1; SHOWSIDES=0; 
-      NodeRadius=0.005*_LARGEUR; EdgeRadius=0.003*_LARGEUR;
-      }
-  rotation_phi_theta();
-  ortho_perspective();
-  Change_Couleur_Fond(_COULEUR_FOND);
-  GLRenderScene();
-  return 0;
-  }
-
-/*---------------------------------------------------------------------*/
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+// EasyAnimGL.cpp: the core routines for viewing with GL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef WINDOWS
+#include <windows.h>
+#include <wingdi.h>
+#endif /* WINDOWS */
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <math.h>
+#include <fstream>
+#include <iostream>
+
+#include "EasyAnimGL.h"
+#include "EasyAnimcnv.h"
+
+// Declarations and initializations
+int i;
+
+// Variables related to the view
+enum {
+	IDX = 0,
+	IDY = 1,
+	IDZ = 2
+};
+
+GLfloat _EYE_X = 2886.75f,
+	_EYE_Y = 2886.75f,
+	_EYE_Z = 2886.75f;
+GLfloat _CENTER_X = 0.0f,
+	_CENTER_Y = 0.0f,
+	_CENTER_Z = 0.0f;
+GLfloat _THETA = M_PI*0.25f,
+	_PHI = 0.6154797;
+GLfloat _GAMMA = 0.0f;
+GLfloat _UP_X = -0.408f,
+	_UP_Y = -0.408f,
+	_UP_Z = 0.577f;
+GLfloat _RIGHT_X = -0.707f,
+	_RIGHT_Y = 0.707f,
+	_RIGHT_Z = 0.0f;
+GLfloat _DIST = 5000.0f;
+static GLsizei _GLOB_W = 0;
+static GLsizei _GLOB_H = 0;
+static GLfloat _LARGEUR = 10;
+
+GLfloat COULEUR[16][3];
+GLfloat MATERIAU[16][3][3];
+
+int SHOWNODES = 0;
+int SHOWEDGES = 1;
+int SHOWSIDES = 1;
+int _ORTHO = 1;
+int _COULEUR_FOND = 0;
+static int _N_SKIP_IMAGE = 0;
+GLint numCylinderSlices = 8;
+
+// Variables controlling aspect of edges and nodes
+GLdouble defaultNodeRadius = 0.1;
+GLdouble defaultEdgeRadius = 0.05;
+GLdouble NodeRadius = defaultNodeRadius;
+GLdouble EdgeRadius = defaultEdgeRadius;
+
+// Variables controlling animation and type of view
+int _ANIME = 0;
+int _MULTI;
+
+// Variables controlling the generation of movie/screenshots
+struct EA_screen {
+	/* get from mouse, or set to size of screen? */
+	int x, y, height, width, dh, dw;
+	unsigned char *buf;
+
+	EA_screen(void) : buf(0) {};
+	~EA_screen(void) {
+		if (buf) {
+			delete[] buf;
+		}
+	};
+};
+
+EA_screen movie;
+int _MOVIE = 0;
+int movie_n;
+// May need to redefine
+#define MOVIE_TMPDIR	"/.easyanim-XXXXXX"
+std::string movie_tmpdirname;
+std::string movie_tmpfname;
+std::string movie_outfname;
+std::string movie_ppm2movie_fmt;
+
+// Variables controlling the generation of pictures
+EA_screen picture;
+int picture_n = 0;
+std::string picture_fname = "easyanim";
+
+// Variables related to the scenes
+#define NSCENES	10
+def_scene *SCENE[NSCENES];
+int n_scene = 0;
+
+// Rotation angle increment; default: 10 deg
+double rotangle = M_PI/18.;
+
+void
+set_rotangle(double angle)
+{
+	rotangle = angle;
+}
+
+const double &
+get_rotangle(void)
+{
+	return rotangle;
+}
+
+// Routine to normalize a vector
+static void
+ReduceToUnit(float vector[3])
+{
+	float length;
+
+	// Calculate the length of the vector
+	length = (float)sqrt(vector[0]*vector[0]
+				+ vector[1]*vector[1]
+				+ vector[2]*vector[2]);
+
+	// Keep the program from blowing up by providing an acceptable
+	// value for vectors that may result too close to zero.
+	if (length == 0.0f) {
+		length = 1.0f;
+	}
+
+	// Dividing each element by the length will result in a
+	// unit normal vector.
+	vector[0] /= length;
+	vector[1] /= length;
+	vector[2] /= length;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de calcul du vecteur normal d'une surface
+static void
+calcNormal(float v[3][3], float out[3])
+{
+	float v1[3],v2[3];
+	static const int x = 0;
+	static const int y = 1;
+	static const int z = 2;
+
+	// Calcul deux vecteurs à partir des trois points
+	v1[x] = v[0][x] - v[1][x];
+	v1[y] = v[0][y] - v[1][y];
+	v1[z] = v[0][z] - v[1][z];
+
+	v2[x] = v[1][x] - v[2][x];
+	v2[y] = v[1][y] - v[2][y];
+	v2[z] = v[1][z] - v[2][z];
+
+	// Take the cross product of the two vectors to get
+	// the normal vector which will be stored in out
+	out[x] = v1[y]*v2[z] - v1[z]*v2[y];
+	out[y] = v1[z]*v2[x] - v1[x]*v2[z];
+	out[z] = v1[x]*v2[y] - v1[y]*v2[x];
+
+	// normalise le vecteur
+	ReduceToUnit(out);
+}
+
+/*********************************************************************/
+
+std::istream&
+toeol(std::istream &stream)
+{
+	char c;
+	do {
+		stream.get(c);
+	} while ((c != '\n') && (!stream.rdstate()));
+
+	return stream;
+}
+
+std::istream&
+skipremark(std::istream &stream)
+{
+	while (stream.peek() == '#') {
+		stream >> toeol;
+	}
+
+	return stream;
+}
+
+/***************************************************************************/
+
+/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
+   ou plusieurs espaces et tabulations */
+int
+GetWordsInLine(std::istream &s, strvec& Mot)
+{
+	int size = Mot.size(), mot = 0;
+
+	// allow one-line unix-style comments
+	skipremark(s);
+	for (;;) {
+		for (;;) {
+			int c = s.peek();
+			if (!isspace(c)) {
+				break;
+			}
+			s.get();
+			if (c == '\n') {
+				return 0;
+			}
+		}
+
+		if (mot < size) {
+			s >> Mot[mot++];
+		} else {
+			std::string str;
+			s >> str;
+			Mot.insert(Mot.end(), str);
+		}
+	}
+
+	return 0;
+} // fin de GetWords
+
+/*---------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------*/
+/*     Premiere partie: procedures generales relatives aux scenes      */
+/*---------------------------------------------------------------------*/
+
+// destructeur
+def_scene::def_scene(void)
+: hidden(false)
+{
+	NbrImages = 0;
+	CurImage = 0;
+	xmin = 0.0;
+	xmax = 0.0;
+	ymin = 0.0;
+	ymax = 0.0;
+	zmin = 0.0;
+	zmax = 0.0;
+
+	/* prepare the default node property */
+	NodeProp *p = new NodeProp(9, GLdouble(1.));
+	nodepropmap.insert(NodePropMap::value_type("default", p));
+
+	/* prepare the default edge properties, numbered from 0 to 15 */
+	for (int i = MIN_COULEUR; i <= MAX_COULEUR; i++) {
+		EdgeProp *ep = new EdgeProp(i, GLdouble(1.));
+		SideProp *sp = new SideProp(i);
+		char buf[3];
+		snprintf(buf, sizeof(buf), "%d", i);
+		edgepropmap.insert(EdgePropMap::value_type(buf, ep));
+		sidepropmap.insert(SidePropMap::value_type(buf, sp));
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// destructeur
+def_scene::~def_scene()
+{
+	for (unsigned i = 0; i < side.size(); i++) {
+		if (side[i].NumNode) {
+			delete side[i].NumNode;
+		}
+	}
+
+	for (NodePropMap::iterator i = nodepropmap.begin();
+		i != nodepropmap.end(); i++)
+	{
+		delete i->second;
+	}
+
+	for (EdgePropMap::iterator i = edgepropmap.begin();
+		i != edgepropmap.end(); i++)
+	{
+		delete i->second;
+	}
+
+	for (SidePropMap::iterator i = sidepropmap.begin();
+		i != sidepropmap.end(); i++)
+	{
+		delete i->second;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------*/
+
+void
+def_scene::GetDim(float& x1, float& x2,
+		float& y1, float& y2,
+		float& z1, float& z2)
+{
+	x1 = xmin;
+	x2 = xmax;
+	y1 = ymin;
+	y2 = ymax;
+	z1 = zmin;
+	z2 = zmax;
+}
+
+/*---------------------------------------------------------------------*/
+
+bool
+def_scene::Hidden() const
+{
+	return hidden;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+def_scene::Hide()
+{
+	hidden = true;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+def_scene::Show()
+{
+	hidden = false;
+}
+
+/*---------------------------------------------------------------------*/
+
+// Homothétie de la scène
+void
+def_scene::Homothetie(float MULT)
+{
+	// modification de la taille de l'image
+	if (MULT > 0.0f) {
+		for (unsigned i = 0; i < node.size(); i++) {
+			node[i].coords.x *= MULT;
+			node[i].coords.y *= MULT;
+			node[i].coords.z *= MULT;
+		}
+
+		xmin *= MULT;
+		xmax *= MULT;
+		ymin *= MULT;
+		ymax *= MULT;
+		zmin *= MULT;
+		zmax *= MULT;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+int
+def_scene::GetNumNodeOfName(std::string &NodeName)
+{
+	int num = -1;
+
+	for (unsigned i = 0; i < node.size(); i++) {
+		if (node[i].name == NodeName) {
+			num = i;
+		}
+	}
+
+	return num;
+}
+
+/*---------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------*/
+
+int
+def_scene::GetNbrImages()
+{
+	return NbrImages;
+}
+
+/*---------------------------------------------------------------------*/
+
+int
+def_scene::GetCurImage()
+{
+	return CurImage;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+def_scene::Next(bool /* next */)
+{
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+def_scene::LoadImage(int /* NumImage */)
+{
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de dessin
+void
+def_scene::Trace()
+{
+	// creation de la liste GL
+	int k;
+	GLfloat mat_ambient[]	= { 0.0f, 0.0f, 0.0f, 1.0f };
+	GLfloat mat_diffuse[]	= { 0.0f, 0.0f, 0.0f, 1.0f };
+	GLfloat mat_gray[]	= { 0.2f, 0.2f, 0.2f, 1.0f };
+	GLfloat mat_lightgray[]	= { 0.4f, 0.4f, 0.4f, 0.0f };
+	GLfloat mat_black[]	= { 0.0f, 0.0f, 0.0f, 0.0f };
+
+	if (!hidden) {
+		// Display the spheres at the nodes
+		if (SHOWNODES) {
+			glPushMatrix();
+			int oldcolor = -1;
+			for (unsigned i = 0; i < node.size(); i++) {
+				if (node[i].prop->radius == 0.0) {
+					continue;
+				}
+
+				if (oldcolor != node[i].prop->color) {
+					mat_ambient[0] = 0.6*COULEUR[node[i].prop->color][0];
+					mat_ambient[1] = 0.6*COULEUR[node[i].prop->color][1];
+					mat_ambient[2] = 0.6*COULEUR[node[i].prop->color][2];
+					mat_diffuse[0] = 0.4*COULEUR[node[i].prop->color][0];
+					mat_diffuse[1] = 0.4*COULEUR[node[i].prop->color][1];
+					mat_diffuse[2] = 0.4*COULEUR[node[i].prop->color][2];
+
+					glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
+					glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
+					glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_lightgray);
+
+					oldcolor = node[i].prop->color;
+				}
+
+				GLdouble radius = node[i].prop->radius;
+				if (node[i].prop->radiusAbsolute) {
+					radius *= defaultNodeRadius;
+
+				} else {
+					radius *= NodeRadius;
+				}
+				glTranslatef(node[i].coords.x,
+					node[i].coords.y,
+					node[i].coords.z);
+				gluSphere(NodeSphere, radius, 10, 10);
+				glTranslatef(-node[i].coords.x,
+					-node[i].coords.y,
+					-node[i].coords.z);
+			}
+			glPopMatrix();
+		}
+
+		// glBegin(GL_LINES);
+		if (SHOWEDGES) {
+			float angle, dx, dy, dz, le;
+			for (unsigned i = 0; i < edge.size(); i++) {
+				dx = node[edge[i].node2].coords.x
+					- node[edge[i].node1].coords.x;
+				dy = node[edge[i].node2].coords.y
+					- node[edge[i].node1].coords.y;
+				dz = node[edge[i].node2].coords.z
+					- node[edge[i].node1].coords.z;
+				le = sqrt(dx*dx + dy*dy + dz*dz);
+				if (le > 1.E-6) {
+					mat_ambient[0] = 0.6*COULEUR[edge[i].prop->color][0];
+					mat_ambient[1]=0.6*COULEUR[edge[i].prop->color][1];
+					mat_ambient[2]=0.6*COULEUR[edge[i].prop->color][2];
+					mat_diffuse[0]=0.4*COULEUR[edge[i].prop->color][0];
+					mat_diffuse[1]=0.4*COULEUR[edge[i].prop->color][1];
+					mat_diffuse[2]=0.4*COULEUR[edge[i].prop->color][2];
+					glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
+					glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
+					glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_black);
+					glPushMatrix();
+					glTranslatef(
+						node[edge[i].node1].coords.x,
+						node[edge[i].node1].coords.y,
+						node[edge[i].node1].coords.z);
+					if (fabs(dz/le) > 0.99999) {
+						angle = 90*(1 - dz/le);
+						glRotatef(angle, 1.0, 0.0, 0.0);
+
+					} else {
+						angle = 180./M_PI*acos(dz/le);
+						if (dy < 0) {
+							glRotatef(angle,
+								-dy, dx, 0);
+
+						} else {
+							glRotatef(-angle,
+								dy, -dx, 0);
+						}
+					}
+					GLdouble radius = edge[i].prop->radius;
+					if (edge[i].prop->radiusAbsolute) {
+						radius *= defaultEdgeRadius;
+
+					} else {
+						radius *= EdgeRadius;
+					}
+					gluCylinder(NodeSphere, radius, radius,
+						le, numCylinderSlices, 1);
+					glPopMatrix();
+				}
+			}
+		}
+
+		// glEnd();
+		if (SHOWSIDES) {
+			float normal[3];
+			for (unsigned i = 0; i < side.size(); i++) {
+				mat_ambient[0] = 0.6*COULEUR[side[i].prop->color][0];
+				mat_ambient[1] = 0.6*COULEUR[side[i].prop->color][1];
+				mat_ambient[2] = 0.6*COULEUR[side[i].prop->color][2];
+				mat_diffuse[0] = 0.4*COULEUR[side[i].prop->color][0];
+				mat_diffuse[1] = 0.4*COULEUR[side[i].prop->color][1];
+				mat_diffuse[2] = 0.4*COULEUR[side[i].prop->color][2];
+				glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
+				glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
+				glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_gray);
+				glBegin(GL_POLYGON);
+				float v[3][3] = {
+					{ node[side[i].NumNode[0]].coords.x,
+						node[side[i].NumNode[0]].coords.y,
+						node[side[i].NumNode[0]].coords.z },
+					{ node[side[i].NumNode[1]].coords.x,
+						node[side[i].NumNode[1]].coords.y,
+						node[side[i].NumNode[1]].coords.z },
+					{ node[side[i].NumNode[2]].coords.x,
+						node[side[i].NumNode[2]].coords.y,
+						node[side[i].NumNode[2]].coords.z }
+				};
+
+				calcNormal(v, normal);
+				for (k = 0; k < side[i].NbrNodes; k++) {
+					glNormal3fv(normal);
+					/*sommet*/
+					glVertex3f(node[side[i].NumNode[k]].coords.x,
+						node[side[i].NumNode[k]].coords.y,
+						node[side[i].NumNode[k]].coords.z);
+				}
+				glEnd();
+			}
+		}
+		glFlush();
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------*/
+void
+def_scene::ReadVol(std::string &VolFileName, def_err& err)
+{
+	// lecture du fichier *.VOL
+	char titre[BUFSIZ];
+	int k;
+	std::ifstream VolFile(VolFileName.c_str());
+	if (!VolFile) {
+		err.set(6, std::string("unable to open file \"") + VolFileName + std::string("\""));
+		return;
+	}
+
+	// Reading the title
+	VolFile.getline(titre, sizeof(titre));
+
+	// Reading the node properties
+	skipremark(VolFile);
+	while (VolFile.peek() == 'p') {
+		strvec Mot;
+		GetWordsInLine(VolFile, Mot);
+		if (Mot[0] != "prop") {
+			err.set(97, std::string("expecting node \"prop\", got \"") + Mot[0] + "\"");
+			return;
+		}
+
+		if (Mot.size() < 4) {
+			err.set(97, std::string("expecting at least 4 args in node \"prop\""));
+			return;
+		}
+
+		char *next;
+		int color = strtol(Mot[2].c_str(), &next, 10);
+		if (next == Mot[2].c_str() || next[0] != '\0') {
+			err.set(97, std::string("unable to parse color \"") + Mot[2] + "\" in node prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		if (color < MIN_COULEUR || color > MAX_COULEUR) {
+			err.set(96, std::string("invalid color \"") + Mot[2] + "\" in node prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		GLdouble radius = strtod(Mot[3].c_str(), &next);
+		if (next == Mot[3].c_str() || next[0] != '\0') {
+			err.set(97, std::string("unable to parse radius \"") + Mot[2] + "\" in node prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		NodeProp *p = new NodeProp(color, radius);
+		nodepropmap.insert(NodePropMap::value_type(Mot[1], p));
+		// TODO: check for duplicates
+		VolFile >> skipremark;
+	}
+
+	// Reading the nodes
+	int NbrNodes;
+	VolFile >> NbrNodes >> toeol;
+	if (NbrNodes <= 0) {
+		err.set(4, std::string("invalid number of nodes"));
+		return;
+	}
+
+	// Initializing the nodes
+	node.resize(NbrNodes);
+
+	// Should not fail!
+	NodePropMap::iterator defnodeprop =
+		nodepropmap.find(std::string("default"));
+	if (defnodeprop == nodepropmap.end()) {
+		err.set(98, std::string("unable to find default node property"));
+		return;
+	}
+
+	xmin = FLT_MAX;
+	xmax = -FLT_MAX;
+	ymin = FLT_MAX;
+	ymax = -FLT_MAX;
+	zmin = FLT_MAX;
+	zmax = -FLT_MAX;
+	for (unsigned i = 0; i < node.size(); i++) {
+		VolFile >> skipremark >> node[i].name
+			>> node[i].coords.x
+			>> node[i].coords.y
+			>> node[i].coords.z;
+		// TODO: check for duplicates
+		if (node[i].coords.x < xmin) {
+			xmin = node[i].coords.x;
+		}
+		if (node[i].coords.x > xmax) {
+			xmax = node[i].coords.x;
+		}
+		if (node[i].coords.y < ymin) {
+			ymin = node[i].coords.y;
+		}
+		if (node[i].coords.y > ymax) {
+			ymax = node[i].coords.y;
+		}
+		if (node[i].coords.z < zmin) {
+			zmin = node[i].coords.z;
+		}
+		if (node[i].coords.z > zmax) {
+			zmax = node[i].coords.z;
+		}
+
+		strvec Mot;
+		GetWordsInLine(VolFile, Mot);
+		if (Mot.size()) {
+			NodePropMap::iterator p = nodepropmap.find(Mot[0]);
+			/* property does not exist? */
+			if (p == nodepropmap.end()) {
+				err.set(99, std::string("unable to find node property \"") + Mot[0] + "\"");
+				return;
+			}
+			node[i].prop = p->second;
+
+		} else {
+			node[i].prop = defnodeprop->second;
+		}
+	} // endfor i
+
+	// Memory allocation for the spheres representing the nodes
+	NodeSphere = gluNewQuadric();
+	gluQuadricNormals(NodeSphere, GLU_FLAT);
+	gluQuadricTexture(NodeSphere, GL_FALSE);
+	gluQuadricOrientation(NodeSphere, GLU_OUTSIDE);
+	gluQuadricDrawStyle(NodeSphere, GLU_FILL);
+
+	// Reading the edge properties
+	skipremark(VolFile);
+	while (VolFile.peek() == 'p') {
+		strvec Mot;
+		GetWordsInLine(VolFile, Mot);
+		if (Mot[0] != "prop") {
+			err.set(97, std::string("expecting edge \"prop\", got \"") + Mot[0] + "\"");
+			return;
+		}
+
+		if (Mot.size() < 4) {
+			err.set(97, std::string("expecting at least 4 args in edge \"prop\""));
+			return;
+		}
+
+		char *next;
+		int color = strtol(Mot[2].c_str(), &next, 10);
+		if (next == Mot[2].c_str() || next[0] != '\0') {
+			err.set(97, std::string("unable to parse color \"") + Mot[2] + "\" in edge prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		if (color < MIN_COULEUR || color > MAX_COULEUR) {
+			err.set(96, std::string("invalid color \"") + Mot[2] + "\" in edge prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		GLdouble radius = strtod(Mot[3].c_str(), &next);
+		if (next == Mot[3].c_str() || next[0] != '\0') {
+			err.set(97, std::string("unable to parse radius \"") + Mot[2] + "\" in edge prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		EdgeProp *p = new EdgeProp(color, radius);
+		edgepropmap.insert(EdgePropMap::value_type(Mot[1], p));
+		// TODO: check for duplicates
+		VolFile >> skipremark;
+	}
+
+	// Reading the edges
+	int NbrEdges;
+	VolFile >> NbrEdges >> toeol;
+	if (NbrEdges < 0) {
+		err.set(4, std::string("invalid number of edges"));
+		return;
+	}
+
+	if (NbrEdges) {
+		edge.resize(NbrEdges);
+		for (unsigned i = 0; i < edge.size(); i++) {
+			std::string Node1Name, Node2Name, prop;
+			VolFile >> skipremark >> edge[i].name
+				>> Node1Name
+				>> Node2Name
+				>> prop >> toeol;
+			// TODO: check for duplicates
+			edge[i].node1 = GetNumNodeOfName(Node1Name);
+			edge[i].node2 = GetNumNodeOfName(Node2Name);
+			EdgePropMap::iterator p = edgepropmap.find(prop);
+			// property does not exist?
+			if (p == edgepropmap.end()) {
+				err.set(99, std::string("unable to find edge property \"") + prop + "\"");
+				return;
+			}
+
+			edge[i].prop = p->second;
+			if (edge[i].node1 == -1) {
+				err.set(4, std::string("unable to find node 1 \"") + Node1Name + "\"");
+				return;
+			}
+
+			if (edge[i].node2 == -1) {
+				err.set(4, std::string("unable to find node 2 \"") + Node2Name + "\"");
+				return;
+			}
+		} // endfor i
+	}
+
+	// Reading the side properties
+	skipremark(VolFile);
+	while (VolFile.peek() == 'p') {
+		strvec Mot;
+		GetWordsInLine(VolFile, Mot);
+		if (Mot[0] != "prop") {
+			err.set(97, std::string("expecting side \"prop\", got \"") + Mot[0] + "\"");
+			return;
+		}
+
+		if (Mot.size() < 3) {
+			err.set(97, std::string("expecting at least 3 args in side \"prop\""));
+			return;
+		}
+
+		char *next;
+		int color = strtol(Mot[2].c_str(), &next, 10);
+		if (next == Mot[2].c_str() || next[0] != '\0') {
+			err.set(97, std::string("unable to parse color \"") + Mot[2] + "\" in side prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		if (color < MIN_COULEUR || color > MAX_COULEUR) {
+			err.set(96, std::string("invalid color \"") + Mot[2] + "\" in side prop \"" + Mot[1] + "\"");
+			return;
+		}
+
+		SideProp *p = new SideProp(color);
+		sidepropmap.insert(SidePropMap::value_type(Mot[1], p));
+		// TODO: check for duplicates
+		VolFile >> skipremark;
+	}
+
+	// Reading the sides
+	int NbrSides;
+	VolFile >> NbrSides >> toeol;
+	if (NbrSides < 0) {
+		err.set(4, std::string("invalid number of sides"));
+		return;
+	}
+
+	if (NbrSides) {
+		side.resize(NbrSides);
+		for (unsigned i = 0; i < side.size(); i++) {
+			side[i].NumNode = 0;
+		}
+
+		for (unsigned i = 0; i < side.size(); i++) {
+			VolFile >> skipremark >> side[i].name
+				>> side[i].NbrNodes;
+			// TODO: check for duplicates
+			// NOTE: at least 3 nodes...
+			if (side[i].NbrNodes <= 2) {
+				err.set(4, std::string("need at least 3 nodes for side \"") + side[i].name + "\"");
+				return;
+			}
+			side[i].NumNode = new int[side[i].NbrNodes];
+			if (side[i].NumNode == 0) {
+				err.set(5, std::string("out of memory?"));
+				return;
+			}
+
+			for (k = 0; k < side[i].NbrNodes; k++) {
+				std::string NodeName;
+				VolFile >> NodeName;
+				side[i].NumNode[k] = GetNumNodeOfName(NodeName);
+				if (side[i].NumNode[k] == -1) {
+					err.set(4, std::string("unable to find node \"") + NodeName
+						+ "\" for side \"" + side[i].name + "\"");
+					return;
+				}
+			}
+
+			std::string prop;
+			VolFile >> prop >> toeol;
+			SidePropMap::iterator p = sidepropmap.find(prop);
+			// property does not exist?
+			if (p == sidepropmap.end()) {
+				err.set(98, std::string("unable to find side property \"") + prop
+					+ "\" for side \"" + side[i].name + "\"");
+				return;
+			}
+
+			side[i].prop = p->second;
+		} // endfor i
+	}
+	VolFile.close();
+}
+
+/*---------------------------------------------------------------------*/
+
+
+void
+Add_Scene(def_scene *sc)
+{
+	if (n_scene == sizeof(SCENE)/sizeof(SCENE[0])) {
+		std::cout << "No more scenes available" << std::endl;
+		return;
+	}
+	SCENE[n_scene++] = sc;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+Remove_Scene()
+{
+	if (n_scene > 0) {
+		n_scene--;
+		SCENE[n_scene] = 0;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+/* Deuxieme partie: procedures relatives a la visualisation des scenes */
+/*---------------------------------------------------------------------*/
+
+// initialisation des couleurs;
+void
+Init_Couleur(void)
+{
+	// Noir			0
+	COULEUR[0][0] = 0.00f;
+	COULEUR[0][1] = 0.00f;
+	COULEUR[0][2] = 0.00f;
+	// Bleu			1
+	COULEUR[1][0] = 0.00f;
+	COULEUR[1][1] = 0.00f;
+	COULEUR[1][2] = 1.00f;
+	// Vert			2
+	COULEUR[2][0] = 0.00f;
+	COULEUR[2][1] = 1.00f;
+	COULEUR[2][2] = 0.00f;
+	// Cyan			3
+	COULEUR[3][0] = 0.00f;
+	COULEUR[3][1] = 1.00f;
+	COULEUR[3][2] = 1.00f;
+	// Rouge		4
+	COULEUR[4][0] = 1.00f;
+	COULEUR[4][1] = 0.00f;
+	COULEUR[4][2] = 0.00f;
+	// Magenta		5
+	COULEUR[5][0] = 1.00f;
+	COULEUR[5][1] = 0.00f;
+	COULEUR[5][2] = 1.00f;
+	// Brun			6
+	COULEUR[6][0] = 0.50f;
+	COULEUR[6][1] = 0.20f;
+	COULEUR[6][2] = 0.00f;
+	// Gris clair		7
+	COULEUR[7][0] = 0.80f;
+	COULEUR[7][1] = 0.80f;
+	COULEUR[7][2] = 0.80f;
+	// Gris foncé		8
+	COULEUR[8][0] = 0.25f;
+	COULEUR[8][1] = 0.25f;
+	COULEUR[8][2] = 0.25f;
+	// Bleu clair		9
+	COULEUR[9][0] = 0.00f;
+	COULEUR[9][1] = 0.50f;
+	COULEUR[9][2] = 1.00f;
+	// Vert clair		10
+	COULEUR[10][0] = 0.00f;
+	COULEUR[10][1] = 1.00f;
+	COULEUR[10][2] = 0.50f;
+	// Cyan clair		11
+	COULEUR[11][0] = 0.50f;
+	COULEUR[11][1] = 1.00f;
+	COULEUR[11][2] = 1.00f;
+	// Rouge clair		12
+	COULEUR[12][0] = 1.00f;
+	COULEUR[12][1] = 0.50f;
+	COULEUR[12][2] = 0.50f;
+	// Magenta clair	13
+	COULEUR[13][0] = 1.00f;
+	COULEUR[13][1] = 0.50f;
+	COULEUR[13][2] = 1.00f;
+	// Jaune		14
+	COULEUR[14][0] = 1.00f;
+	COULEUR[14][1] = 1.00f;
+	COULEUR[14][2] = 0.00f;
+	// Blanc		15
+	COULEUR[15][0] = 1.00f;
+	COULEUR[15][1] = 1.00f;
+	COULEUR[15][2] = 1.00f;
+}
+
+/*---------------------------------------------------------------------*/
+
+// changement de la couleur du canvas
+void
+Change_Couleur_Fond(int c)
+{
+	if ((c < 0) || (c > 15)) {
+		std::cout<<"couleur de fond illicite";
+		return;
+	}
+
+	glClearColor(COULEUR[c][0], COULEUR[c][1], COULEUR[c][2],0.0f);
+	_COULEUR_FOND = c;
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routine de calcul des nouvelles coordonnées
+void
+rotation_phi_theta(void)
+{
+	float cst, csf, snt, snf, csr, snr;
+
+	cst = float(cos((double)_THETA));
+	snt = float(sin((double)_THETA));
+	csf = float(cos((double)_PHI));
+	snf = float(sin((double)_PHI));
+	_EYE_X = _CENTER_X + cst*csf*_DIST;
+	_EYE_Y = _CENTER_Y + csf*snt*_DIST;
+	_EYE_Z = _CENTER_Z + snf*_DIST;
+	csr = float(cos((double)_GAMMA));
+	snr = float(sin((double)_GAMMA));
+	_UP_X = snr*snt - csr*cst*snf;
+	_UP_Y = -snr*cst - csr*snf*snt;
+	_UP_Z = csr*csf;
+	_RIGHT_X = -snt*csr - cst*snf*snr;
+	_RIGHT_Y = cst*csr - snt*snf*snr;
+	_RIGHT_Z = csf*snr;
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routine contenant les initialisations OpenGL
+void
+GLSetupRC(void)
+{
+	Init_Couleur();			// initialisation des couleurs
+	rotation_phi_theta();
+	glEnable(GL_DEPTH_TEST);	// permet l'utilisation du Z buffer
+#if 0
+	GLint depth;
+	std::ofstream ftmp("del.del");
+	glGetIntegerv(GL_DEPTH_BITS,&depth);
+	ftmp << "depth=" << depth << "\n";
+	glGetIntegerv(GL_RED_BITS,&depth);
+	ftmp << "red_bits=" << depth << "\n";
+	glGetIntegerv(GL_GREEN_BITS,&depth);
+	ftmp << "green_bits=" << depth << "\n";
+	glGetIntegerv(GL_BLUE_BITS,&depth);
+	ftmp << "blue_bits=" << depth << "\n";
+	glGetIntegerv(GL_ALPHA_BITS,&depth);
+	ftmp << "alpha_bits=" << depth << "\n";
+	ftmp.close();
+#endif
+
+	// Activation des valeurs pour les lumieres
+	// Par defaut, toutes les composantes de la lumiere sont blanches
+	glEnable(GL_LIGHTING);
+	GLfloat  ambientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+	glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
+	GLfloat  diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+	glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
+	GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 0.6f};
+	glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
+	GLfloat  lightPos[] = { 0.0f, 150.0f, 150.0f, 0.0f };
+	glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
+	glEnable(GL_LIGHT0);
+
+	// Pour que les deux faces soient traitees sur le meme pied
+	// glMightModeli(LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+
+	// Defintion de la brillance (les couleurs sont gerees durant le trace)
+	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
+
+	glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+	_COULEUR_FOND = 0;
+	glShadeModel (GL_FLAT);
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routine de dessin
+void
+GLRenderScene(void)
+{
+	// declarations
+	int i;
+	// efface l'ecran et le buffer Z
+	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+	glLoadIdentity();		// Nettoie la matrice courante
+	// transformation de vue
+	gluLookAt(_EYE_X, _EYE_Y, _EYE_Z,
+		_CENTER_X, _CENTER_Y, _CENTER_Z,
+		_UP_X, _UP_Y, _UP_Z);
+
+	// Dessin de la scène
+	for (i = 0; i < n_scene; i++) {
+		// pour les vues multiples
+		if (_MULTI != 0) {
+			// Vue globale
+			//changement de la zone de dessin
+			glViewport(0, 0, _GLOB_W/2, _GLOB_H/2);
+			// Nettoyage de la matrice courante
+			glLoadIdentity();
+			// transformation de vue
+			gluLookAt(_EYE_X, _EYE_Y, _EYE_Z,
+				_CENTER_X, _CENTER_Y, _CENTER_Z,
+				_UP_X, _UP_Y, _UP_Z);
+			// tracé de la scène
+			SCENE[i]->Trace();
+
+			// Vue selon X
+			glViewport(0, _GLOB_H/2, _GLOB_W/2, _GLOB_H/2);
+			glLoadIdentity();
+			gluLookAt(_CENTER_X + _DIST, _CENTER_Y, _CENTER_Z,
+				_CENTER_X, _CENTER_Y, _CENTER_Z,
+				0.0, 0.0, 1.0);
+			SCENE[i]->Trace();
+
+			// Vue selon Y
+			glViewport(_GLOB_W/2, _GLOB_H/2, _GLOB_W/2, _GLOB_H/2);
+			glLoadIdentity();
+			gluLookAt(_CENTER_X, _CENTER_Y + _DIST, _CENTER_Z,
+				_CENTER_X, _CENTER_Y, _CENTER_Z,
+				0.0, 0.0, 1.0);
+			SCENE[i]->Trace();
+
+			// Vue selon Z
+			glViewport(_GLOB_W/2, 0, _GLOB_W/2, _GLOB_H/2);
+			glLoadIdentity();
+			gluLookAt(_CENTER_X, _CENTER_Y, _CENTER_Z + _DIST,
+				_CENTER_X, _CENTER_Y, _CENTER_Z,
+				0.0, 1.0, 0.0);
+			SCENE[i]->Trace();
+
+			// retour a la vue de départ
+			glLoadIdentity();
+			gluLookAt(_EYE_X, _EYE_Y, _EYE_Z,
+				_CENTER_X, _CENTER_Y, _CENTER_Z,
+				_UP_X, _UP_Y, _UP_Z);
+
+		} else {
+			// une seule vue
+			// zone de vue correspondant à tout l'écran
+			glViewport(0, 0, _GLOB_W, _GLOB_H);
+			SCENE[i]->Trace();
+		}
+
+		//    glPopMatrix();	//on va chercher la matrice
+	}
+
+	// oblige le tracé de la scène et du repère avant de continuer
+	glFlush();
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routine utilisée lors du redimensionnement du canvas
+void
+GLResize(GLsizei w, GLsizei h)
+{
+	_GLOB_W = w;
+	_GLOB_H = h;
+	ortho_perspective();
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routine passant de la projection parallèle à la projection
+// avec perspective et inversément
+void
+ortho_perspective(void)
+{
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	if (_ORTHO) {
+		glOrtho(-_LARGEUR/2, _LARGEUR/2,
+			-_LARGEUR*_GLOB_H/(_GLOB_W*2),
+			_LARGEUR*_GLOB_H/(_GLOB_W*2),
+			0.5*_DIST, 1.5*_DIST);
+
+	} else {
+		glFrustum(-_LARGEUR/2, _LARGEUR/2,
+			-_LARGEUR*_GLOB_H/(_GLOB_W*2),
+			_LARGEUR*_GLOB_H/(_GLOB_W*2),
+			0.5*_DIST, 1.5*_DIST);
+	}
+	glMatrixMode(GL_MODELVIEW);
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routines de zoom
+
+void
+zoom_plus(void)
+{
+	_LARGEUR *= 1.1;
+	ortho_perspective();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+zoom_moins(void)
+{
+	_LARGEUR /= 1.1;
+	ortho_perspective();
+}
+
+/*---------------------------------------------------------------------*/
+
+// Routines de changement de vue
+
+void
+vue_selon_x_plus(void)
+{
+	// affectation des nouvelles valeurs
+	_THETA = 0.0f;
+	_PHI = 0.0f;
+	_GAMMA = 0;
+
+	// calcul des nouvelles coordonnées
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_selon_x_moins(void)
+{
+	_THETA = M_PI;
+	_PHI = 0.0;
+	_GAMMA = 0;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_selon_y_plus(void)
+{
+	_THETA = M_PI_2;
+	_PHI = 0.0f;
+	_GAMMA = 0;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_selon_y_moins(void)
+{
+	_THETA = -M_PI_2;
+	_PHI = 0.0f;
+	_GAMMA = 0;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_selon_z_plus(void)
+{
+	_THETA = 0.0f;
+	_PHI = M_PI_2;
+	_GAMMA = -M_PI_2;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_selon_z_moins(void)
+{
+	_THETA = 0.0f;
+	_PHI = -M_PI_2;
+	_GAMMA = -M_PI_2;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routines pour les déplacements de la caméra
+void
+distance_plus(void)
+{
+	_DIST *= 1.1;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+distance_moins(void)
+{
+	if (_DIST > 1.0) {
+		_DIST /= 1.1;
+	}
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+distance_plus_plus(void)
+{
+	_DIST *= 2;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+distance_moins_moins(void)
+{
+	_DIST /= 2;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routines pour un changement de vue plus fin
+void
+phi_plus(void)
+{
+	_PHI += get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+phi_moins(void)
+{
+	_PHI -= get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+theta_plus(void)
+{
+	_THETA += get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+theta_moins(void)
+{
+	_THETA -= get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+gamma_plus(void)
+{
+	_GAMMA += get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+gamma_moins(void)
+{
+	_GAMMA -= get_rotangle();
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour definir le rayon des spheres representant les noeuds
+void
+SetNodeRadius(double NewRadius)
+{
+	defaultNodeRadius = NodeRadius = NewRadius;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour multiplier le rayon des spheres representant les noeuds
+void
+MultNodeRadius(double Factor)
+{
+	NodeRadius*=Factor;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour definir le rayon des cylindres representant les lignes
+void
+SetEdgeRadius(double NewRadius)
+{
+	defaultEdgeRadius = EdgeRadius = NewRadius;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour multiplier le rayon des cylindres representant les lignes
+void
+MultEdgeRadius(double Factor)
+{
+	EdgeRadius*=Factor;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des noeuds
+void
+SetShowNodesOn(void)
+{
+	SHOWNODES = 1;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des noeuds
+void
+SetShowNodesOff()
+{
+	SHOWNODES=0;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des noeuds
+void
+ToggleShowNodes(void)
+{
+	if (SHOWNODES == 0) {
+		SHOWNODES = 1;
+	} else {
+		SHOWNODES = 0;
+	}
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine renvoyant le drapeau d'affichage des noeuds
+int
+GetShowNodes(void)
+{
+	return SHOWNODES;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des aretes
+void
+SetShowEdgesOn(void)
+{
+	SHOWEDGES = 1;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des aretes
+void
+SetShowEdgesOff()
+{
+	SHOWEDGES = 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des aretes
+void
+ToggleShowEdges(void)
+{
+	if (SHOWEDGES == 0) {
+		SHOWEDGES = 1;
+
+	} else {
+		SHOWEDGES = 0;
+	}
+
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine renvoyant le drapeau d'affichage des aretes
+int
+GetShowEdges(void)
+{
+	return SHOWEDGES;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des faces
+void
+SetShowSidesOn(void)
+{
+	SHOWSIDES = 1;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des faces
+void
+SetShowSidesOff(void)
+{
+	SHOWSIDES = 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage des faces
+void
+ToggleShowSides(void)
+{
+	if (SHOWSIDES == 0) {
+		SHOWSIDES = 1;
+
+	} else {
+		SHOWSIDES = 0;
+	}
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine renvoyant le drapeau d'affichage des faces
+int
+GetShowSides(void)
+{
+	return SHOWSIDES;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routines de déplacement de la scène par rapport aux axes
+void
+depl_x_plus(void)
+{
+	_CENTER_X -= 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_x_moins(void)
+{
+	_CENTER_X += 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_y_plus(void)
+{
+	_CENTER_Y -= 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_y_moins(void)
+{
+	_CENTER_Y += 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_z_plus(void)
+{
+	_CENTER_Z -= 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_z_moins(void)
+{
+	_CENTER_Z += 0.1f*float(sqrt(_LARGEUR));
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+// routines de déplacement de la scène par rapport à l'écran
+void
+depl_haut(void)
+{
+	_EYE_X -= _UP_X*(_LARGEUR)*0.02;
+	_EYE_Y -= _UP_Y*(_LARGEUR)*0.02;
+	_EYE_Z -= _UP_Z*(_LARGEUR)*0.02;
+	_CENTER_X -= _UP_X*(_LARGEUR)*0.02;
+	_CENTER_Y -= _UP_Y*(_LARGEUR)*0.02;
+	_CENTER_Z -= _UP_Z*(_LARGEUR)*0.02;
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_bas(void)
+{
+	_EYE_X += _UP_X*(_LARGEUR)*0.02;
+	_EYE_Y += _UP_Y*(_LARGEUR)*0.02;
+	_EYE_Z += _UP_Z*(_LARGEUR)*0.02;
+	_CENTER_X += _UP_X*(_LARGEUR)*0.02;
+	_CENTER_Y += _UP_Y*(_LARGEUR)*0.02;
+	_CENTER_Z += _UP_Z*(_LARGEUR)*0.02;
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_gauche(void)
+{
+	_EYE_X += _RIGHT_X*(_LARGEUR)*0.02;
+	_EYE_Y += _RIGHT_Y*(_LARGEUR)*0.02;
+	_EYE_Z += _RIGHT_Z*(_LARGEUR)*0.02;
+	_CENTER_X += _RIGHT_X*(_LARGEUR)*0.02;
+	_CENTER_Y += _RIGHT_Y*(_LARGEUR)*0.02;
+	_CENTER_Z += _RIGHT_Z*(_LARGEUR)*0.02;
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+depl_droite(void)
+{
+	_EYE_X -= _RIGHT_X*(_LARGEUR)*0.02;
+	_EYE_Y -= _RIGHT_Y*(_LARGEUR)*0.02;
+	_EYE_Z -= _RIGHT_Z*(_LARGEUR)*0.02;
+	_CENTER_X -= _RIGHT_X*(_LARGEUR)*0.02;
+	_CENTER_Y -= _RIGHT_Y*(_LARGEUR)*0.02;
+	_CENTER_Z -= _RIGHT_Z*(_LARGEUR)*0.02;
+	GLRenderScene();
+}
+
+/*---------------------------------------------------------------------*/
+
+static int
+write_frame(EA_screen &screen, const char *filename)
+{
+	FILE *fout = fopen(filename, "w");
+	if (fout == NULL ) {
+		return -1;
+	}
+
+	if (screen.buf == NULL) {
+		screen.dh = screen.height - screen.y;
+		screen.dw = screen.width - screen.x;
+
+		screen.buf = new unsigned char[3*screen.dh*screen.dw];
+	}
+
+	glReadPixels(screen.x, screen.y, screen.width, screen.height,
+		GL_RGB, GL_UNSIGNED_BYTE, screen.buf);
+
+	/* flip */
+	unsigned char	*top = screen.buf,
+			*bot = screen.buf + 3*screen.dw*(screen.dh - 1);
+	for (int r = 0; r < screen.dh/2; r++) {
+		for (int c = 0; c < 3*screen.dw; c++) {
+			unsigned char v = bot[c];
+			bot[c] = top[c];
+			top[c] = v;
+		}
+		top += 3*screen.dw;
+		bot -= 3*screen.dw;
+	}
+
+	fprintf(fout, "P6\n%d %d\n%d\n", screen.dw, screen.dh, 255);
+	fwrite(screen.buf, 3*screen.dw*screen.dh, 1, fout);
+	fclose(fout);
+
+	return 0;
+}
+
+
+// routine pour l'animation
+void
+anime(void)
+{
+	if (_ANIME) {
+		for (int j = 1; j < n_scene; j++) {
+			for (int i = -1; i < _N_SKIP_IMAGE; i++) {
+				SCENE[j]->Next(_ANIME == 1);
+			}
+		}
+
+		GLRenderScene();
+
+		if (_MOVIE) {
+			char buf[BUFSIZ];
+			snprintf(buf, sizeof(buf), "%s%04d.ppm",
+				movie_tmpfname.c_str(), movie_n);
+			if (write_frame(movie, buf) == 0) {
+				movie_n++;
+
+			} else {
+				movie_n = -(++movie_n);
+				stop_movie();
+			}
+			/* else log error? */
+		}
+	}
+}
+
+bool
+is_anime(void)
+{
+	return _ANIME != 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+int
+start_anime(bool next)
+{
+	int j;
+
+	for (j = 0; j < n_scene; j++) {
+		if (SCENE[j]->GetNbrImages() > 0) {
+			break;
+		}
+	}
+
+	if (j == n_scene) {
+		return 1;
+	}
+
+	_ANIME = next ? 1 : -1;
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+stop_anime()
+{
+	_ANIME = 0;
+	if (_MOVIE) {
+		stop_movie();
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de démarrage et d'arrêt de l'animation
+int
+start_stop_anime(bool next)
+{
+	if (_ANIME) {
+		stop_anime();
+		return 0;
+	}
+
+	return start_anime(next);
+}
+
+/*---------------------------------------------------------------------*/
+
+int
+start_movie(void)
+{
+	// get from form? from tmpnam?
+	char	*tmpdir = getenv("TMPDIR");
+	if (tmpdir == NULL) {
+		tmpdir = "/tmp";
+	}
+	movie_tmpdirname = std::string(tmpdir) + MOVIE_TMPDIR;
+
+	if (mkdtemp((char *)movie_tmpdirname.c_str()) == NULL) {
+		std::cout << "Unable to create temporary directory "
+			"\"" << movie_tmpdirname.c_str() << "\"" << std::endl;
+		return 1;
+	}
+	movie_tmpfname = movie_tmpdirname + "/movie";
+	movie_outfname = "output.mpg";
+	// this could come from an environment variable? (risky...)
+	movie_ppm2movie_fmt = "ffmpeg -b 2500 -i \"%s%%04d.ppm\" -s 640x480 \"%s\"";
+
+	// get from mouse, or set to size of screen?
+	movie.x = 0;
+	movie.y = 0;
+	movie.height = _GLOB_H;
+	movie.width = _GLOB_W;
+	movie.buf = 0;
+
+	movie_n = 0;
+	_MOVIE = 1;
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+stop_movie(void)
+{
+	if (_MOVIE == 0 ) {
+		return;
+	}
+
+	_MOVIE = 0;
+	free(movie.buf);
+	movie.buf = 0;
+
+	if (movie_n > 0) {
+		// create movie
+		int rc;
+
+		unlink(movie_outfname.c_str());
+		char buf[BUFSIZ];
+		rc = snprintf(buf, sizeof(buf), movie_ppm2movie_fmt.c_str(),
+			movie_tmpfname.c_str(), movie_outfname.c_str());
+		if (rc >= (int)sizeof(buf)) {
+			std::cout << "Cannot make movie: command line too long"
+				<< std::endl;
+		} else {
+			rc = std::system(buf);
+			if (rc) {
+				std::cout << "system(" << buf << ") failed: "
+					<< strerror(errno) << std::endl;
+			}
+		}
+
+	} else {
+		movie_n = - movie_n;
+	}
+
+	char buf[BUFSIZ];
+	for (int i = movie_n; --i >= 0; ) {
+		snprintf(buf, sizeof(buf), "%s%04d.ppm",
+			movie_tmpfname.c_str(), i);
+		unlink(buf);
+	}
+
+	rmdir(movie_tmpdirname.c_str());
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de démarrage et d'arrêt de l'animation
+int
+start_stop_movie(void)
+{
+	if (_MOVIE) {
+		stop_movie();
+		return 0;
+	}
+
+	return start_movie();
+}
+
+void
+take_picture()
+{
+	if (!_MOVIE) {
+		char buf[BUFSIZ];
+
+		/* get from mouse, or set to size of screen? */
+		picture.x = 0;
+		picture.y = 0;
+		picture.height = _GLOB_H;
+		picture.width = _GLOB_W;
+		picture.buf = 0;
+
+		snprintf(buf, sizeof(buf), "%s%04d.ppm",
+			picture_fname.c_str(), picture_n);
+		(void)write_frame(picture, buf);
+		picture_n++;
+
+		delete[] picture.buf;
+		picture.buf = 0;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+SetOneView(void)
+{
+	_MULTI = 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+SetMultiView(void)
+{
+	_MULTI = 1;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de démarrage et d'arrêt de l'animation
+void
+ToggleView(void)
+{
+	if (_MULTI) {
+		_MULTI = 0;
+
+	} else {
+		_MULTI = 1;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour passer à l'image suivante
+static void
+image_next(bool next)
+{
+	_ANIME = 0;
+	for (int j = 1; j < n_scene; j++) {
+		SCENE[j]->Next(next);
+	}
+	GLRenderScene();
+}
+
+void
+image_suivante()
+{
+	image_next(true);
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour passer à l'image suivante
+void
+image_precedente()
+{
+	image_next(false);
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine utilisée pour revenir en arrière dans l'animation
+
+// routines changeant la vitesse de l'animation
+void
+skip_image_plus(void)
+{
+	// diminue le nombre d'images affichées
+	_N_SKIP_IMAGE += 2;
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+skip_image_moins(void)
+{
+	// augmente le nombre d'images affichées
+	_N_SKIP_IMAGE -= 2;
+	if(_N_SKIP_IMAGE < 0) {
+		_N_SKIP_IMAGE = 0;
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine permettant de revenir à la vue de départ
+void
+vue_depart(void)
+{
+	_THETA = 0.785398f;
+	_PHI = 0.6154797f;
+	_GAMMA = 0.0f;
+	rotation_phi_theta();
+}
+
+/*---------------------------------------------------------------------*/
+
+void
+vue_centre(void)
+{
+	if (n_scene) {
+		int j;
+		float xmin, xmax, ymin, ymax, zmin, zmax;
+		float xmin2, xmax2, ymin2, ymax2, zmin2, zmax2;
+		SCENE[0]->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+		for (j = 1; j < n_scene; j++) {
+			SCENE[j]->GetDim(xmin2, xmax2,
+				ymin2, ymax2, zmin2, zmax2);
+			if (xmin2 < xmin) {
+				xmin = xmin2;
+			}
+			if (xmax2 > xmax) {
+				xmax = xmax2;
+			}
+			if (ymin2 < ymin) {
+				ymin = ymin2;
+			}
+			if (ymax2 > ymax) {
+				ymax = ymax2;
+			}
+			if (zmin2 < zmin) {
+				zmin = zmin2;
+			}
+			if (zmax2 > zmax) {
+				zmax = zmax2;
+			}
+		}
+
+		_LARGEUR = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+		ortho_perspective();
+		_CENTER_X = (xmax + xmin)/2;
+		_CENTER_Y = (ymax + ymin)/2;
+		_CENTER_Z = (zmax + zmin)/2;
+		rotation_phi_theta();
+		GLRenderScene();
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de sauvegarde de configuration
+int
+Sauve_Config(std::string &nom)
+{
+	if (nom.c_str() == 0) {
+		return 1;
+	}
+
+	std::ofstream fout(nom.c_str());
+	if (!fout) {
+		return 2;
+	}
+
+	fout
+		<< "_ORTHO "		<< _ORTHO		<< std::endl
+		<< "SHOWREPERE "	<< is_repere()		<< std::endl
+		<< "SHOWNODES "		<< SHOWNODES		<< std::endl
+		<< "SHOWEDGES "		<< SHOWEDGES		<< std::endl
+		<< "SHOWSIDES "		<< SHOWSIDES		<< std::endl
+		<< "NodeRadius "	<< NodeRadius		<< std::endl
+		<< "EdgeRadius "	<< EdgeRadius		<< std::endl
+		<< "RepereSize "	<< get_repere_size()	<< std::endl
+		<< "_CENTER_X "		<< _CENTER_X		<< std::endl
+		<< "_CENTER_Y "		<< _CENTER_Y		<< std::endl
+		<< "_CENTER_Z "		<< _CENTER_Z		<< std::endl
+		<< "_THETA "		<< _THETA		<< std::endl
+		<< "_PHI "		<< _PHI			<< std::endl
+		<< "_GAMMA "		<< _GAMMA		<< std::endl
+		<< "_DIST "		<< _DIST		<< std::endl
+		<< "_LARGEUR "		<< _LARGEUR		<< std::endl
+		<< "_N_SKIP_IMAGE "	<< _N_SKIP_IMAGE	<< std::endl
+		<< "_COULEUR_FOND "	<< _COULEUR_FOND	<< std::endl;
+	std::string s(get_stream());
+	if (!s.empty()) {
+		fout << "STREAM "		<< s << std::endl;
+	}
+
+	fout.close();
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine de lecture d'une configuration
+int
+Lecture_Config(std::string &nom_fichier)
+{
+	std::ifstream fin(nom_fichier.c_str());
+	if (!fin) {
+		return 1;
+	}
+
+	std::string mot;
+	int _FILAIRE = 2, OK = 0;
+	while (!fin.rdstate()) {
+		fin >> mot;
+		if (!fin.rdstate()) {
+			OK = 0;
+			if (mot == "_ORTHO") {
+				fin >> _ORTHO;
+				OK = 1;
+
+			} else if (mot == "_FILAIRE") {
+				fin >> _FILAIRE;
+				OK = 1;
+
+			} else if (mot == "SHOWREPERE") {
+				bool show;
+				fin >> show;
+				repere(show);
+				OK = 1;
+
+			} else if (mot == "SHOWNODES") {
+				fin >> SHOWNODES;
+				OK = 1;
+
+			} else if (mot == "SHOWEDGES") {
+				fin >> SHOWEDGES;
+				OK = 1;
+
+			} else if (mot == "SHOWSIDES") {
+				fin >> SHOWSIDES;
+				OK = 1;
+
+			} else if (mot == "NodeRadius") {
+				fin >> NodeRadius;
+				OK = 1;
+
+			} else if (mot == "EdgeRadius") {
+				fin >> EdgeRadius;
+				OK = 2;
+
+			} else if (mot == "RepereSize") {
+				GLdouble size;
+				fin >> size;
+				set_repere_size(size);
+				OK = 1;
+
+			} else if (mot == "_CENTER_X") {
+				fin >> _CENTER_X;
+				OK = 1;
+
+			} else if (mot == "_CENTER_Y") {
+				fin >> _CENTER_Y;
+				OK = 1;
+
+			} else if (mot == "_CENTER_Z") {
+				fin >> _CENTER_Z;
+				OK = 1;
+
+			} else if (mot == "_THETA") {
+				fin >> _THETA;
+				OK = 1;
+
+			} else if (mot == "_PHI") {
+				fin >> _PHI;
+				OK = 1;
+
+			} else if (mot == "_GAMMA") {
+				fin >> _GAMMA;
+				OK = 1;
+
+			} else if (mot == "_DIST") {
+				fin >> _DIST;
+				OK = 1;
+
+			} else if (mot == "_LARGEUR") {
+				fin >> _LARGEUR;
+				OK = 1;
+
+			} else if (mot == "_N_SKIP_IMAGE") {
+				fin >> _N_SKIP_IMAGE;
+				OK = 1;
+
+			} else if (mot == "_COULEUR_FOND") {
+				fin >> _COULEUR_FOND;
+				OK = 1;
+
+			} else if (mot == "STREAM") {
+				std::string stream;
+				fin >> stream;
+				set_stream(stream);
+				OK = 1;
+			}
+
+			if (fin.rdstate()) {
+				OK = 0;
+			}
+		}
+	}
+
+	fin.close();
+	if (!OK) {
+		return 2;
+	}
+
+	switch (_FILAIRE) {
+	case 0:
+		SHOWNODES = 0;
+		SHOWEDGES = 1;
+		SHOWSIDES = 1;
+
+		defaultNodeRadius = NodeRadius = 0.005*_LARGEUR;
+		defaultEdgeRadius = EdgeRadius = 0.003*_LARGEUR;
+		break;
+
+	case 1:
+		SHOWNODES = 0;
+		SHOWEDGES = 1;
+		SHOWSIDES = 0;
+		defaultNodeRadius = NodeRadius = 0.005*_LARGEUR;
+		defaultEdgeRadius = EdgeRadius = 0.003*_LARGEUR;
+		break;
+	}
+
+	rotation_phi_theta();
+	ortho_perspective();
+	Change_Couleur_Fond(_COULEUR_FOND);
+	GLRenderScene();
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
Index: src/EasyAnimGL.h
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimGL.h,v
retrieving revision 1.1.1.1
retrieving revision 1.24
diff -u -r1.1.1.1 -r1.24
--- src/EasyAnimGL.h	27 Jan 2006 19:53:25 -0000	1.1.1.1
+++ src/EasyAnimGL.h	28 Nov 2006 00:35:06 -0000	1.24
@@ -1,173 +1,262 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-// Definition of the class relative to the scenes used for wiewing
-
-#ifndef EasyAnimGLH
-#define EasyAnimGLH
-
-struct VecStruct
-  {
-    double x,y,z;
-};
-
-struct NodeStruct
-  {
-    double x,y,z;
-    int color;
-    char name[41];
-};
-
-struct EdgeStruct
-  {
-    int node1, node2;
-    int color;
-    char name[41];
-};
-
-struct SideStruct
-  {
-    int NbrNodes, *NumNode;
-    int color;
-    char name[41];
-};
-
-class def_scene
-  {
-  protected :
-  int NbrNodes,NbrEdges,NbrSides,hidden,NbrImages,CurImage;
-  NodeStruct *node; EdgeStruct *edge; SideStruct *side;
-  float xmin,xmax,ymin,ymax,zmin,zmax;
-  GLUquadricObj *NodeSphere;
-  public:
-  def_scene();
-  ~def_scene();
-  int Set(int npoint, float **point,int narr, int **arrete, 
-           int nface, int **face);
-  void GetDim(float &x1,float &x2,float &y1,float &y2,float &z1,float &z2);
-  int Hidden();
-  void Hide();
-  void Show();
-  void Homothetie(float MULT);	
-  //void Get_Point(int num,float Pt[3]);
-  int GetNumNodeOfName(const char *NodeName);
-  int GetNumEdgeOfName(const char *EdgeName);
-  int GetNumSideOfName(const char *SideName);
-  int GetNbrImages();
-  int GetCurImage();
-  virtual void Next();
-  virtual void LoadImage(int NumImage);
-  virtual void Trace();
-  void Trace2();
-  };
-
-extern GLfloat COULEUR[16][3];
-extern GLfloat MATERIAU[16][3][3];
-
-// Fonctions d'initialisation
-void Init_Couleur();
-void GLSetupRC(); 
-
-// Fonctions permettant d'ajouter et de retirer des scenes
-void Add_Scene(def_scene *sc);
-void Remove_Scene();
-
-// fonction de visualisation
-void GLRenderScene();
-
-// fonction de gestion de la fenetre
-void GLResize(GLsizei w, GLsizei h);
-void Change_Couleur_Fond(int c);
-void SetOneView();
-void SetMultiView();
-void SwitchView();
-
-//Fonctions pour gerer la dimension des noeuds et des lignes
-void SetNodeRadius(double NewRadius);
-void MultNodeRadius(double Factor);
-void SetEdgeRadius(double NewRadius);
-void MultEdgeRadius(double Factor);
-
-// Fonctions pour activer ou desactiver la vision fil de fer
-void SetShowNodesOn();
-void SetShowNodesOff();
-void SwitchShowNodes();
-int  GetShowNodes();
-void SetShowEdgesOn();
-void SetShowEdgesOff();
-void SwitchShowEdges();
-int  GetShowEdges();
-void SetShowSidesOn();
-void SetShowSidesOff();
-void SwitchShowSides();
-int  GetShowSides();
-
-// fonctions de gestion de la camera
-void ortho_perspective();
-void vue_depart();
-void vue_centre();
-void zoom_plus();
-void zoom_moins();
-void vue_selon_x_plus();
-void vue_selon_x_moins();
-void vue_selon_y_plus();
-void vue_selon_y_moins();
-void vue_selon_z_plus();
-void vue_selon_z_moins();
-void distance_plus();
-void distance_moins();
-void distance_plus_plus();
-void distance_moins_moins();
-void phi_plus();
-void phi_moins();
-void theta_plus();
-void theta_moins();
-void gamma_plus();
-void gamma_moins();
-void depl_x_plus();
-void depl_x_moins();
-void depl_y_plus();
-void depl_y_moins();
-void depl_z_plus();
-void depl_z_moins();
-void depl_haut();
-void depl_bas();
-void depl_gauche();
-void depl_droite();
-int Sauve_Config(const char *nom);
-int Lecture_Config(const char *nom_fichier);
-
-// fonctions de gestion de l'animation
-void anime();
-void start_anime();
-void stop_anime();
-void start_stop_anime();
-void image_suivante();
-void image_precedente();
-void skip_image_plus();
-void skip_image_moins();
-
-#endif
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+// Definition of the class relative to the scenes used for wiewing
+
+#ifndef EasyAnimGL_h
+#define EasyAnimGL_h
+
+#include <map>
+#include <vector>
+#include <math.h>
+
+#ifndef FLT_MAX
+#define FLT_MAX 1E+10
+#endif // FLT_MAX
+
+struct VecStruct {
+	double x,y,z;
+};
+
+struct NodeProp {
+	int color;
+	GLdouble radius;
+	bool radiusAbsolute;
+	NodeProp(int c, GLdouble r)
+		: color(c), radius(fabs(r)), radiusAbsolute(r < 0.) {};
+	~NodeProp(void) {};
+};
+
+typedef std::map<std::string, NodeProp *> NodePropMap;
+
+struct NodeStruct {
+	VecStruct coords;
+	NodeProp *prop;
+	std::string name;
+};
+
+/* NOTE: right now, it's identical to NodeProp;
+ * however, they may depart in the future */
+struct EdgeProp {
+	int color;
+	GLdouble radius;
+	bool radiusAbsolute;
+	EdgeProp(int c, GLdouble r)
+		: color(c), radius(fabs(r)), radiusAbsolute(r < 0.) {};
+	~EdgeProp(void) {};
+};
+
+typedef std::map<std::string, EdgeProp *> EdgePropMap;
+
+struct EdgeStruct {
+	int node1, node2;
+	EdgeProp *prop;
+	std::string name;
+};
+
+struct SideProp {
+	int color;
+	SideProp(int c)
+		: color(c) {};
+	~SideProp(void) {};
+};
+
+typedef std::map<std::string, SideProp *> SidePropMap;
+
+struct SideStruct {
+	int NbrNodes, *NumNode;
+	SideProp *prop;
+	std::string name;
+};
+
+class def_err {
+protected:
+	int err;
+	std::string msg;
+
+public:
+	def_err(void) : err(0) {};
+	def_err(int err, std::string& msg)
+	: err(err), msg(msg) {};
+	virtual ~def_err(void) {};
+	void set(int err) { this->err = err; };
+	void set(int err, std::string msg) { this->err = err; this->msg = msg; };
+	int geterr(void) const { return err; };
+	const std::string& getmsg(void) const { return msg; };
+};
+
+class def_scene {
+protected:
+	bool hidden;
+	int NbrImages,CurImage;
+	NodePropMap nodepropmap;
+	EdgePropMap edgepropmap;
+	SidePropMap sidepropmap;
+	std::vector<NodeStruct> node;
+	std::vector<EdgeStruct> edge;
+	std::vector<SideStruct> side;
+	float xmin,xmax,ymin,ymax,zmin,zmax;
+	GLUquadricObj *NodeSphere;
+	void ReadVol(std::string &VolFileName, def_err& err);
+public:
+	def_scene(void);
+	virtual ~def_scene(void);
+	int Set(int npoint, float **point,int narr, int **arrete, 
+		int nface, int **face);
+	void GetDim(float &x1, float &x2, float &y1, float &y2,
+		float &z1, float &z2);
+	bool Hidden(void) const;
+	void Hide(void);
+	void Show(void);
+	void Homothetie(float MULT);	
+	// void Get_Point(int num,float Pt[3]);
+	int GetNumNodeOfName(std::string &NodeName);
+	int GetNumEdgeOfName(const char *EdgeName);
+	int GetNumSideOfName(const char *SideName);
+	int GetNbrImages(void);
+	int GetCurImage(void);
+	virtual void Next(bool next = true);
+	virtual void LoadImage(int NumImage);
+	virtual void Trace(void);
+	void Trace2(void);
+};
+
+#define	MIN_COULEUR	(0)
+#define	MAX_COULEUR	(15)
+extern GLfloat COULEUR[16][3];
+extern GLfloat MATERIAU[16][3][3];
+
+// Fonctions d'initialisation
+void Init_Couleur(void);
+void GLSetupRC(void); 
+
+// Fonctions permettant d'ajouter et de retirer des scenes
+void Add_Scene(def_scene *sc);
+void Remove_Scene(void);
+
+// fonction de visualisation
+void GLRenderScene(void);
+
+// fonction de gestion de la fenetre
+void GLResize(GLsizei w, GLsizei h);
+void Change_Couleur_Fond(int c);
+void SetOneView(void);
+void SetMultiView(void);
+void ToggleView(void);
+
+//Fonctions pour gerer la dimension des noeuds et des lignes
+void SetNodeRadius(double NewRadius);
+void MultNodeRadius(double Factor);
+void SetEdgeRadius(double NewRadius);
+void MultEdgeRadius(double Factor);
+
+// Fonctions pour activer ou desactiver la vision fil de fer
+void SetShowNodesOn(void);
+void SetShowNodesOff(void);
+void ToggleShowNodes(void);
+int GetShowNodes(void);
+void SetShowEdgesOn(void);
+void SetShowEdgesOff(void);
+void ToggleShowEdges(void);
+int GetShowEdges(void);
+void SetShowSidesOn(void);
+void SetShowSidesOff(void);
+void ToggleShowSides(void);
+int GetShowSides(void);
+
+// fonctions de gestion de la camera
+void ortho_perspective(void);
+void vue_depart(void);
+void vue_centre(void);
+void zoom_plus(void);
+void zoom_moins(void);
+void vue_selon_x_plus(void);
+void vue_selon_x_moins(void);
+void vue_selon_y_plus(void);
+void vue_selon_y_moins(void);
+void vue_selon_z_plus(void);
+void vue_selon_z_moins(void);
+void distance_plus(void);
+void distance_moins(void);
+void distance_plus_plus(void);
+void distance_moins_moins(void);
+void set_rotangle(double angle);
+const double &get_rotangle(void);
+void phi_plus(void);
+void phi_moins(void);
+void theta_plus(void);
+void theta_moins(void);
+void gamma_plus(void);
+void gamma_moins(void);
+void depl_x_plus(void);
+void depl_x_moins(void);
+void depl_y_plus(void);
+void depl_y_moins(void);
+void depl_z_plus(void);
+void depl_z_moins(void);
+void depl_haut(void);
+void depl_bas(void);
+void depl_gauche(void);
+void depl_droite(void);
+int Sauve_Config(std::string &nom);
+int Lecture_Config(std::string &nom_fichier);
+
+// fonctions de gestion de l'animation
+void anime(void);
+bool is_anime(void);
+int start_anime(bool next);
+void stop_anime(void);
+int start_stop_anime(bool next);
+int start_movie(void);
+void stop_movie(void);
+int start_stop_movie(void);
+void take_picture(void);
+void image_suivante(void);
+void image_precedente(void);
+void skip_image_plus(void);
+void skip_image_moins(void);
+
+extern std::istream & toeol(std::istream &stream);
+extern std::istream & skipremark(std::istream &stream);
+
+typedef std::vector<std::string> strvec;
+
+int GetWordsInLine(std::istream &s, strvec& Mot);
+
+#endif // EasyAnimGL_h
Index: src/EasyAnimcmdw.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimcmdw.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.27
diff -u -r1.1.1.1 -r1.27
--- src/EasyAnimcmdw.cpp	27 Jan 2006 19:53:25 -0000	1.1.1.1
+++ src/EasyAnimcmdw.cpp	29 Nov 2006 01:44:20 -0000	1.27
@@ -1,1013 +1,1644 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-#include <v/vnotice.h>	// for vNoticeDialog
-#include <v/vkeys.h>	// to map keys
-#include <v/vfilesel.h> // for file select
-#include <v/vreply.h> // for file select
-
-#include "EasyAnimcmdw.h"     // our header
-#include "EasyAnimcnv.h"
-#include <fstream>
-#include <math.h>
-
-// Déclarations et initialisations
-extern int retval;
-
-int _INIT_VOL=0;
-int LOOP=0;
-
-//	Start defines for the main window with 100
-
-//@V@:BeginIDs
-    enum {
-	m_FirstCmd = 100, // Dummy Command
-    blanc,
-        m_open2,
-        m_open3,
-	m_vue_dep,
-	zoom_in,
-	zoom_out,
-	m_start_stop,
-	m_suiv,
-	m_prec,
-	m_fast,
-	m_slow,
-	m_shownodes,
-	m_showedges,
-	m_showsides,
-	m_repere,
-	m_reperep,
-	m_reperem,
-	m_noderadp,
-	m_noderadm,
-	m_lineradp,
-	m_lineradm,
-	m_vuexp,
-	m_vuexm,
-	m_vueyp,
-	m_vueym,
-	m_vuezp,
-	m_vuezm,
-	m_vuecentre,
-	m_phiplus,
-	m_phimoins,
-	m_thetaplus,
-	m_thetamoins,
-	m_gammaplus,
-	m_gammamoins,
-	m_distpl,
-	m_distpp,
-	m_distm,
-	m_distmm,
-	m_dephaut,
-	m_depbas,
-	m_depgauche,
-	m_depdroite,
-	m_multi,
-	m_couleur,
-	m_loadmode,
-	cmdAuxTimer,	// AuxTimer
-	m_lblspeed,     // the label for the animation speed
-	m_sldspeed,     // the slider for the animation speed
-	m_lblprogress,  // the label for the animation progress bar
-	m_sldprogress,  // the slider for the animation progress bar
-        m_loop,
-        m_info,
-	blkLast		// Last item
-      };
-//@V@:EndIDs
-
-//@V@:BeginPulldownMenu FileMenu
-// Définition du Menu "File"
-    static vMenu FileMenu[] =
-      {
-	{"&Open animation (vol-van)", M_Open, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"&Open modal analysis (vol-vmo)", m_open2, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"&Open modal analysis (universal)", m_open3, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"&Close...", M_CloseFile, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
-	{"Save &Config", M_Save, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
-	{"&Print", M_Print, notSens, notChk, noKeyLbl, noKey, noSub},
-	{"-", M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
-	{"E&xit", M_Exit, isSens, notChk, noKeyLbl, noKey, noSub},
-	{NULL} // dernière instruction des menus
-      };
-//@V@:EndPulldownMenu
-
-//@V@:BeginPulldownMenu OptionMenu
-// Définition du menu "Options"
-	static vMenu OptionMenu[] =
-	  {
-	{"&Background Color...", m_couleur, isSens, notChk, noKeyLbl, noKey, noSub},
-	{"&Load mode...", m_loadmode, isSens, notChk, noKeyLbl, noKey, noSub},
-	//{"Hide/show &Nodes", m_shownodes, isSens, notChk, noKeyLbl, noKey, noSub},
-        //{"Hide/show &Edges", m_showedges, isSens, notChk, noKeyLbl, noKey, noSub},
-        //{"Hide/show &Sides", m_showsides, isSens, notChk, noKeyLbl, noKey, noSub},
-	//{"Hide/show &Mark", m_repere, isSens, notChk, noKeyLbl, noKey, noSub},
-	{NULL}
-	  };
-//@V@:EndPulldownMenu
-
-//@V@:BeginMenu StandardMenu
-// Définition de la barre de menu
-    static vMenu StandardMenu[] =
-      {
-	{"&File", M_File, isSens, notUsed, notUsed, noKey, &FileMenu[0]},
-	{"&Options", M_Options, isSens, notUsed, notUsed, noKey, &OptionMenu[0]},
-	{NULL}
-      };
-//@V@:EndMenu
-
-
-//@V@:BeginCmdPane ToolBar
-// Définition de la barre d'outil
-    static CommandObject DisplaceBar[] =
-      {
-	{C_IconButton,zoom_in,zoom_in,"",(void*)&zpicon,CA_None,isSens,NoFrame,0,0,0,"Zoom +"},
-	{C_IconButton,zoom_out,zoom_out,"",(void*)&zmicon,CA_None,isSens,NoFrame,0,0,0,"Zoom -"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},  
-		{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-		{C_IconButton,m_vuecentre,m_vuecentre,"",(void*)&vuecentricon,CA_None,isSens,NoFrame,0,0,0,"Centered View"},
-		{C_IconButton,m_dephaut,m_dephaut,"",(void*)&dephauticon,CA_None,isSens,NoFrame,0,0,0,"Up Move"},
-		{C_IconButton,m_depbas,m_depbas,"",(void*)&depbasicon,CA_None,isSens,NoFrame,0,0,0,"Down move"},
-		{C_IconButton,m_depgauche,m_depgauche,"",(void*)&depgaucheicon,CA_None,isSens,NoFrame,0,0,0,"Left Move"},
-		{C_IconButton,m_depdroite,m_depdroite,"",(void*)&depdroiteicon,CA_None,isSens,NoFrame,0,0,0,"Right Move"},
-	{C_ToggleIconButton,m_multi,0,"",(void*)&multiicon,CA_None,isSens,NoFrame,0,0,0,"MDI"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-	{C_ToggleIconButton,m_repere,m_repere,"",(void*)&repicon,CA_None,isSens,NoFrame,0,0,0,"Show marker"},
-	{C_IconButton,m_reperep,m_reperep,"",(void*)&reppicon,CA_None,isSens,NoFrame,0,0,0,"Increase size of marker"},
-	{C_IconButton,m_reperem,m_reperem,"",(void*)&repmicon,CA_None,isSens,NoFrame,0,0,0,"Decrease size of marker"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-	{C_ToggleIconButton,m_showedges,m_showedges,"",(void*)&lineicon,CA_None,isSens,NoFrame,0,0,0,"Show edges"},
-	{C_IconButton,m_lineradp,m_lineradp,"",(void*)&lineradpicon,CA_None,isSens,NoFrame,0,0,0,"Increase radius of edges"},
-	{C_IconButton,m_lineradm,m_lineradm,"",(void*)&lineradmicon,CA_None,isSens,NoFrame,0,0,0,"Decrease radius of edges"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-	{C_ToggleIconButton,m_shownodes,m_shownodes,"",(void*)&nodeicon,CA_None,isSens,NoFrame,0,0,0,"Show nodes"},
-	{C_IconButton,m_noderadp,m_noderadp,"",(void*)&noderadpicon,CA_None,isSens,NoFrame,0,0,0,"Increase size of nodes"},
-	{C_IconButton,m_noderadm,m_noderadm,"",(void*)&noderadmicon,CA_None,isSens,NoFrame,0,0,0,"Decrease size of nodes"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-	{C_ToggleIconButton,m_showsides,m_showsides,"",(void*)&sideicon,CA_None,isSens,NoFrame,0,0,0,"Show sides"},
-	//{C_IconButton,m_distmm,m_distmm,"",(void*)&distmmicon,CA_None,isSens,NoFrame,0,0,0,"Decrease the distance of the camera"},
-	//{C_IconButton,m_distm,m_distm,"",(void*)&distmicon,CA_None,isSens,NoFrame,0,0,0,"Decrease the distance of the camera"},
-	//{C_IconButton,m_distpl,m_distpl,"",(void*)&distplicon,CA_None,isSens,NoFrame,0,0,0,"Increase the distance of the camera"},
-	//{C_IconButton,m_distpp,m_distpp,"",(void*)&distppicon,CA_None,isSens,NoFrame,0,0,0,"Increase the distance of the camera"},
-	{C_EndOfList,0,0,0,0,CA_None,0,0,0} // dernière instruction des listes
-      };
-
-//@V@:EndCmdPane
-//@V@:BeginCmdPane CommandBar
-	static CommandObject RotateBar[] =
-	{ 
-		{C_IconButton,m_vue_dep,m_vue_dep,"",(void*)&vuedepicon,CA_None,isSens,NoFrame,0,0,0,"Start View"},
-		{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-		{C_IconButton,m_vuexp,m_vuexp,"",(void*)&vuexpicon,CA_None,isSens,NoFrame,0,0,0,"X + View"},
-		{C_IconButton,m_vuexm,m_vuexm,"",(void*)&vuexmicon,CA_None,isSens,NoFrame,0,0,0,"X - View"},
-		{C_IconButton,m_vueyp,m_vueyp,"",(void*)&vueypicon,CA_None,isSens,NoFrame,0,0,0,"Y + View"},
-		{C_IconButton,m_vueym,m_vueym,"",(void*)&vueymicon,CA_None,isSens,NoFrame,0,0,0,"Y - View"},
-		{C_IconButton,m_vuezp,m_vuezp,"",(void*)&vuezpicon,CA_None,isSens,NoFrame,0,0,0,"Z + View"},
-		{C_IconButton,m_vuezm,m_vuezm,"",(void*)&vuezmicon,CA_None,isSens,NoFrame,0,0,0,"Z - View"},
-		{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},
-		{C_IconButton,m_phiplus,m_phiplus,"",(void*)&phiplusicon,CA_None,isSens,NoFrame,0,0,0,"Phi + Rotation"},
-		{C_IconButton,m_phimoins,m_phimoins,"",(void*)&phimoinsicon,CA_None,isSens,NoFrame,0,0,0,"Phi - Rotation"},
-		{C_IconButton,m_thetaplus,m_thetaplus,"",(void*)&thetaplusicon,CA_None,isSens,NoFrame,0,0,0,"Theta + Rotation"},
-		{C_IconButton,m_thetamoins,m_thetamoins,"",(void*)&thetamoinsicon,CA_None,isSens,NoFrame,0,0,0,"Theta - Rotation"},
-		{C_IconButton,m_gammaplus,m_gammaplus,"",(void*)&gammaplusicon,CA_None,isSens,NoFrame,0,0,0,"Gamma + Rotation"},
-		{C_IconButton,m_gammamoins,m_gammamoins,"",(void*)&gammamoinsicon,CA_None,isSens,NoFrame,0,0,0,"Gamma - Rotation"},
-		{C_EndOfList,0,0,0,0,CA_None,0,0,0}
-	};
-//@V@:EndCmdPane
-
-// Définition de la barre d'outil
-    static CommandObject AnimBar[] =
-      {
-	//	{C_IconButton,m_slow,m_slow,"",(void*)&slowicon,CA_None,isSens,NoFrame,0,0,0,"Slow animation"},
-	//	{C_IconButton,m_fast,m_fast,"",(void*)&fasticon,CA_None,isSens,NoFrame,0,0,0,"Fast animation"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},   
-	{C_Label,m_lblspeed,0,"Speed",NoList,CA_None,isSens,NoFrame,0,0,0,""},
-	{C_Slider,m_sldspeed,0,"",NoList,CA_Horizontal,isSens,NoFrame,0,0,0,""},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},   
-	{C_Label,m_lblprogress,0,"Progress",NoList,CA_None,isSens,NoFrame,0,0,0,""},
-       	{C_IconButton,m_prec,m_prec,"",(void*)&precicon,CA_None,isSens,NoFrame,0,0,0,"Previous Frame"}, 
-	{C_Slider,m_sldprogress,0,"",NoList,CA_Horizontal,isSens,NoFrame,0,0,0,""},
-	{C_IconButton,m_suiv,m_suiv,"",(void*)&suivicon,CA_None,isSens,NoFrame,0,0,0,"Next Frame"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},   
-	{C_ToggleIconButton,m_start_stop,0,"",(void*)&ssicon,CA_None,isSens,NoFrame,0,0,0,"Start/Stop"},
-	{C_Blank,blanc,0," ",NoList,CA_None,isSens,NoFrame,0,0,5},   
-	{C_ToggleButton,m_loop,0,"LOOP",NoList,CA_None,isSens,NoFrame,0,0},   
-	{C_EndOfList,0,0,0,0,CA_None,0,0,0} // derniere instruction des listes
-      };
-
-//@V@:BeginCmdPane InfoBar
-static vStatus InfoBar[] =
- { 
-   {"No application yet",m_info,CA_None,isSens,500},
-   {0,0,0,0,0}
- };
-
-//====================>>> myAuxTimer::TimerTick <<<====================
-  void myAuxTimer::TimerTick()
-  {
-	cmdw->WindowCommand(cmdAuxTimer, cmdAuxTimer, C_Button); // update clock
-  }
-
-
-//====================>>> myCmdWindow::myCmdWindow <<<====================
-// Définition du contenu de la fenêtre de commandes
-  myCmdWindow::myCmdWindow(char* name, int width, int height) :
-    vCmdWindow(name, width, height)
-  {
-    UserDebug1(Constructor,"myCmdWindow::myCmdWindow(%s) Constructor\n",name)
-    
-	// The Menu Bar
-    myMenu = new vMenuPane(StandardMenu);
-    AddPane(myMenu);
-
-	// The Canvas
-    myCanvas = new myOGLCanvasPane;
-    AddPane(myCanvas);
-
-	// The Timer
-	_auxTimer = new myAuxTimer(this);	// create aux timer
-    _auxTimer->TimerSet(1);		// 1/2 second intervals
-
-    // The Command Pane
-    DisplacePane = new vCommandPane(DisplaceBar);
-    AddPane(DisplacePane);
-     
-    // The second Command Pane
-    RotatePane = new vCommandPane(RotateBar);
-    AddPane(RotatePane);
-     
-    // The second Command Pane
-    AnimPane = new vCommandPane(AnimBar);
-    AddPane(AnimPane);
-     
-    // The status Pane
-    InfoPane = new vStatusPane(InfoBar);
-    AddPane(InfoPane);
-	
-    // Associated dialogs
-    myMDlg = new myModalDialog(this,name);
-
-    // Show Window
-    ShowWindow();
-    WindowCommand(cmdAuxTimer,cmdAuxTimer,C_Button);	// update clock
-    
-    SetValue(m_sldspeed,100,Value);
-    SetValue(m_sldprogress,0,Value);
-    SetValue(m_multi,0,Value);
-    SetValue(m_repere,1,Value);
-    SetValue(m_shownodes,0,Value);
-    SetValue(m_showsides,1,Value);
-    SetValue(m_showedges,1,Value);
-    }
-
-//====================>>> myCmdWindow::~myCmdWindow <<<====================
-// Destructeur de la fenêtre de commandes
-	myCmdWindow::~myCmdWindow()
-  {
-    UserDebug(Destructor,"myCmdWindow::~myCmdWindow() destructor\n")
-
-    // Now put a delete for each new in the constructor.
-
-    delete myMenu;
-    delete myCanvas;
-    delete DisplacePane;
-    delete RotatePane;
-    delete AnimPane;
-    delete myMDlg;
-    _auxTimer->TimerStop();	// end it
-    delete _auxTimer;	// free it
-
-
-  }
-
-//===================>>> myCmdWindow::Lecture <<<======================
-  void myCmdWindow::Lecture(char* fichier_config)
-  {
-	  Lecture_Config(fichier_config);
-  }
-
-  
-//===================>>> myCmdWindow::OpenFile <<<======================
-// ouverture des fichier ".vol" et ".van"
-
-  void myCmdWindow::WindowCommand(ItemVal id, ItemVal val, CmdType cType)
-  {
-  // Default: route menu and toolbar commands here
-
-  static char nomfichiervol[200]="";
-  vNoticeDialog note(this);
-  char Utiltmp[40];
-	
-  UserDebug1(CmdEvents,"myCmdWindow:WindowCommand(%d)\n",id)
-
-  // instructions exécutées lors de l'activation des menu, boutons, ...
-  switch (id)
-    {
-    case M_Open:// This demos vFileSelect dialog
-      {
-      char name[200] = "";        // start out with null name
-      vFileSelect fsel(this);     // an instance of vFileSelect
-      int fI = 0;		      // Filter index
-      static char* filter[]={"*.vol",0};    // Filter for file select
-      int ans;  
-      // Show the file select dialog
-      ans = fsel.FileSelect("Open file",name,99,filter,fI);
-      if (ans && *name)   // User picked a file name
-	  {
-          if (s2!=NULL) { Remove_Scene(); delete s2; s2=NULL; }
-          if (s3!=NULL) { Remove_Scene(); delete s3; s3=NULL; }
-          if (s4!=NULL) { Remove_Scene(); delete s4; s4=NULL; }
-          strcpy(nomfichiervol,name);
-          int ec;
-          s2=new def_volvan(nomfichiervol,ec);
-          if (s2==NULL) note.Notice("Impossible d'allouer s2");
-          if ((s2!=NULL) && (ec<4))
-            {
-            Add_Scene(s2);
-            float xmin,xmax,ymin,ymax,zmin,zmax,diag;
-            // Remise a l'echelle du repere
-            s1->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            s1->Homothetie(1/xmax);
-            s2->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            diag=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                    +(zmax-zmin)*(zmax-zmin));
-            s1->Homothetie(0.2*diag);
-            if ((ec==1)||(ec==3)) 
-                {
-                vue_centre(); 
-                SetNodeRadius(0.005*diag); 
-                SetEdgeRadius(0.003*diag);
-		}
-            GLRenderScene();
-            SetValue(m_sldprogress,0,Value);
-            SetValue(m_shownodes,GetShowNodes(),Value);
-            SetValue(m_showedges,GetShowEdges(),Value);
-            SetValue(m_showsides,GetShowSides(),Value);
-            char Message[80];
-            strcpy(Message,"Anim - Number of images=");
-            sprintf(Utiltmp,"%4d",s2->GetNbrImages());
-            strcat(Message,Utiltmp);
-            SetString(m_info,Message);
-            }
-          else { delete s2; s2=NULL; }
-          if ((ec==1)||(ec==3)) 
-            note.Notice ("Configuration (cfg) file not found or not conform");
-          if ((ec==2)||(ec==3)) 
-              note.Notice ("Animation (van) file not found or corrupted");
-          if ((ec==4)||(ec==6)) 
-              note.Notice ("Image (vol) file not found or corrupted");
-          if (ec==5) 
-              note.Notice ("Memory allocation problems");
-          }
-      break;
-      }
-
-    case m_open2:// Opening a modal file
-      {
-      char name[200] = "";        // start out with null name
-      vFileSelect fsel(this);     // an instance of vFileSelect
-      int fI = 0;		      // Filter index
-      static char* filter[]={"*.vol",0};    // Filter for file select
-      int ans;  
-      // Show the file select dialog
-      ans = fsel.FileSelect("Open file",name,99,filter,fI);
-      if (ans && *name)   // User picked a file name
-	  {
-          if (s2!=NULL) { Remove_Scene(); delete s2; s2=NULL; }
-          if (s3!=NULL) { Remove_Scene(); delete s3; s3=NULL; }
-          if (s4!=NULL) { Remove_Scene(); delete s4; s4=NULL; }
-          strcpy(nomfichiervol,name);
-          int ec;
-          s3=new def_volvmo(nomfichiervol,ec);
-          if (s3==NULL) note.Notice("Impossible d'allouer s3");
-          if ((s3!=NULL) && (ec<4))
-            {
-            Add_Scene(s3);
-            float xmin,xmax,ymin,ymax,zmin,zmax,diag;
-            // Remise a l'echelle du repere
-            s1->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            s1->Homothetie(1/xmax);
-            s3->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            diag=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                    +(zmax-zmin)*(zmax-zmin));
-            s1->Homothetie(0.2*diag);
-            if ((ec==1)||(ec==3)) 
-                {
-                vue_centre(); 
-                SetNodeRadius(0.005*diag); 
-                SetEdgeRadius(0.003*diag);
-		}
-            GLRenderScene();
-            SetValue(m_sldprogress,0,Value);
-            SetValue(m_shownodes,GetShowNodes(),Value);
-            SetValue(m_showedges,GetShowEdges(),Value);
-            SetValue(m_showsides,GetShowSides(),Value);
-            if (ec<2)
-              {
-              char Message[80];
-              strcpy(Message,"Modal - Freq(Hz)=");
-              sprintf(Utiltmp,"%8.4f",s3->freq);
-              strcat(Message,Utiltmp);
-              strcat(Message," Damp(%)=");
-              sprintf(Utiltmp,"%8.4f",100*s3->amor);
-              strcat(Message,Utiltmp);
-              SetString(m_info,Message);
-              }
-            else SetString(m_info,"Modal - No mode");
-            }
-          else { delete s3; s3=NULL; }
-          if ((ec==1)||(ec==3)) 
-            note.Notice ("Configuration (cfg) file not found or not conform");
-          if ((ec==2)||(ec==3)) 
-              note.Notice ("Mode (vmo) file not found or corrupted");
-          if ((ec==4)||(ec==6)) 
-              note.Notice ("Image (vol) file not found or corrupted");
-          if (ec==5) 
-              note.Notice ("Memory allocation problems");
-          }
-      break;
-      }
-
-    case m_open3:// Opening a modal file
-      {
-      char name[200] = "";        // start out with null name
-      vFileSelect fsel(this);     // an instance of vFileSelect
-      int fI = 0;		      // Filter index
-      static char* filter[]={"*.unv;*.uff","*",0};    // Filter for file select
-      int ans;  
-      // Show the file select dialog
-      ans = fsel.FileSelect("Open geometry file",name,99,filter,fI);
-      if (ans && *name)   // User picked a file name
-	  {
-          if (s2!=NULL) { Remove_Scene(); delete s2; s2=NULL; }
-          if (s3!=NULL) { Remove_Scene(); delete s3; s3=NULL; }
-          if (s4!=NULL) { Remove_Scene(); delete s4; s4=NULL; }
-          strcpy(nomfichiervol,name);
-          note.Notice ("Now choose the uff modal file");
-          char name2[200] = "";
-          ans = fsel.FileSelect("Open modal file",name,99,filter,fI);
-          if (ans && *name) { strcpy(name2,name); }
-          int ec;
-          s4=new def_uff(nomfichiervol,name2,ec);
-          if (s4==NULL) note.Notice("Impossible d'allouer s4");
-          if ((s4!=NULL) && (ec<2))
-            {
-            Add_Scene(s4);
-            float xmin,xmax,ymin,ymax,zmin,zmax,diag;
-            // Remise a l'echelle du repere
-            s1->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            s1->Homothetie(1/xmax);
-            s4->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-            diag=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                    +(zmax-zmin)*(zmax-zmin));
-            s1->Homothetie(0.2*diag);
-            vue_centre(); 
-            SetNodeRadius(0.005*diag); 
-            SetEdgeRadius(0.003*diag);
-            GLRenderScene();
-            SetValue(m_sldprogress,0,Value);
-            SetValue(m_shownodes,GetShowNodes(),Value);
-            SetValue(m_showedges,GetShowEdges(),Value);
-            SetValue(m_showsides,GetShowSides(),Value);
-            if (ec!=1)
-              {
-              char Message[80];
-              strcpy(Message,"Modal - Freq(Hz)=");
-              sprintf(Utiltmp,"%8.4f",s4->freq);
-              strcat(Message,Utiltmp);
-              strcat(Message," Damp(%)=");
-              sprintf(Utiltmp,"%8.4f",100*s4->amor);
-              strcat(Message,Utiltmp);
-              SetString(m_info,Message);
-              }
-            else SetString(m_info,"Modal - No mode");
-            }
-          else { delete s4; s4=NULL; }
-          if (ec==1) 
-            note.Notice ("Cannot open modal file");
-          if (ec==2) 
-              note.Notice ("Error in modal file");
-          if (ec==3) 
-              note.Notice ("Uff block 82 corrupted");
-          if (ec==4) 
-              note.Notice ("Uff block 82 not found");
-          if (ec==7) 
-              note.Notice ("Uff block 15 corrupted");
-          if (ec==8) 
-              note.Notice ("Uff block 15 not found");
-          if (ec==5) 
-              note.Notice ("Memory allocation problems");
-          if (ec==6) 
-            note.Notice ("Cannot open geometry file");
-          }
-      break;
-      }
-
-
-	//@V@:Case M_Save
-      case M_Save:
-	  {
-	  char nom_fichier_cfg[200]="";
-	  if(strcmp(nomfichiervol,""))
-	     {
-             int ll=strlen(nomfichiervol);
-	     strcpy(nom_fichier_cfg,nomfichiervol);
-             nom_fichier_cfg[ll-3]=0;
-	     strcat(nom_fichier_cfg,"cfg");				
-             if(Sauve_Config(nom_fichier_cfg)) 
-               note.Notice("Was not able to save configuration file");
-	     }
-	  else note.Notice("You must have opened an animation");
-	  break;
-	  }	//@V@:EndCase
-
-	//@V@:Case M_CloseFile
-	case M_CloseFile:
-	  {
-	  Change_Couleur_Fond(0);
-          if (s2!=NULL) { Remove_Scene(); delete s2; s2=NULL; }
-          if (s3!=NULL) { Remove_Scene(); delete s3; s3=NULL; }
-          if (s4!=NULL) { Remove_Scene(); delete s4; s4=NULL; }
-          strcpy(nomfichiervol,"");
-          float xmin,xmax,ymin,ymax,zmin,zmax;
-          s1->GetDim(xmin,xmax,ymin,ymax,zmin,zmax);
-          s1->Homothetie(1/xmax);
-	  vue_depart();
-          vue_centre();
-          break;
-	  }	//@V@:EndCase
-
-
-	//@V@:Case M_Exit
-	case M_Exit:
-	  {
-            if (s1!=NULL) { delete s1; s1=NULL; }
-            if (s2!=NULL) { delete s2; s2=NULL; }
-            if (s3!=NULL) { delete s3; s3=NULL; }
-            if (s4!=NULL) { delete s4; s4=NULL; }
-	    theApp->Exit();
-	    break;
-	  }	//@V@:EndCase
-
-        case m_loadmode:// Chargement d'un autre mode
-          {
-	  vReplyDialog rp(this);
-          if (rp.Reply("Enter mode number",Utiltmp,9)==M_OK)
-	    {
-	    int modenum=atoi(Utiltmp),lstatus;
-            if (s3!=NULL) lstatus=s3->LoadMode(modenum);
-            if (s4!=NULL) lstatus=s4->LoadMode(modenum);
-            if (lstatus==1) note.Notice("Invalid mode number");
-            if (lstatus==2) note.Notice("Problem in vmo file");
-            if (!lstatus)
-              {
-              GLRenderScene();
-              char Message[80];
-              strcpy(Message,"Modal - Freq(Hz)=");
-              if (s3!=NULL) sprintf(Utiltmp,"%8.4f",s3->freq);
-              if (s4!=NULL) sprintf(Utiltmp,"%8.4f",s4->freq);
-              strcat(Message,Utiltmp);
-              strcat(Message," Damp(%)=");
-              if (s3!=NULL) sprintf(Utiltmp,"%8.4f",100*s3->amor);
-              if (s4!=NULL) sprintf(Utiltmp,"%8.4f",100*s4->amor);
-              strcat(Message,Utiltmp);
-              SetString(m_info,Message);
-              //sprintf(Utiltmp,"%8.4f",s2->alpha);
-              //sprintf(Utiltmp,"%8.4f",s2->beta);
-              }
-            else SetString(m_info,"Modal - No mode");
-            }
-          break;
-          }
-
-	//@V@:Case m_couleur
-	case m_couleur:
-	  {
-		  int retour;
-		 retour = myMDlg->myAction("Sample Modal Dialog");
-		 if (retour) Change_Couleur_Fond(retval);
-		 break;
-	  } //@V@:EndCase
-
-	//@V@:Case Vue_depart 
-	case m_vue_dep:
-		{
-		vue_depart();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-    //@V@:Case zoom in
-		case zoom_in:
-		{
-		zoom_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case zoom out
-		case zoom_out:
-		{
-		zoom_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case shownodes
-		case m_shownodes:
-		{
-		if (GetValue(m_shownodes)) SetShowNodesOn(); 
-                else SetShowNodesOff();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case showedges
-		case m_showedges:
-		{
-		if (GetValue(m_showedges)) SetShowEdgesOn(); 
-                else SetShowEdgesOff();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case showsides
-		case m_showsides:
-		{
-		if (GetValue(m_showsides)) SetShowSidesOn(); 
-                else SetShowSidesOff();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case m_suiv
-		case m_suiv:
-		{
-		image_suivante();
-		SetValue(m_start_stop,0,Value);	
-		break;
-		}
-
-	//@V@:Case m_prec
-		case m_prec:
-		{
-		stop_anime();
-                image_precedente();
-	        SetValue(m_start_stop,0,Value);
-		break;
-		}
-
-	//@V@:Case m_fast
-		case m_fast:
-		{
-			skip_image_plus();
-			break;
-		}
-
-	//@V@:Case m_slow
-		case m_slow:
-		{
-			skip_image_moins();
-			break;
-		}
-
-	//@V@:Case start_stop
-		case m_start_stop:
-		{
-		if (GetValue(m_start_stop)) start_anime();
-                else stop_anime();
-		break;
-		}
-
-	//@V@:Case sldprogress
-		case m_sldprogress:
-		{
-		stop_anime();
-		if (s2!=NULL) if (s2->GetNbrImages()>2)
-                    s2->LoadImage((int) val*(s2->GetNbrImages()-1)/100+1);
-		if (s3!=NULL) if (s3->GetNbrImages()>2)
-                    s3->LoadImage((int) val*(s3->GetNbrImages()-1)/100+1);
-		if (s4!=NULL) if (s4->GetNbrImages()>2)
-                    s4->LoadImage((int) val*(s4->GetNbrImages()-1)/100+1);
-		GLRenderScene();
-	        SetValue(m_start_stop,0,Value);
-		break;
-		}
-
-	//@V@:Case repere
-		case m_repere:
-		{
-		if (GetValue(m_repere)) s1->Show(); else s1->Hide();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case repere plus
-		case m_reperep:
-		{
-		repere_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case repere moins
-		case m_reperem:
-		{
-		repere_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-	    
-	//@V@:Case node radius smaller
-		case m_noderadm:
-		{
-		MultNodeRadius(0.8);
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case node radius larger
-		case m_noderadp:
-		{
-		MultNodeRadius(1.25);
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-	    
-	//@V@:Case line radius smaller
-		case m_lineradm:
-		{
-		MultEdgeRadius(0.8);
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case line radius larger
-		case m_lineradp:
-		{
-		MultEdgeRadius(1.25);
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case vue selon x positif
-		case m_vuexp:
-		{
-		vue_selon_x_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case vue selon x négatif
-		case m_vuexm:
-		{
-		vue_selon_x_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-	
-	//@V@:Case vue selon y positif
-		case m_vueyp:
-		{
-		vue_selon_y_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case vue selon y négatif
-		case m_vueym:
-		{
-		vue_selon_y_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case vue selon z positif
-		case m_vuezp:
-		{
-		vue_selon_z_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case vue selon z négatif
-		case m_vuezm:
-		{
-		vue_selon_z_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case phi_plus
-		case m_phiplus:
-		{
-		phi_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case phi_moins
-		case m_phimoins:
-		{
-		phi_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case theta_plus
-		case m_thetaplus:
-		{
-		theta_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case theta_moins
-		case m_thetamoins:
-		{
-		theta_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case gamma_plus
-		case m_gammaplus:
-		{
-		gamma_plus();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case gamma_moins
-		case m_gammamoins:
-		{
-		gamma_moins();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-	//@V@:Case distance plus
-		//case m_distpl:
-		//{
-		//distance_plus();
-		//GLRenderScene();
-		//break;
-		//}
-
-	//@V@:Case distance plus plus
-		//case m_distpp:
-		//{
-		//distance_plus_plus();
-		//GLRenderScene();
-		//break;
-		//}
-
-	//@V@:Case distance moins
-		//case m_distm:
-		//{
-		//distance_moins();
-		//GLRenderScene();
-		//break;
-		//}
-
-	//@V@:Case distance moins moins
-		//case m_distmm:
-		//{
-		//distance_moins_moins();
-		//GLRenderScene();
-		//break;
-		//}
-
-	//@V@:Case depl x positif
-		case m_vuecentre:
-		{
-		vue_centre();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-//@V@:Case depl vers haut
-		case m_dephaut:
-		{
-		depl_haut();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-//@V@:Case depl vers bas
-		case m_depbas:
-		{
-		depl_bas();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-//@V@:Case depl vers gauche
-		case m_depgauche:
-		{
-		depl_gauche();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-//@V@:Case depl vers droite
-		case m_depdroite:
-		{
-		depl_droite();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-//@V@:Case multi vues
-		case m_multi:
-		{
-		if (GetValue(m_multi)) SetMultiView(); else SetOneView();
-		if (!GetValue(m_start_stop)) GLRenderScene();
-		break;
-		}
-
-//@V@:Case multi vues
-		case m_sldspeed:
-		{
-		_auxTimer->TimerStop();
-		_auxTimer->TimerSet(201-2*val);
-		break;
-		}
-
-//@V@:Case multi vues
-		case m_loop:
-		{		
-		if (GetValue(m_loop)) LOOP=1; else LOOP=0;
-		break;
-		}
-
-//@V@:Case auxTimer
-		case cmdAuxTimer:	// Event from aux timer
-	  {
-	  myCanvas->TimerAnimate();
-          if (s2!=NULL)
-	      {
-	      if (s2->GetNbrImages()>1) SetValue(m_sldprogress,
-                    (int) 100*(s2->GetCurImage()-1)/(s2->GetNbrImages()-1),Value);
-	      if ((!LOOP)&&(s2->GetCurImage()==s2->GetNbrImages()))
-                 {
-	         stop_anime();
-	         SetValue(m_start_stop,0,Value);
-	         }
-              }
-          if (s3!=NULL)
-	      {
-	      if (s3->GetNbrImages()>1) SetValue(m_sldprogress,
-                    (int) 100*(s3->GetCurImage()-1)/(s3->GetNbrImages()-1),Value);
-	      if ((!LOOP)&&(s3->GetCurImage()==s3->GetNbrImages()))
-                 {
-	         stop_anime();
-	         SetValue(m_start_stop,0,Value);
-	         }
-              }
-          if (s4!=NULL)
-	      {
-	      if (s4->GetNbrImages()>1) SetValue(m_sldprogress,
-                    (int) 100*(s4->GetCurImage()-1)/(s4->GetNbrImages()-1),Value);
-	      if ((!LOOP)&&(s4->GetCurImage()==s4->GetNbrImages()))
-                 {
-	         stop_anime();
-	         SetValue(m_start_stop,0,Value);
-	         }
-              }
-	  break;
-	  }	//@V@:EndCase 
-	 
-//@V@:Case default
-// instructions exécutées par défaut
-	  	default:		// route unhandled commands up
-	  {
-	    vCmdWindow::WindowCommand(id, val, cType);
-		break;
-	  }
-      }
-  }
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+#include <v/vnotice.h>		// for vNoticeDialog
+#include <v/vkeys.h>		// to map keys
+#include <v/vfilesel.h>		// for file select
+#include <v/vreply.h>		// for file select
+
+#include "EasyAnimcmdw.h"	// our header
+#include "EasyAnimcnv.h"
+#include <fstream>
+#include <math.h>
+
+// Déclarations et initialisations
+extern int retval;
+
+int _INIT_VOL = 0;
+int LOOP = 0;
+
+/* for stream */
+#define DEFAULT_PORT 9011
+static std::string stream_src;
+static std::string stream_host;
+static std::string stream_path;
+static int stream_port;
+
+void
+set_string(std::string &s)
+{
+	// SetString(s.c_str());	
+}
+
+const std::string&
+get_stream(void)
+{
+	return stream_src;
+}
+
+int
+set_stream(std::string& stream)
+{
+	if (stream.empty()) {
+		stream_src.clear();
+		stream_host.clear();
+		stream_path.clear();
+		return 0;
+	}
+
+	if (strncasecmp(stream.c_str(), "inet://", sizeof("inet://")-1) == 0) {
+		std::string host = stream;
+		host.erase(0, sizeof("inet://") - 1);
+		int port = DEFAULT_PORT;
+		char *p = strchr(host.c_str(), ':');
+		if (p) {
+			char *next;
+			port = strtol(&p[1], &next, 10);
+			if (port <= 0) {
+				return 1;
+			}
+			stream_port = port;
+			host.erase(p - host.c_str(), host.length());
+		}
+
+		if (!host.empty()) {
+			stream_host = host;
+		}
+
+		stream_path.clear();
+		stream_src = stream;
+
+	} else {
+		stream_host.clear();
+		stream_path = stream;
+		stream_src = stream_path;
+	}
+
+	return 0;
+}
+
+//	Start defines for the main window with 100
+
+//@V@:BeginIDs
+enum {
+	m_FirstCmd = 100, // Dummy Command
+
+	blanc,
+        m_open1,
+        m_open2,
+        m_open3,
+	m_reload,
+	m_vue_dep,
+	zoom_in,
+	zoom_out,
+	m_rev_start_stop,
+	m_start_stop,
+	m_movie_start_stop,
+	m_picture,
+	m_suiv,
+	m_prec,
+	m_fast,
+	m_slow,
+	m_shownodes,
+	m_showedges,
+	m_showsides,
+	m_repere,
+	m_reperep,
+	m_reperem,
+	m_noderadp,
+	m_noderadm,
+	m_lineradp,
+	m_lineradm,
+	m_vuexp,
+	m_vuexm,
+	m_vueyp,
+	m_vueym,
+	m_vuezp,
+	m_vuezm,
+	m_vuecentre,
+	m_phiplus,
+	m_phimoins,
+	m_thetaplus,
+	m_thetamoins,
+	m_gammaplus,
+	m_gammamoins,
+	m_distpl,
+	m_distpp,
+	m_distm,
+	m_distmm,
+	m_dephaut,
+	m_depbas,
+	m_depgauche,
+	m_depdroite,
+	m_multi,
+	m_couleur,
+	m_loadmode,
+	m_rotangle,
+	m_selectstream,
+	cmdAuxTimer,	// AuxTimer
+	m_lblspeed,     // the label for the animation speed
+	m_sldspeed,     // the slider for the animation speed
+	m_lblprogress,  // the label for the animation progress bar
+	m_sldprogress,  // the slider for the animation progress bar
+        m_loop,
+        m_info,
+
+	blkLast		// Last item
+};
+//@V@:EndIDs
+
+//@V@:BeginPulldownMenu FileMenu
+// Définition du Menu "File"
+static vMenu FileMenu[] = {
+	{"&Open animation (vol-van)",
+		M_Open, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Open streamed animation (vol-str)",
+		m_open1, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Open modal analysis (vol-vmo)",
+		m_open2, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Open modal analysis (universal)",
+		m_open3, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Close...",
+		M_CloseFile, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"-",
+		M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Reload",
+		m_reload, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"Save &Config",
+		M_Save, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"-",
+		M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Print",
+		M_Print, notSens, notChk, noKeyLbl, noKey, noSub},
+	{"-",
+		M_Line, notSens, notChk, noKeyLbl, noKey, noSub},
+	{"E&xit",
+		M_Exit, isSens, notChk, noKeyLbl, noKey, noSub},
+
+	{0} // dernière instruction des menus
+};
+//@V@:EndPulldownMenu
+
+//@V@:BeginPulldownMenu OptionMenu
+// Définition du menu "Options"
+static vMenu OptionMenu[] = {
+	{"&Background Color...",
+		m_couleur, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Load mode...",
+		m_loadmode, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Rotation angle...",
+		m_rotangle, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"&Select stream...",
+		m_selectstream, isSens, notChk, noKeyLbl, noKey, noSub},
+#if 0
+	{"Hide/show &Nodes",
+		m_shownodes, isSens, notChk, noKeyLbl, noKey, noSub},
+        {"Hide/show &Edges",
+		m_showedges, isSens, notChk, noKeyLbl, noKey, noSub},
+        {"Hide/show &Sides",
+		m_showsides, isSens, notChk, noKeyLbl, noKey, noSub},
+	{"Hide/show &Mark",
+		m_repere, isSens, notChk, noKeyLbl, noKey, noSub},
+#endif
+	{0}
+};
+//@V@:EndPulldownMenu
+
+//@V@:BeginMenu StandardMenu
+// Définition de la barre de menu
+static vMenu StandardMenu[] = {
+	{"&File",
+		M_File, isSens, notUsed, notUsed, noKey, &FileMenu[0]},
+	{"&Options",
+		M_Options, isSens, notUsed, notUsed, noKey, &OptionMenu[0]},
+
+	{0}
+};
+//@V@:EndMenu
+
+
+//@V@:BeginCmdPane ToolBar
+// Définition de la barre d'outil
+static CommandObject DisplaceBar[] = {
+	{C_IconButton, zoom_in, zoom_in, "", (void*)&zpicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Zoom +"},
+	{C_IconButton, zoom_out, zoom_out, "", (void*)&zmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Zoom -"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_IconButton, m_vuecentre, m_vuecentre, "", (void*)&vuecentricon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Centered View"},
+	{C_IconButton, m_dephaut, m_dephaut, "", (void*)&dephauticon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Up Move"},
+	{C_IconButton, m_depbas, m_depbas, "", (void*)&depbasicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Down move"},
+	{C_IconButton, m_depgauche, m_depgauche, "", (void*)&depgaucheicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Left Move"},
+	{C_IconButton, m_depdroite, m_depdroite, "", (void*)&depdroiteicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Right Move"},
+	{C_ToggleIconButton, m_multi, 0, "", (void*)&multiicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "MDI"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleIconButton, m_repere, m_repere, "", (void*)&repicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Show marker"},
+	{C_IconButton, m_reperep, m_reperep, "", (void*)&reppicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Increase size of marker"},
+	{C_IconButton, m_reperem, m_reperem, "", (void*)&repmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Decrease size of marker"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleIconButton, m_showedges, m_showedges, "",(void*)&lineicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Show edges"},
+	{C_IconButton, m_lineradp, m_lineradp, "", (void*)&lineradpicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Increase radius of edges"},
+	{C_IconButton, m_lineradm, m_lineradm, "", (void*)&lineradmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Decrease radius of edges"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleIconButton, m_shownodes, m_shownodes, "", (void*)&nodeicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Show nodes"},
+	{C_IconButton, m_noderadp, m_noderadp, "", (void*)&noderadpicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Increase size of nodes"},
+	{C_IconButton, m_noderadm, m_noderadm, "", (void*)&noderadmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Decrease size of nodes"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleIconButton, m_showsides, m_showsides, "", (void*)&sideicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Show sides"},
+#if 0
+	{C_IconButton, m_distmm, m_distmm, "", (void*)&distmmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0,
+		"Decrease the distance of the camera"},
+	{C_IconButton, m_distm, m_distm, "", (void*)&distmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0,
+		"Decrease the distance of the camera"},
+	{C_IconButton, m_distpl, m_distpl, "", (void*)&distplicon,
+		CA_None, isSens, NoFrame, 0, 0, 0,
+		"Increase the distance of the camera"},
+	{C_IconButton, m_distpp, m_distpp, "", (void*)&distppicon,
+		CA_None, isSens, NoFrame, 0, 0, 0,
+		"Increase the distance of the camera"},
+#endif
+
+	{C_EndOfList, 0, 0, 0, 0,
+		CA_None, 0, 0, 0} // dernière instruction des listes
+};
+
+//@V@:EndCmdPane
+//@V@:BeginCmdPane CommandBar
+static CommandObject RotateBar[] = {
+	{C_IconButton, m_vue_dep, m_vue_dep, "",(void*)&vuedepicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Start View"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_IconButton, m_vuexp, m_vuexp, "", (void*)&vuexpicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "X + View"},
+	{C_IconButton, m_vuexm, m_vuexm, "", (void*)&vuexmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "X - View"},
+	{C_IconButton, m_vueyp, m_vueyp, "", (void*)&vueypicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Y + View"},
+	{C_IconButton, m_vueym, m_vueym, "", (void*)&vueymicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Y - View"},
+	{C_IconButton, m_vuezp, m_vuezp, "", (void*)&vuezpicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Z + View"},
+	{C_IconButton, m_vuezm, m_vuezm, "", (void*)&vuezmicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Z - View"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_IconButton, m_phiplus, m_phiplus, "", (void*)&phiplusicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Phi + Rotation"},
+	{C_IconButton, m_phimoins, m_phimoins, "", (void*)&phimoinsicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Phi - Rotation"},
+	{C_IconButton, m_thetaplus, m_thetaplus, "", (void*)&thetaplusicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Theta + Rotation"},
+	{C_IconButton, m_thetamoins, m_thetamoins, "", (void*)&thetamoinsicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Theta - Rotation"},
+	{C_IconButton, m_gammaplus, m_gammaplus, "", (void*)&gammaplusicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Gamma + Rotation"},
+	{C_IconButton, m_gammamoins, m_gammamoins, "", (void*)&gammamoinsicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Gamma - Rotation"},
+
+	{C_EndOfList, 0, 0, 0, 0,
+		CA_None, 0, 0, 0}
+};
+//@V@:EndCmdPane
+
+// Définition de la barre d'outil
+static CommandObject AnimBar[] = {
+#if 0
+	{C_IconButton, m_slow, m_slow, "", (void*)&slowicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Slow animation"},
+	{C_IconButton, m_fast, m_fast, "", (void*)&fasticon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Fast animation"},
+#endif
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_Label, m_lblspeed, 0, "Speed", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 0, ""},
+	{C_Slider, m_sldspeed, 0, "", NoList,
+		CA_Horizontal, isSens, NoFrame, 0, 0, 0, ""},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_Label, m_lblprogress, 0, "Progress", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 0, ""},
+       	{C_IconButton, m_prec, m_prec, "", (void*)&precicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Previous Frame"},
+	{C_Slider, m_sldprogress, 0, "", NoList,
+		CA_Horizontal, isSens, NoFrame, 0, 0, 0, ""},
+	{C_IconButton, m_suiv, m_suiv, "", (void*)&suivicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Next Frame"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleIconButton, m_rev_start_stop, 0, "", (void*)&revssicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Reverse Start/Stop"},
+	{C_ToggleIconButton, m_start_stop, 0, "", (void*)&ssicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Start/Stop"},
+	{C_ToggleIconButton, m_movie_start_stop, 0, "",(void*)&moviessicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Movie Start/Stop"},
+	{C_ToggleIconButton, m_picture, 0, "", (void*)&pictureicon,
+		CA_None, isSens, NoFrame, 0, 0, 0, "Take Picture"},
+	{C_Blank, blanc, 0, " ", NoList,
+		CA_None, isSens, NoFrame, 0, 0, 5},
+	{C_ToggleButton, m_loop, 0, "LOOP", NoList,
+		CA_None, isSens, NoFrame, 0, 0},
+
+	{C_EndOfList, 0, 0, 0, 0,
+		CA_None, 0, 0, 0} // derniere instruction des listes
+};
+
+//@V@:BeginCmdPane InfoBar
+static vStatus InfoBar[] = {
+	{"No application yet", m_info, CA_None, isSens, 500},
+	{0, 0, 0, 0, 0}
+};
+
+//====================>>> myAuxTimer::TimerTick <<<====================
+void
+myAuxTimer::TimerTick(void)
+{
+	// update clock
+	cmdw->WindowCommand(cmdAuxTimer, cmdAuxTimer, C_Button);
+}
+
+
+//====================>>> myCmdWindow::myCmdWindow <<<====================
+// Définition du contenu de la fenêtre de commandes
+myCmdWindow::myCmdWindow(char* name, int width, int height)
+: vCmdWindow(name, width, height)
+{
+	UserDebug1(Constructor, "myCmdWindow::myCmdWindow(%s) Constructor\n",
+		name);
+
+	// The Menu Bar
+	myMenu = new vMenuPane(StandardMenu);
+	AddPane(myMenu);
+
+	// The Canvas
+	myCanvas = new myOGLCanvasPane;
+	AddPane(myCanvas);
+
+	// The Timer
+	_auxTimer = new myAuxTimer(this);	// create aux timer
+	_auxTimer->TimerSet(1);			// 1/2 second intervals
+
+	// The Command Pane
+	DisplacePane = new vCommandPane(DisplaceBar);
+	AddPane(DisplacePane);
+
+	// The second Command Pane
+	RotatePane = new vCommandPane(RotateBar);
+	AddPane(RotatePane);
+
+	// The second Command Pane
+	AnimPane = new vCommandPane(AnimBar);
+	AddPane(AnimPane);
+
+	// The status Pane
+	InfoPane = new vStatusPane(InfoBar);
+	AddPane(InfoPane);
+
+	// Associated dialogs
+	myMDlg = new myModalDialog(this, name);
+
+	// Show Window
+	ShowWindow();
+	WindowCommand(cmdAuxTimer, cmdAuxTimer, C_Button);	// update clock
+
+	SetValue(m_sldspeed, 100, Value);
+	SetValue(m_sldprogress, 0, Value);
+	SetValue(m_multi, 0, Value);
+	SetValue(m_repere, s1->Hidden() ? 0 : 1, Value);
+	SetValue(m_shownodes, 0, Value);
+	SetValue(m_showsides, 1, Value);
+	SetValue(m_showedges, 1, Value);
+}
+
+//====================>>> myCmdWindow::~myCmdWindow <<<====================
+// Destructeur de la fenêtre de commandes
+myCmdWindow::~myCmdWindow(void)
+{
+	UserDebug(Destructor, "myCmdWindow::~myCmdWindow() destructor\n");
+
+	// Now put a delete for each new in the constructor.
+	delete myMenu;
+	delete myCanvas;
+	delete DisplacePane;
+	delete RotatePane;
+	delete AnimPane;
+	delete myMDlg;
+	_auxTimer->TimerStop();	// end it
+	delete _auxTimer;	// free it
+}
+
+//===================>>> myCmdWindow::Lecture <<<======================
+void
+myCmdWindow::Lecture(char* fichier_config)
+{
+	std::string cfg(fichier_config);
+	Lecture_Config(cfg);
+}
+
+
+//===================>>> myCmdWindow::OpenFile <<<======================
+// ouverture des fichier ".vol" et ".van"
+
+void
+myCmdWindow::WindowCommandOpen(ItemVal val, std::string &name,
+	std::string &name2)
+{
+	if (s2 != 0 || s3 != 0 || s4 != 0 || s5 != 0) {
+		Remove_Scene();
+		if (s2 != 0) {
+			delete s2;
+			s2 = 0;
+		}
+
+		if (s3 != 0) {
+			delete s3;
+			s3 = 0;
+		}
+
+		if (s4 != 0) {
+			delete s4;
+			s4 = 0;
+		}
+
+		if (s5 != 0) {
+			delete s5;
+			s5 = 0;
+		}
+	}
+
+	vNoticeDialog note(this);
+	def_err ec;
+
+	switch (val) {
+	case M_Open: {
+		s2 = new def_volvan(name, ec);
+		if (s2 == 0) {
+			note.Notice("Impossible d'allouer s2");
+		}
+
+		if (s2 != 0 && ec.geterr() < 4) {
+			Add_Scene(s2);
+			float xmin, xmax, ymin, ymax, zmin, zmax, diag;
+			// Remise a l'echelle du repere
+			s1->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			s1->Homothetie(1/xmax);
+			s2->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			diag = sqrt((xmax - xmin)*(xmax - xmin)
+				+ (ymax - ymin)*(ymax - ymin)
+				+ (zmax - zmin)*(zmax - zmin));
+			s1->Homothetie(get_repere_size()*diag);
+			if (ec.geterr() == 1 || ec.geterr() == 3) {
+				vue_centre();
+				SetNodeRadius(0.005*diag);
+				SetEdgeRadius(0.003*diag);
+			}
+			GLRenderScene();
+			SetValue(m_repere, s1->Hidden() ? 0 : 1, Value);
+			SetValue(m_sldprogress, 0, Value);
+			SetValue(m_shownodes, GetShowNodes(), Value);
+			SetValue(m_showedges, GetShowEdges(), Value);
+			SetValue(m_showsides, GetShowSides(), Value);
+			char Message[BUFSIZ];
+			snprintf(Message, sizeof(Message),
+				"file=\"%s\" images=%d",
+				name.c_str(), s2->GetNbrImages());
+			SetString(m_info, Message);
+
+		} else {
+			note.Notice(ec.getmsg().c_str());
+			delete s2;
+			s2 = 0;
+		}
+
+		if (ec.geterr() == 1 || ec.geterr() == 3) {
+			note.Notice("Configuration (cfg) file not found "
+				"or not conform");
+		}
+
+		if (ec.geterr() == 2 || ec.geterr() == 3) {
+			note.Notice("Animation (van) file not found "
+				"or corrupted");
+		}
+
+		if (ec.geterr() == 4 || ec.geterr() == 6) {
+			note.Notice("Image (vol) file not found or corrupted");
+		}
+
+		if (ec.geterr() == 5) {
+			note.Notice("Memory allocation problems");
+		}
+		} break;
+
+	case m_open1:
+	{
+		if (stream_src.empty()) {
+			stream_path = std::string("/tmp/easyanim.sock");
+			stream_src = stream_path;
+		}
+
+		UseSocket *sock;
+
+		if (!stream_path.empty()) {
+			sock = new UseLocalSocket(stream_path, false);
+
+		} else {
+			sock = new UseInetSocket(stream_host, stream_port,
+				false);
+		}
+
+		s5 = new def_volstream(name, sock, ec);
+		if (s5 == 0) {
+			note.Notice("Impossible d'allouer s5");
+		}
+
+		if (s5 != 0 && ec.geterr() < 4) {
+			Add_Scene(s5);
+			float xmin, xmax, ymin, ymax, zmin, zmax, diag;
+			// Remise a l'echelle du repere
+			s1->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			s1->Homothetie(1/xmax);
+			s5->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			diag = sqrt((xmax - xmin)*(xmax - xmin)
+				+ (ymax - ymin)*(ymax - ymin)
+				+ (zmax - zmin)*(zmax - zmin));
+			s1->Homothetie(0.2*diag);
+			if (ec.geterr() == 1 || ec.geterr() == 3) {
+				vue_centre();
+				SetNodeRadius(0.005*diag);
+				SetEdgeRadius(0.003*diag);
+			}
+			GLRenderScene();
+			SetValue(m_sldprogress, 0, Value);
+			SetValue(m_shownodes, GetShowNodes(), Value);
+			SetValue(m_showedges, GetShowEdges(), Value);
+			SetValue(m_showsides, GetShowSides(), Value);
+			if (ec.geterr() < 2) {
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Streamed - %s", stream_src.c_str());
+				SetString(m_info, Message);
+
+			} else {
+				SetString(m_info, "Streamed - no source");
+			}
+
+		} else {
+			note.Notice(ec.getmsg().c_str());
+			delete s5;
+			s5 = 0;
+		}
+
+		if (ec.geterr() == 1 || ec.geterr() == 3) {
+			note.Notice("Configuration (cfg) file not found "
+				"or not conform");
+		}
+
+		if (ec.geterr() == 2 || ec.geterr() == 3) {
+			note.Notice("Mode (vmo) file not found or corrupted");
+		}
+
+		if (ec.geterr() == 4 || ec.geterr() == 6) {
+			note.Notice("Image (vol) file not found or corrupted");
+		}
+
+		if (ec.geterr() == 5) {
+			note.Notice("Memory allocation problems");
+		}
+		} break;
+
+	case m_open2: {
+		s3 = new def_volvmo(name, ec);
+		if (s3 == 0) {
+			note.Notice("Impossible d'allouer s3");
+		}
+
+		if (s3 != 0 && ec.geterr() < 4) {
+			Add_Scene(s3);
+			float xmin, xmax, ymin, ymax, zmin, zmax, diag;
+			// Remise a l'echelle du repere
+			s1->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			s1->Homothetie(1/xmax);
+			s3->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			diag = sqrt((xmax - xmin)*(xmax - xmin)
+				+ (ymax - ymin)*(ymax - ymin)
+				+ (zmax - zmin)*(zmax - zmin));
+			s1->Homothetie(0.2*diag);
+			if (ec.geterr() == 1 || ec.geterr() == 3) {
+				vue_centre();
+				SetNodeRadius(0.005*diag);
+				SetEdgeRadius(0.003*diag);
+			}
+			GLRenderScene();
+			SetValue(m_sldprogress, 0, Value);
+			SetValue(m_shownodes, GetShowNodes(), Value);
+			SetValue(m_showedges, GetShowEdges(), Value);
+			SetValue(m_showsides, GetShowSides(), Value);
+			if (ec.geterr() < 2) {
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Modal - Freq(Hz)=%8.4f Damp(%%)=%8.4f",
+					s3->freq, 100*s3->amor);
+				SetString(m_info, Message);
+
+			} else {
+				SetString(m_info, "Modal - No mode");
+			}
+
+		} else {
+			note.Notice(ec.getmsg().c_str());
+			delete s3;
+			s3 = 0;
+		}
+
+		if (ec.geterr() == 1 || ec.geterr() == 3) {
+			note.Notice("Configuration (cfg) file not found "
+				"or not conform");
+		}
+
+		if (ec.geterr() == 2 || ec.geterr() == 3) {
+			note.Notice("Mode (vmo) file not found or corrupted");
+		}
+
+		if (ec.geterr() == 4 || ec.geterr() == 6) {
+			note.Notice("Image (vol) file not found or corrupted");
+		}
+
+		if (ec.geterr() == 5) {
+			note.Notice("Memory allocation problems");
+		}
+		} break;
+
+	case m_open3: {
+		s4 = new def_uff(name, name2, ec);
+		if (s4 == 0) {
+			note.Notice("Impossible d'allouer s4");
+		}
+
+		if (s4 != 0 && ec.geterr() < 2) {
+			Add_Scene(s4);
+			float xmin, xmax, ymin, ymax, zmin, zmax, diag;
+			// Remise a l'echelle du repere
+			s1->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			s1->Homothetie(1/xmax);
+			s4->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+			diag = sqrt((xmax - xmin)*(xmax - xmin)
+				+ (ymax - ymin)*(ymax - ymin)
+				+ (zmax - zmin)*(zmax - zmin));
+			s1->Homothetie(0.2*diag);
+			vue_centre();
+			SetNodeRadius(0.005*diag);
+			SetEdgeRadius(0.003*diag);
+			GLRenderScene();
+			SetValue(m_sldprogress, 0, Value);
+			SetValue(m_shownodes, GetShowNodes(), Value);
+			SetValue(m_showedges, GetShowEdges(), Value);
+			SetValue(m_showsides, GetShowSides(), Value);
+			if (ec.geterr() != 1) {
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Modal - Freq(Hz)=%8.4f Damp(%%)=%8.4f",
+					s4->freq, 100*s4->amor);
+				SetString(m_info, Message);
+
+			} else {
+				SetString(m_info, "Modal - No mode");
+			}
+
+		} else {
+			note.Notice(ec.getmsg().c_str());
+			delete s4;
+			s4 = 0;
+		}
+
+		switch (ec.geterr()) {
+		case 1:
+			note.Notice ("Cannot open modal file");
+			break;
+
+		case 2:
+			note.Notice ("Error in modal file");
+			break;
+
+		case 3:
+			note.Notice ("Uff block 82 corrupted");
+			break;
+
+		case 4:
+			note.Notice ("Uff block 82 not found");
+			break;
+
+		case 5:
+			note.Notice ("Memory allocation problems");
+			break;
+
+		case 6:
+			note.Notice ("Cannot open geometry file");
+			break;
+
+		case 7:
+			note.Notice ("Uff block 15 corrupted");
+			break;
+
+		case 8:
+			note.Notice ("Uff block 15 not found");
+			break;
+
+		default:
+			break;
+		}
+		} break;
+
+	default:
+		/* impossible */
+		break;
+	}
+}
+
+void
+myCmdWindow::doStop(void)
+{
+	SetValue(m_rev_start_stop, 0, Value);
+	SetValue(m_start_stop, 0, Value);
+}
+
+void
+myCmdWindow::WindowCommand(ItemVal id, ItemVal val, CmdType cType)
+{
+	// Default: route menu and toolbar commands here
+
+	static std::string nomfichiervol("");
+	static std::string name2("");
+	static ItemVal lastFileType = blkLast;
+
+	vNoticeDialog note(this);
+
+	UserDebug1(CmdEvents, "myCmdWindow:WindowCommand(%d)\n", id);
+
+	// instructions exécutées lors de l'activation des menu, boutons, ...
+	switch (id) {
+	case M_Open: {
+		// This demos vFileSelect dialog
+		char name[BUFSIZ] = "";		// start out with null name
+		vFileSelect fsel(this);		// an instance of vFileSelect
+		int fI = 0;			// Filter index
+		// Filter for file select
+		static char* filter[] = { "*.vol", 0};
+		int ans;
+		// Show the file select dialog
+		ans = fsel.FileSelect("Open file",
+			name, sizeof(name) - 1, filter, fI);
+		if (ans && *name) {
+			// User picked a file name
+			nomfichiervol = std::string(name);
+			lastFileType = M_Open;
+
+			WindowCommandOpen(lastFileType, nomfichiervol, name2);
+		}
+		} break;
+
+	case m_open1: {
+		// Opening a streamed file
+		char name[BUFSIZ] = "";		// start out with null name
+		vFileSelect fsel(this);		// an instance of vFileSelect
+		int fI = 0;			// Filter index
+		// Filter for file select
+		static char* filter[] = {"*.vol", 0};
+		int ans;
+		// Show the file select dialog
+		ans = fsel.FileSelect("Open file",
+			name, sizeof(name) - 1, filter, fI);
+		if (ans && *name) {
+			// User picked a file name
+			nomfichiervol = std::string(name);
+			lastFileType = m_open1;
+
+			WindowCommandOpen(lastFileType, nomfichiervol, name2);
+		}
+		} break;
+
+	case m_open2: {
+		// Opening a modal file
+		char name[BUFSIZ] = "";		// start out with null name
+		vFileSelect fsel(this);		// an instance of vFileSelect
+		int fI = 0;			// Filter index
+		// Filter for file select
+		static char* filter[] = {"*.vol", 0};
+		int ans;
+		// Show the file select dialog
+		ans = fsel.FileSelect("Open file",
+			name, sizeof(name) - 1, filter, fI);
+		if (ans && *name) {
+			// User picked a file name
+			nomfichiervol = std::string(name);
+			lastFileType = m_open2;
+
+			WindowCommandOpen(lastFileType, nomfichiervol, name2);
+		}
+		} break;
+
+	case m_open3: {
+		// Opening a modal file
+		char name[BUFSIZ] = "";		// start out with null name
+		vFileSelect fsel(this);		// an instance of vFileSelect
+		int fI = 0;			// Filter index
+		// Filter for file select
+		static char* filter[] = {"*.unv;*.uff", "*", 0};
+		int ans;
+		// Show the file select dialog
+		ans = fsel.FileSelect("Open geometry file",
+			name, sizeof(name) - 1, filter, fI);
+		if (ans && *name) {
+			// User picked a file name
+			nomfichiervol = std::string(name);
+			lastFileType = m_open3;
+
+			note.Notice("Now choose the uff modal file");
+			ans = fsel.FileSelect("Open modal file",
+				name, sizeof(name) - 1, filter, fI);
+			if (ans && *name) {
+				name2 = std::string(name);
+
+				WindowCommandOpen(lastFileType, nomfichiervol,
+					name2);
+			}
+		}
+		} break;
+
+	case m_reload:
+		switch (lastFileType) {
+		case M_Open:
+		case m_open1:
+		case m_open2:
+		case m_open3:
+			WindowCommandOpen(lastFileType, nomfichiervol, name2);
+			break;
+
+		default:
+			// Nothing to reload...
+			break;
+		}
+		break;
+
+	//@V@:Case M_Save
+	case M_Save:
+		if (!nomfichiervol.empty()) {
+			std::string nom_fichier_cfg = nomfichiervol;
+			nom_fichier_cfg.replace(nomfichiervol.length() - 3, 3,
+				"cfg");
+			if (Sauve_Config(nom_fichier_cfg)) {
+				char buf[BUFSIZ];
+
+				snprintf(buf, sizeof(buf),
+					"Unable to save "
+					"configuration file \"%s\"",
+					nom_fichier_cfg.c_str());
+				note.Notice(buf);
+			}
+
+		} else {
+			note.Notice("An animation must be open");
+		}
+		break;
+		//@V@:EndCase
+
+	//@V@:Case M_CloseFile
+	case M_CloseFile: {
+		Change_Couleur_Fond(0);
+		if (s2 != 0) {
+			Remove_Scene();
+			delete s2;
+			s2 = 0;
+		}
+		if (s3 != 0) {
+			Remove_Scene();
+			delete s3;
+			s3 = 0;
+		}
+		if (s4 != 0) {
+			Remove_Scene();
+			delete s4;
+			s4 = 0;
+		}
+		if (s5 != 0) {
+			Remove_Scene();
+			delete s5;
+			s5 = 0;
+		}
+		nomfichiervol = std::string("");
+		float xmin, xmax, ymin, ymax, zmin, zmax;
+		s1->GetDim(xmin, xmax, ymin, ymax, zmin, zmax);
+		s1->Homothetie(1/xmax);
+		vue_depart();
+		vue_centre();
+		} break;
+		//@V@:EndCase
+
+	//@V@:Case M_Exit
+	case M_Exit:
+		if (s1 != 0) {
+			delete s1;
+			s1 = 0;
+		}
+		if (s2 != 0) {
+			delete s2;
+			s2 = 0;
+		}
+		if (s3 != 0) {
+			delete s3;
+			s3 = 0;
+		}
+		if (s4 != 0) {
+			delete s4;
+			s4 = 0;
+		}
+		if (s5 != 0) {
+			delete s5;
+			s5 = 0;
+		}
+		theApp->Exit();
+		break;
+		//@V@:EndCase
+
+	case m_loadmode: {
+		// Chargement d'un autre mode
+		char Utiltmp[BUFSIZ];
+		vReplyDialog rp(this);
+		if (rp.Reply("Enter mode number", Utiltmp, sizeof(Utiltmp) - 1)
+			== M_OK)
+		{
+			char *next;
+			int modenum, lstatus = 0;
+			modenum = strtol(Utiltmp, &next, 10);
+			if (next == Utiltmp || next[0] != '\0') {
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Modal - invalid mode=%s", Utiltmp);
+				SetString(m_info, Message);
+				break;
+			}
+			if (s3 != 0) {
+				lstatus = s3->LoadMode(modenum);
+			}
+			if (s4 != 0) {
+				lstatus = s4->LoadMode(modenum);
+			}
+
+			if (lstatus == 1) {
+				char buf[BUFSIZ];
+
+				snprintf(buf, sizeof(buf),
+					"Invalid mode number %d", modenum);
+				note.Notice(buf);
+
+			} else if (lstatus == 2) {
+				note.Notice("Problem in vmo file");
+			}
+			if (!lstatus) {
+				GLRenderScene();
+				char Message[BUFSIZ];
+				float freq = 0., amor = 0.;
+				if (s3 != 0) {
+					freq = s3->freq;
+					amor = 100*s3->amor;
+				} else if (s4 != 0) {
+					freq = s4->freq;
+					amor = 100*s4->amor;
+				}
+
+				snprintf(Message, sizeof(Message),
+					"Modal - Freq(Hz)=%8.4f Damp(%%)=%8.4f",
+					freq, amor);
+				SetString(m_info, Message);
+#if 0
+				sprintf(Utiltmp, "%8.4f", s2->alpha);
+				sprintf(Utiltmp, "%8.4f", s2->beta);
+#endif
+			} else {
+				SetString(m_info,"Modal - No mode");
+			}
+		}
+		} break;
+
+	case m_rotangle: {
+		char Utiltmp[BUFSIZ];
+		snprintf(Utiltmp, sizeof(Utiltmp), "%f", get_rotangle()*180./M_PI);
+		for (int l = strlen(Utiltmp); --l > 0 && Utiltmp[l] == '0' && Utiltmp[l-1] != '.'; ) {
+			Utiltmp[l] = '\0';
+		}
+		vReplyDialog rp(this);
+		if (rp.Reply("Enter angle increment", Utiltmp, sizeof(Utiltmp) - 1, Utiltmp)
+			== M_OK)
+		{
+			char *next;
+			double rotangle;
+			rotangle = strtod(Utiltmp, &next);
+			if (next == Utiltmp || next[0] != '\0'
+				|| rotangle <= 0. || rotangle > 180.)
+			{
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Rotation angle - invalid angle %s (must be 0.0 < angle < 180.0)", Utiltmp);
+				SetString(m_info, Message);
+				break;
+			}
+
+			set_rotangle(rotangle/180*M_PI);
+		}
+		} break;
+
+	// Selection of the input stream
+	case m_selectstream: {
+		if (lastFileType != m_open1) {
+			char Message[BUFSIZ];
+			snprintf(Message, sizeof(Message),
+				"Need to be in stream mode");
+			SetString(m_info, Message);
+			break;
+		}
+		char Utiltmp[BUFSIZ];
+		vReplyDialog rp(this);
+		if (rp.Reply("Enter stream socket info",
+			Utiltmp, sizeof(Utiltmp)-1,
+			stream_src.c_str()) == M_OK)
+		{
+			int lstatus = 0;
+			std::string stream(Utiltmp);
+
+			if (set_stream(stream)) {
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Invalid stream socket info \"%s\"",
+					Utiltmp);
+				SetString(m_info, Message);
+				break;
+			}
+
+			if (!stream_host.empty()) {
+				lstatus = s5->SetSocket(stream_host,
+					stream_port);
+
+			} else {
+				lstatus = s5->SetSocket(stream_path);
+			}
+
+			if (!lstatus) {
+				GLRenderScene();
+				char Message[BUFSIZ];
+				snprintf(Message, sizeof(Message),
+					"Streamed - %s", stream_src.c_str());
+				SetString(m_info, Message);
+			}
+		}
+		} break;
+
+	//@V@:Case m_couleur
+	case m_couleur: {
+		int retour = myMDlg->myAction("Sample Modal Dialog");
+		if (retour) {
+			Change_Couleur_Fond(retval);
+		}
+		} break;
+		//@V@:EndCase
+
+	//@V@:Case Vue_depart
+	case m_vue_dep:
+		vue_depart();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case zoom in
+	case zoom_in:
+		zoom_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case zoom out
+	case zoom_out:
+		zoom_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case shownodes
+	case m_shownodes:
+		if (GetValue(m_shownodes)) {
+			SetShowNodesOn();
+                } else {
+			SetShowNodesOff();
+		}
+
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case showedges
+	case m_showedges:
+		if (GetValue(m_showedges)) {
+			SetShowEdgesOn();
+                } else {
+			SetShowEdgesOff();
+		}
+
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case showsides
+	case m_showsides:
+		if (GetValue(m_showsides)) {
+			SetShowSidesOn();
+                } else {
+			SetShowSidesOff();
+		}
+
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case m_suiv
+	case m_suiv:
+		image_suivante();
+		doStop();
+		break;
+
+	//@V@:Case m_prec
+	case m_prec:
+		stop_anime();
+                image_precedente();
+		doStop();
+		break;
+
+	//@V@:Case m_fast
+	case m_fast:
+		skip_image_plus();
+		break;
+
+	//@V@:Case m_slow
+	case m_slow:
+		skip_image_moins();
+		break;
+
+	//@V@:Case rev_start_stop
+	case m_rev_start_stop:
+		if (GetValue(m_rev_start_stop)) {
+			if (GetValue(m_start_stop)) {
+				stop_anime();
+	        		SetValue(m_start_stop, 0, Value);
+			}
+
+			if (start_anime(false)) {
+	        		SetValue(m_rev_start_stop, 0, Value);
+			}
+
+                } else {
+			stop_anime();
+		}
+		break;
+
+	//@V@:Case start_stop
+	case m_start_stop:
+		if (GetValue(m_start_stop)) {
+			if (GetValue(m_rev_start_stop)) {
+				stop_anime();
+	        		SetValue(m_rev_start_stop, 0, Value);
+			}
+
+			if (start_anime(true)) {
+	        		SetValue(m_start_stop, 0, Value);
+			}
+
+                } else {
+			stop_anime();
+		}
+		break;
+
+	//@V@:Case movie_start_stop
+	case m_movie_start_stop:
+		if (GetValue(m_movie_start_stop)) {
+			if (start_movie()) {
+				SetValue(m_movie_start_stop, 0, Value);
+			}
+
+                } else {
+			stop_movie();
+		}
+		break;
+
+	//@V@:Case picture
+	case m_picture:
+		/* only when not taking movie */
+		if (GetValue(m_picture)) {
+			take_picture();
+		}
+	        SetValue(m_picture,0,Value);
+		break;
+
+	//@V@:Case sldprogress
+	case m_sldprogress:
+		stop_anime();
+		if (s2 != 0) {
+			if (s2->GetNbrImages() > 2) {
+                   		s2->LoadImage(int(val*(s2->GetNbrImages() - 1)/100 + 1));
+			}
+		}
+		if (s3 != 0) {
+			if (s3->GetNbrImages() > 2) {
+				s3->LoadImage(int(val*(s3->GetNbrImages() - 1)/100 + 1));
+			}
+		}
+		if (s4 != 0) {
+			if (s4->GetNbrImages() > 2) {
+				s4->LoadImage(int(val*(s4->GetNbrImages() - 1)/100 + 1));
+			}
+		}
+		if (s5 != 0) {
+			if (s5->GetNbrImages() > 2) {
+				s5->LoadImage(int(val*(s5->GetNbrImages() - 1)/100 + 1));
+			}
+		}
+		GLRenderScene();
+		doStop();
+		break;
+
+	//@V@:Case repere
+	case m_repere:
+		if (GetValue(m_repere)) {
+			s1->Show();
+		} else {
+			s1->Hide();
+		}
+
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case repere plus
+	case m_reperep:
+		repere_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case repere moins
+	case m_reperem:
+		repere_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case node radius smaller
+	case m_noderadm:
+		MultNodeRadius(0.8);
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case node radius larger
+	case m_noderadp:
+		MultNodeRadius(1.25);
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case line radius smaller
+	case m_lineradm:
+		MultEdgeRadius(0.8);
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case line radius larger
+	case m_lineradp:
+		MultEdgeRadius(1.25);
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon x positif
+	case m_vuexp:
+		vue_selon_x_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon x négatif
+	case m_vuexm:
+		vue_selon_x_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon y positif
+	case m_vueyp:
+		vue_selon_y_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon y négatif
+	case m_vueym:
+		vue_selon_y_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon z positif
+	case m_vuezp:
+		vue_selon_z_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case vue selon z négatif
+	case m_vuezm:
+		vue_selon_z_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case phi_plus
+	case m_phiplus:
+		phi_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case phi_moins
+	case m_phimoins:
+		phi_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case theta_plus
+	case m_thetaplus:
+		theta_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case theta_moins
+	case m_thetamoins:
+		theta_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case gamma_plus
+	case m_gammaplus:
+		gamma_plus();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case gamma_moins
+	case m_gammamoins:
+		gamma_moins();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+#if 0
+	//@V@:Case distance plus
+	case m_distpl:
+		distance_plus();
+		GLRenderScene();
+		break;
+
+	//@V@:Case distance plus plus
+	case m_distpp:
+		distance_plus_plus();
+		GLRenderScene();
+		break;
+
+	//@V@:Case distance moins
+	case m_distm:
+		distance_moins();
+		GLRenderScene();
+		break;
+
+	//@V@:Case distance moins moins
+	case m_distmm:
+		distance_moins_moins();
+		GLRenderScene();
+		break;
+#endif
+
+	//@V@:Case depl x positif
+	case m_vuecentre:
+		vue_centre();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case depl vers haut
+	case m_dephaut:
+		depl_haut();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case depl vers bas
+	case m_depbas:
+		depl_bas();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case depl vers gauche
+	case m_depgauche:
+		depl_gauche();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case depl vers droite
+	case m_depdroite:
+		depl_droite();
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case multi vues
+	case m_multi:
+		if (GetValue(m_multi)) {
+			SetMultiView();
+		} else {
+			SetOneView();
+		}
+
+		if (!GetValue(m_start_stop) && !GetValue(m_rev_start_stop)) {
+			GLRenderScene();
+		}
+		break;
+
+	//@V@:Case multi vues
+	case m_sldspeed:
+		_auxTimer->TimerStop();
+		_auxTimer->TimerSet(201 - 2*val);
+		break;
+
+	//@V@:Case multi vues
+	case m_loop:
+		if (GetValue(m_loop)) {
+			LOOP = 1;
+		} else {
+			LOOP = 0;
+		}
+		break;
+
+//@V@:Case auxTimer
+	case cmdAuxTimer:	// Event from aux timer
+		myCanvas->TimerAnimate();
+		if (s2 != 0) {
+			if (s2->GetNbrImages() > 1) {
+				SetValue(m_sldprogress,
+					int(100*(s2->GetCurImage() - 1)/(s2->GetNbrImages() - 1)), Value);
+			}
+
+			if (!LOOP
+				&& (GetValue(m_start_stop)&& s2->GetCurImage() == s2->GetNbrImages())
+					|| (GetValue(m_rev_start_stop) && s2->GetCurImage() == -1))
+			{
+				stop_anime();
+				doStop();
+			}
+		}
+
+		if (s3 != 0) {
+			if (s3->GetNbrImages() > 1) {
+				SetValue(m_sldprogress,
+					int(100*(s3->GetCurImage() - 1)/(s3->GetNbrImages() - 1)), Value);
+			}
+			if ((!LOOP)
+				&& (s3->GetCurImage() == s3->GetNbrImages()))
+			{
+				stop_anime();
+				doStop();
+			}
+		}
+
+		if (s4 != 0) {
+			if (s4->GetNbrImages() > 1) {
+				SetValue(m_sldprogress,
+					int(100*(s4->GetCurImage() - 1)/(s4->GetNbrImages() - 1)), Value);
+			}
+
+			if ((!LOOP)
+				&& (s4->GetCurImage()==s4->GetNbrImages()))
+			{
+				stop_anime();
+				doStop();
+			}
+		}
+
+		if (s5 != 0 ) {
+			if (!is_anime()) {
+				SetValue(m_start_stop, 0, Value);
+			}
+		}
+		break;
+		//@V@:EndCase
+
+	//@V@:Case default
+	// instructions exécutées par défaut
+	default:
+		// route unhandled commands up
+		vCmdWindow::WindowCommand(id, val, cType);
+		break;
+	}
+}
Index: src/EasyAnimcmdw.h
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimcmdw.h,v
retrieving revision 1.1.1.1
retrieving revision 1.7
diff -u -r1.1.1.1 -r1.7
--- src/EasyAnimcmdw.h	27 Jan 2006 19:53:27 -0000	1.1.1.1
+++ src/EasyAnimcmdw.h	16 Nov 2006 22:07:21 -0000	1.7
@@ -1,182 +1,253 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-#ifndef EasyAnimCMDW_H
-#define EasyAnimCMDW_H
-
-#include <v/vcmdwin.h>	// So we can use vCmdWindow
-#include <v/vmenu.h>	// For the menu pane
-#include <v/vutil.h>	// For V Utilities
-#include <v/vcmdpane.h> // command pane
-#include <v/vstatusp.h> // status pane
-#include <v/vtimer.h>	// Timer
-#include <v/vicon.h>   // Icons
-#include "zoompl.vbm"
-#include "zoomm.vbm"
-#include "xplus.vbm"
-#include "xmoins.vbm"
-#include "yplus.vbm"
-#include "ymoins.vbm"
-#include "zplus.vbm"
-#include "zmoins.vbm"
-#include "st_stop.vbm"
-// #include "stop.vbm"
-#include "suiv.vbm"
-#include "prec.vbm"
-// #include "fast.vbm"
-// #include "slow.vbm"
-// #include "save.vbm"
-// #include "open.vbm"
-// #include "print.vbm"
-// #include "filaire.vbm"
-#include "repere.vbm"
-#include "reperep.vbm"
-#include "reperem.vbm"
-#include "noderadp.vbm"
-#include "node.vbm"
-#include "noderadm.vbm"
-#include "line.vbm"
-#include "lineradp.vbm"
-#include "lineradm.vbm"
-#include "side.vbm"
-#include "phipl.vbm"
-#include "phim.vbm"
-#include "thetap.vbm"
-#include "thetam.vbm"
-#include "gammap.vbm"
-#include "gammam.vbm"
-//#include "distpl.vbm"
-//#include "distm.vbm"
-//#include "distpp.vbm"
-//#include "distmm.vbm"
-#include "dephaut.vbm"
-#include "depbas.vbm"
-#include "depg.vbm"
-#include "depd.vbm"
-#include "vuedep.vbm"
-#include "multi.vbm"
-#include "vcentr.vbm"
-
-#ifdef vDEBUG
-#include <v/vdebug.h>
-#endif
-
-#include "EasyAnimmdlg.h"     // my modal dialog
-#include "EasyAnimcnv.h"      // myOGLCanvasPane
-
-static vIcon ssicon(&st_stop_bits[0],st_stop_height,st_stop_width,st_stop_depth);
-static vIcon precicon(&prec_bits[0],prec_height,prec_width,prec_depth);
-static vIcon suivicon(&suiv_bits[0],suiv_height,suiv_width,suiv_depth);
-//static vIcon fasticon(&fast_bits[0],fast_height,fast_width,fast_depth);
-//static vIcon slowicon(&slow_bits[0],slow_height,slow_width,slow_depth);
-
-static vIcon zpicon(&zoompl_bits[0],zoompl_height,zoompl_width,zoompl_depth);
-static vIcon zmicon(&zoomm_bits[0],zoomm_height,zoomm_width,zoomm_depth);
-//static vIcon filicon(&filaire_bits[0],filaire_height,filaire_width,filaire_depth);
-
-static vIcon repicon(&repere_bits[0],repere_height,repere_width,repere_depth);
-static vIcon reppicon(&reperep_bits[0],reperep_height,reperep_width,reperep_depth);
-static vIcon repmicon(&reperem_bits[0],reperem_height,reperem_width,reperem_depth);
-static vIcon nodeicon(&node_bits[0],node_height,node_width,node_depth);
-static vIcon noderadpicon(&noderadp_bits[0],noderadp_height,noderadp_width,noderadp_depth);
-static vIcon noderadmicon(&noderadm_bits[0],noderadm_height,noderadm_width,noderadm_depth);
-static vIcon lineicon(&line_bits[0],line_height,line_width,line_depth);
-static vIcon lineradpicon(&lineradp_bits[0],lineradp_height,lineradp_width,lineradp_depth);
-static vIcon lineradmicon(&lineradm_bits[0],lineradm_height,lineradm_width,lineradm_depth);
-static vIcon sideicon(&side_bits[0],side_height,side_width,side_depth);
-
-static vIcon vuedepicon(&vuedep_bits[0],vuedep_height,vuedep_width,vuedep_depth);
-static vIcon vuexpicon(&xplus_bits[0],xplus_height,xplus_width,xplus_depth);
-static vIcon vuexmicon(&xmoins_bits[0],xmoins_height,xmoins_width,xmoins_depth);
-static vIcon vueypicon(&yplus_bits[0],yplus_height,yplus_width,yplus_depth);
-static vIcon vueymicon(&ymoins_bits[0],ymoins_height,ymoins_width,ymoins_depth);
-static vIcon vuezpicon(&zplus_bits[0],zplus_height,zplus_width,zplus_depth);
-static vIcon vuezmicon(&zmoins_bits[0],zmoins_height,zmoins_width,zmoins_depth);
-
-static vIcon phiplusicon(&phipl_bits[0],phipl_height,phipl_width,phipl_depth);
-static vIcon phimoinsicon(&phim_bits[0],phim_height,phim_width,phim_depth);
-static vIcon thetaplusicon(&thetap_bits[0],thetap_height,thetap_width,thetap_depth);
-static vIcon thetamoinsicon(&thetam_bits[0],thetam_height,thetam_width,thetam_depth);
-static vIcon gammaplusicon(&gammap_bits[0],gammap_height,gammap_width,gammap_depth);
-static vIcon gammamoinsicon(&gammam_bits[0],gammam_height,gammam_width,gammam_depth);
-
-//static vIcon distplicon(&distpl_bits[0],distpl_height,distpl_width,distpl_depth);
-//static vIcon distppicon(&distpp_bits[0],distpp_height,distpp_width,distpp_depth);
-//static vIcon distmicon(&distm_bits[0],distm_height,distm_width,distm_depth);
-//static vIcon distmmicon(&distmm_bits[0],distmm_height,distmm_width,distmm_depth);
-
-
-static vIcon vuecentricon(&vcentr_bits[0],vcentr_height,vcentr_width,vcentr_depth);
-static vIcon dephauticon(&dephaut_bits[0],dephaut_height,dephaut_width,dephaut_depth);
-static vIcon depbasicon(&depbas_bits[0],depbas_height,depbas_width,depbas_depth);
-static vIcon depgaucheicon(&depg_bits[0],depg_height,depg_width,depg_depth);
-static vIcon depdroiteicon(&depd_bits[0],depd_height,depd_width,depd_depth);
-static vIcon multiicon(&multi_bits[0],multi_height,multi_width,multi_depth);
-
-	class myCmdWindow;
-	
-    class myAuxTimer : public vTimer
-      {
-      public:		//---------------------------------------- public
-	myAuxTimer(myCmdWindow* cw) { cmdw = cw; }
-	~myAuxTimer() {}
-	virtual void TimerTick();
-      private:		//--------------------------------------- private
-	myCmdWindow* cmdw;
-      };
-	
-
-
-
-    class myCmdWindow : public vCmdWindow
-      {
-	friend int AppMain(int, char**);	// allow AppMain access
-
-      public:		//---------------------------------------- public
-	myCmdWindow(char*, int, int);
-	virtual ~myCmdWindow();
-	virtual void WindowCommand(ItemVal id, ItemVal val, CmdType cType);
-	void Lecture(char* fichier_config);
-	myAuxTimer* GetmyAuxTimer() {return _auxTimer;}// Aux Timer
-	  protected:	//--------------------------------------- protected
-
-      private:		//--------------------------------------- private
-
-
-	// Standard elements
-	vMenuPane* myMenu;		// For the menu bar
-	myOGLCanvasPane* myCanvas;		// For the canvas
-        vCommandPane* DisplacePane;        // For the Command Pane
-	vCommandPane* RotatePane;		// For the Command Pane
-	vCommandPane* AnimPane;		// For the Command Pane
-	vStatusPane* InfoPane;		// For the Command Pane
-	myAuxTimer* _auxTimer;	// Aux Timer
- 
-	// Dialogs associated with CmdWindow
-	myModalDialog* myMDlg;
-
-      };
-#endif
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+#ifndef EasyAnimcmdw_h
+#define EasyAnimcmdw_h
+
+#include <v/vcmdwin.h>	// So we can use vCmdWindow
+#include <v/vmenu.h>	// For the menu pane
+#include <v/vutil.h>	// For V Utilities
+#include <v/vcmdpane.h> // command pane
+#include <v/vstatusp.h> // status pane
+#include <v/vtimer.h>	// Timer
+#include <v/vicon.h>	// Icons
+
+#include "zoompl.vbm"
+#include "zoomm.vbm"
+#include "xplus.vbm"
+#include "xmoins.vbm"
+#include "yplus.vbm"
+#include "ymoins.vbm"
+#include "zplus.vbm"
+#include "zmoins.vbm"
+#include "rev_st_stop.vbm"
+#include "st_stop.vbm"
+#include "movie_st_stop.vbm"
+#include "picture.vbm"
+#if 0
+#include "stop.vbm"
+#endif
+#include "suiv.vbm"
+#include "prec.vbm"
+#if 0
+#include "fast.vbm"
+#include "slow.vbm"
+#include "save.vbm"
+#include "open.vbm"
+#include "print.vbm"
+#include "filaire.vbm"
+#endif
+#include "repere.vbm"
+#include "reperep.vbm"
+#include "reperem.vbm"
+#include "noderadp.vbm"
+#include "node.vbm"
+#include "noderadm.vbm"
+#include "line.vbm"
+#include "lineradp.vbm"
+#include "lineradm.vbm"
+#include "side.vbm"
+#include "phipl.vbm"
+#include "phim.vbm"
+#include "thetap.vbm"
+#include "thetam.vbm"
+#include "gammap.vbm"
+#include "gammam.vbm"
+#if 0
+#include "distpl.vbm"
+#include "distm.vbm"
+#include "distpp.vbm"
+#include "distmm.vbm"
+#endif
+#include "dephaut.vbm"
+#include "depbas.vbm"
+#include "depg.vbm"
+#include "depd.vbm"
+#include "vuedep.vbm"
+#include "multi.vbm"
+#include "vcentr.vbm"
+
+#ifdef vDEBUG
+#include <v/vdebug.h>
+#endif
+
+#include "EasyAnimmdlg.h"     // my modal dialog
+#include "EasyAnimcnv.h"      // myOGLCanvasPane
+
+static vIcon revssicon(&rev_st_stop_bits[0],
+	rev_st_stop_height, rev_st_stop_width, rev_st_stop_depth);
+static vIcon ssicon(&st_stop_bits[0],
+	st_stop_height, st_stop_width, st_stop_depth);
+static vIcon moviessicon(&movie_st_stop_bits[0],
+	movie_st_stop_height, movie_st_stop_width, movie_st_stop_depth);
+static vIcon pictureicon(&picture_bits[0],
+	picture_height, picture_width, picture_depth);
+static vIcon precicon(&prec_bits[0],
+	prec_height, prec_width, prec_depth);
+static vIcon suivicon(&suiv_bits[0],
+	suiv_height, suiv_width, suiv_depth);
+#if 0
+static vIcon fasticon(&fast_bits[0],
+	fast_height, fast_width, fast_depth);
+static vIcon slowicon(&slow_bits[0],
+	slow_height, slow_width, slow_depth);
+#endif
+
+static vIcon zpicon(&zoompl_bits[0],
+	zoompl_height, zoompl_width, zoompl_depth);
+static vIcon zmicon(&zoomm_bits[0],
+	zoomm_height, zoomm_width, zoomm_depth);
+#if 0
+static vIcon filicon(&filaire_bits[0],
+	filaire_height, filaire_width, filaire_depth);
+#endif
+
+static vIcon repicon(&repere_bits[0],
+	repere_height, repere_width, repere_depth);
+static vIcon reppicon(&reperep_bits[0],
+	reperep_height, reperep_width, reperep_depth);
+static vIcon repmicon(&reperem_bits[0],reperem_height,reperem_width,reperem_depth);
+static vIcon nodeicon(&node_bits[0],
+	node_height, node_width, node_depth);
+static vIcon noderadpicon(&noderadp_bits[0],
+	noderadp_height, noderadp_width, noderadp_depth);
+static vIcon noderadmicon(&noderadm_bits[0],
+	noderadm_height, noderadm_width, noderadm_depth);
+static vIcon lineicon(&line_bits[0],
+	line_height, line_width, line_depth);
+static vIcon lineradpicon(&lineradp_bits[0],
+	lineradp_height, lineradp_width, lineradp_depth);
+static vIcon lineradmicon(&lineradm_bits[0],
+	lineradm_height, lineradm_width, lineradm_depth);
+static vIcon sideicon(&side_bits[0],
+	side_height, side_width, side_depth);
+
+static vIcon vuedepicon(&vuedep_bits[0],
+	vuedep_height, vuedep_width, vuedep_depth);
+static vIcon vuexpicon(&xplus_bits[0],
+	xplus_height, xplus_width, xplus_depth);
+static vIcon vuexmicon(&xmoins_bits[0],
+	xmoins_height, xmoins_width, xmoins_depth);
+static vIcon vueypicon(&yplus_bits[0],
+	yplus_height, yplus_width, yplus_depth);
+static vIcon vueymicon(&ymoins_bits[0],
+	ymoins_height, ymoins_width, ymoins_depth);
+static vIcon vuezpicon(&zplus_bits[0],
+	zplus_height, zplus_width, zplus_depth);
+static vIcon vuezmicon(&zmoins_bits[0],
+	zmoins_height, zmoins_width, zmoins_depth);
+
+static vIcon phiplusicon(&phipl_bits[0],
+	phipl_height, phipl_width, phipl_depth);
+static vIcon phimoinsicon(&phim_bits[0],
+	phim_height, phim_width, phim_depth);
+static vIcon thetaplusicon(&thetap_bits[0],
+	thetap_height, thetap_width, thetap_depth);
+static vIcon thetamoinsicon(&thetam_bits[0],
+	thetam_height, thetam_width, thetam_depth);
+static vIcon gammaplusicon(&gammap_bits[0],
+	gammap_height, gammap_width, gammap_depth);
+static vIcon gammamoinsicon(&gammam_bits[0],
+	gammam_height, gammam_width, gammam_depth);
+
+#if 0
+static vIcon distplicon(&distpl_bits[0],
+	distpl_height, distpl_width, distpl_depth);
+static vIcon distppicon(&distpp_bits[0],
+	distpp_height, distpp_width, distpp_depth);
+static vIcon distmicon(&distm_bits[0],
+	distm_height, distm_width, distm_depth);
+static vIcon distmmicon(&distmm_bits[0],
+	distmm_height, distmm_width, distmm_depth);
+#endif
+
+static vIcon vuecentricon(&vcentr_bits[0],
+	vcentr_height, vcentr_width, vcentr_depth);
+static vIcon dephauticon(&dephaut_bits[0],
+	dephaut_height, dephaut_width, dephaut_depth);
+static vIcon depbasicon(&depbas_bits[0],
+	depbas_height, depbas_width, depbas_depth);
+static vIcon depgaucheicon(&depg_bits[0],
+	depg_height, depg_width, depg_depth);
+static vIcon depdroiteicon(&depd_bits[0],
+	depd_height, depd_width, depd_depth);
+static vIcon multiicon(&multi_bits[0],
+	multi_height, multi_width, multi_depth);
+
+class myCmdWindow;
+
+class myAuxTimer : public vTimer {
+public:		//---------------------------------------- public
+	myAuxTimer(myCmdWindow* cw) { cmdw = cw; }
+	~myAuxTimer(void) {}
+	virtual void TimerTick(void);
+private:	//--------------------------------------- private
+	myCmdWindow* cmdw;
+};
+
+class myCmdWindow : public vCmdWindow {
+	friend int AppMain(int, char**);	// allow AppMain access
+
+public:		//---------------------------------------- public
+	myCmdWindow(char*, int, int);
+	virtual ~myCmdWindow(void);
+	virtual void WindowCommand(ItemVal id, ItemVal val, CmdType cType);
+	void Lecture(char* fichier_config);
+	myAuxTimer* GetmyAuxTimer(void) { return _auxTimer; }// Aux Timer
+protected:	//--------------------------------------- protected
+
+private:	//--------------------------------------- private
+	void doStop(void);
+
+	// Standard elements
+	vMenuPane* myMenu;		// For the menu bar
+	myOGLCanvasPane* myCanvas;		// For the canvas
+        vCommandPane* DisplacePane;        // For the Command Pane
+	vCommandPane* RotatePane;		// For the Command Pane
+	vCommandPane* AnimPane;		// For the Command Pane
+	vStatusPane* InfoPane;		// For the Command Pane
+	myAuxTimer* _auxTimer;	// Aux Timer
+
+	// Dialogs associated with CmdWindow
+	myModalDialog* myMDlg;
+
+	void WindowCommandOpen(ItemVal val, std::string &name,
+		std::string &name2);
+};
+#endif /* EasyAnimcmdw_h */
Index: src/EasyAnimcnv.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimcnv.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.30
diff -u -r1.1.1.1 -r1.30
--- src/EasyAnimcnv.cpp	27 Jan 2006 19:53:26 -0000	1.1.1.1
+++ src/EasyAnimcnv.cpp	28 Nov 2006 00:35:06 -0000	1.30
@@ -24,10 +24,26 @@
 
 */
 
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+#include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
+#include <float.h>
+#include <sstream>
 #include <fstream>
 #include <iostream>
 #include "EasyAnimcnv.h"
@@ -37,72 +53,112 @@
 #define _FATAL   1
 #define _WARNING 0
 
-def_repere* s1=NULL;
-def_volvan* s2=NULL;
-def_volvmo* s3=NULL;
-def_uff* s4=NULL;
-
-//*********************************************************************
-
-istream &toeol(istream &stream)
-  {
-  char c;
-  do { stream.get(c); } while ((c!='\r') && (c!='\n') && (!stream.rdstate()));
-  return stream;
-  }
+def_repere* s1 = 0;
+def_volvan* s2 = 0;
+def_volvmo* s3 = 0;
+def_uff* s4 = 0;
+def_volstream* s5 = 0;
+GLdouble repereSize = 1.;
 
 /********************** Gestion des messages d'erreur *****************/
 
-void ErreurMessage(int i,const char *message)
+void
+ErreurMessage(int i, const char *message)
 {
- if (i) std::cout<<"\n !!! ERREUR FATALE !!!\n";
-	else std::cout<<"\n !!! ATTENTION !!!\n";
-	std::cout<<message<<"\n";
- if (i) exit(1);
+	if (i) {
+		std::cout << "\n !!! ERREUR FATALE !!!\n";
+	} else {
+		std::cout << "\n !!! ATTENTION !!!\n";
+	}
+	std::cout << message << "\n";
+	if (i) {
+		exit(EXIT_FAILURE);
+	}
 }
 
 /*---------------------------------------------------------------------*/
 
 /* impression des messages d'erreur */
 /* si ErrType < 100 : arret du programme */
-void ErreurMessage(int ErrType,const char *mot,int num_lig)
+void
+ErreurMessage(int ErrType, const char *mot, int num_lig)
 {
-
- if (ErrType < 100) printf("\n !!! ERREUR FATALE !!!\n");
-switch (ErrType)
- {
-  case 1 : printf("\t fichier %s impossible a ouvrir. ",mot);
-	   break;
-  case 2 : printf("\t nombre de points %d incorrect dans le fichier %d.",num_lig,mot);
-	   break;
-  case 3 : printf("\t numero de point %d incorrect dans le fichier %s.",num_lig,mot);
-	   break;
-  case 4 : printf("\t nombre d'arretes %d incorrect dans le fichier %d.",num_lig,mot);
-	   break;
-  case 5 : printf("\t numero d'arrete %d incorrect dans le fichier %s.",num_lig,mot);
-	   break;
-  case 6 : printf("\t nombre de faces %d incorrect dans le fichier %d.",num_lig,mot);
-	   break;
-  case 7 : printf("\t numero de faces %d incorrect dans le fichier %s.",num_lig,mot);
-	   break;
-  case 8 : printf("\t nombre de sommets dans la face %d incorrect dans le fichier %s.",num_lig,mot);
-	   break;
-  case 9 : printf("\t sommet non defini dans l'arrete %d du fichier %s.",num_lig,mot);
-	   break;
-
-  case 10 : printf("\t sommet non defini dans la face %d du fichier %s.",num_lig,mot);
-	   break;
-
-  case 101 : printf("\n ****** Lecture de %s avec succes ****** \n",mot);
-	   break;
-  case 102 : printf(" ****** Nombre de lignes : %4d      ****** \n",num_lig);
-	     break;
-  case 103 : printf("\n ****** Lecture de %s             ****** \n",mot);
-	     break;
-  default : printf("\t il y a une erreur a la ligne %d.",num_lig);
-	    break;
- }
- if (ErrType < 100) exit(0);
+	if (ErrType < 100) {
+		printf("\n !!! ERREUR FATALE !!!\n");
+	}
+
+	switch (ErrType) {
+	case 1:
+		printf("\t fichier %s impossible a ouvrir. ", mot);
+		break;
+
+	case 2:
+		printf("\t nombre de points %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 3:
+		printf("\t numero de point %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 4:
+		printf("\t nombre d'arretes %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 5:
+		printf("\t numero d'arrete %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 6:
+		printf("\t nombre de faces %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 7:
+		printf("\t numero de faces %d incorrect dans le fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 8:
+		printf("\t nombre de sommets dans la face %d incorrect "
+			"dans le fichier %s.", num_lig, mot);
+		break;
+
+	case 9:
+		printf("\t sommet non defini dans l'arrete %d du fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 10:
+		printf("\t sommet non defini dans la face %d du fichier %s.",
+			num_lig, mot);
+		break;
+
+	case 101:
+		printf("\n ****** Lecture de %s avec succes ****** \n", mot);
+		break;
+
+	case 102:
+		printf(" ****** Nombre de lignes : %4d      ****** \n",
+			num_lig);
+		break;
+
+	case 103:
+		printf("\n ****** Lecture de %s             ****** \n", mot);
+		break;
+
+	default:
+		printf("\t il y a une erreur a la ligne %d.", num_lig);
+		break;
+	}
+
+	if (ErrType < 100) {
+		// FIXME: shouldn't this be EXIT_FAILURE?
+		exit(EXIT_SUCCESS);
+	}
 }
 
 /*---------------------------------------------------------------------*/
@@ -110,188 +166,130 @@
 /*---------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------*/
-
-def_volvan::def_volvan(const char *VolFileName, int &errcode)
+def_volvan::def_volvan(std::string &VolFileName, def_err &err)
+: vandata(0)
 {
- int ll=strlen(VolFileName);
- strcpy(FileName,VolFileName);
- FileName[ll-4]=0;
- errcode=0;
- /* lecture du fichier *.VOL */
- char titre[180];
- int i,j,k,l,num;
- float x,y,z;
- ifstream VolFile(VolFileName);
- if (!VolFile) { errcode=6; return; }
-
- //Reading the title
- VolFile.getline(titre,179);
-
- // Reading the nodes
- VolFile >> NbrNodes >> toeol;
- if (NbrNodes<=0) { errcode=4; return; }
- node=new NodeStruct[NbrNodes];
- if (node==NULL) { errcode=5; return; }
- xmin=1E10; xmax=-1E10; ymin=1E10; ymax=-1E10; zmin=1E10; zmax=-1E10;
- for (i=0;i<NbrNodes;i++)
-   {
-   VolFile >> node[i].name >> node[i].x >> node[i].y >> node[i].z >> toeol;
-   if(node[i].x<xmin) xmin=node[i].x;
-   if(node[i].x>xmax) xmax=node[i].x;
-   if(node[i].y<ymin) ymin=node[i].y;
-   if(node[i].y>ymax) ymax=node[i].y;
-   if(node[i].z<zmin) zmin=node[i].z;
-   if(node[i].z>zmax) zmax=node[i].z;
-   }/*endfor i*/
-  // Memory allocation for the spheres representing the nodes
-  NodeSphere=gluNewQuadric();
-  gluQuadricNormals(NodeSphere,GLU_FLAT);
-  gluQuadricTexture(NodeSphere,GL_FALSE);
-  gluQuadricOrientation(NodeSphere,GLU_OUTSIDE);
-  gluQuadricDrawStyle(NodeSphere,GLU_FILL);
-
- // Reading the edges
- VolFile >> NbrEdges >> toeol;
- if (NbrEdges<0) { errcode=4; return; }
- if (NbrEdges) 
-    {
-    edge=new EdgeStruct[NbrEdges];
-    if (edge==NULL) { errcode=5; return; }
-    }
- for (i=0;i<NbrEdges;i++)
-   {
-   char Node1Name[40],Node2Name[40];
-   VolFile >> edge[i].name >> Node1Name >> Node2Name >> edge[i].color;
-   edge[i].node1=GetNumNodeOfName(Node1Name);
-   edge[i].node2=GetNumNodeOfName(Node2Name);
-   if (edge[i].node1==-1) { errcode=4; return; }
-   if (edge[i].node2==-1) { errcode=4; return; }
-   }/*endfor i*/
-
- // Reading the sides
- VolFile >> NbrSides >> toeol;
- if (NbrSides<0) { errcode=4; return; }
- if (NbrSides) 
-    {
-    side=new SideStruct[NbrSides];
-    if (side==NULL) { errcode=5; return; }
-    }
- for (i=0;i<NbrSides;i++)
-    {
-    VolFile >> side[i].name >> side[i].NbrNodes;
-    if (side[i].NbrNodes<=0) { errcode=4; return; }
-    side[i].NumNode=new int[side[i].NbrNodes];
-    if (side[i].NumNode==NULL) { errcode=5; return; }
-    for (k=0;k<side[i].NbrNodes;k++)
-       {
-       char NodeName[40];
-       VolFile >> NodeName;
-       side[i].NumNode[k]=GetNumNodeOfName(NodeName);
-       if (side[i].NumNode[k]==-1) { errcode=4; return; }
-       }
-    VolFile >> side[i].color >> toeol;
-    } /*endfor i*/
- VolFile.close();
-
- // Lecture du fichier van s'il existe
- char nomf[200]="";
- strcpy(nomf,FileName);
- strcat(nomf,".van");
- fpos.open(nomf);
- if (!fpos) errcode=2;
- NbrImages=0;
- CurImage=0;
- if (fpos)
-   {
-   while (!fpos.rdstate())
-     {
-     for (i=0; i<NbrNodes;i++) fpos >> x >> y >> z;
-     if (!fpos.rdstate()) NbrImages++;
-     }
-   fpos.close();
-   fpos.clear();
-   fpos.open(nomf);
-   }
- 
- // Lecture du fichier cfg s'il existe
- strcpy(nomf,FileName);
- strcat(nomf,".cfg");
- if (Lecture_Config(nomf)) { errcode+=1; return; }
+	FileName = VolFileName;
+	FileName.erase(VolFileName.length() - 4, 4);
 
- }
+	def_scene::ReadVol(VolFileName, err);
+	if (err.geterr() != 0) {
+		return;
+	}
+
+	// Lecture du fichier cfg s'il existe
+	std::string CfgFileName = FileName + ".cfg";
+	if (Lecture_Config(CfgFileName)) {
+		err.set(err.geterr() + 1);
+	}
+
+	LoadVan(err);
+	if (err.geterr() != 0) {
+		return;
+	}
+}
+
+void
+def_volvan::LoadVan(def_err &err)
+{
+	// Lecture du fichier van s'il existe
+	NbrImages = 0;
+	CurImage = 0;
+	std::string VanFileName = FileName + ".van";
+	std::ifstream fpos(VanFileName.c_str());
+	if (!fpos) {
+		err.set(2, std::string("unable to open van file \"") + VanFileName + "\"");
+	} else {
+		while (true) {
+			for (unsigned n = 0; n < node.size(); n++) {
+				double x, y, z;
+				fpos >> x >> y >> z;
+			}
+			if (!fpos) {
+				break;
+			}
+			NbrImages++;
+		}
+		fpos.close();
+		fpos.clear();
+		fpos.open(VanFileName.c_str());
+
+		vandata = new VecStruct*[NbrImages];
+		vandata[0] = new VecStruct[NbrImages*node.size()];
+
+		for (int i = 1; i < NbrImages; i++) {
+			vandata[i] = vandata[i-1] + node.size();
+		}
+
+		for (int i = 0; i < NbrImages; i++) {
+			for (unsigned n = 0; n < node.size(); n++) {
+				fpos >> vandata[i][n].x
+					>> vandata[i][n].y
+					>> vandata[i][n].z;
+			}
+		}
+	}
+	fpos.close();
+}
 
 /*---------------------------------------------------------------------*/
 
 // destructeur
 def_volvan::~def_volvan()
 {
-if (fpos) fpos.close();
-}	
+	if (vandata) {
+		delete[] vandata[0];
+		delete[] vandata;
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_volvan::Next()
 // Lecture des coordonnées
-  {
-  if (NbrImages) 
-    {
-    int i;
-    if (CurImage<NbrImages) 
-      {
-      for (i=0;i<NbrNodes;i++) fpos>>node[i].x>>node[i].y>>node[i].z;
-      CurImage++;
-      }
-    else
-      {
-      fpos.close();
-      fpos.clear();
-      char VanFileName[200]="";
-      strcpy(VanFileName,FileName);
-      strcat(VanFileName,".van");
-      fpos.open(VanFileName);
-      if (fpos)
-	{
-        for (i=0;i<NbrNodes;i++) fpos>>node[i].x>>node[i].y>>node[i].z;
-        CurImage=1;
-        }
-      else std::cout << "Cannot reopen file " << VanFileName << "\n";
-      }
-    }
-  }
+void
+def_volvan::Next(bool next)
+{
+	if (NbrImages) {
+		if (next) {
+			if (CurImage >= NbrImages) {
+				CurImage = 0;
+			}
+			LoadImage(CurImage);
+			CurImage++;
+
+		} else {
+			if (CurImage < 0) {
+				CurImage = NbrImages - 1;
+			}
+			LoadImage(CurImage);
+			CurImage--;
+		}
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_volvan::LoadImage(int NumImage)
 // Lecture des coordonnées
-  {
-  if (NbrImages) 
-    {
-    if (NumImage>NbrImages) NumImage=NbrImages;
-    if (NumImage<1) NumImage=1;
-    int i,j;
-    if (NumImage>CurImage) while (CurImage<NumImage)
-      {
-      for (i=0;i<NbrNodes;i++) fpos>>node[i].x>>node[i].y>>node[i].z;
-      CurImage++;
-      }
-    else
-      {
-      fpos.close();
-      fpos.clear();
-      char VanFileName[200]="";
-      strcpy(VanFileName,FileName);
-      strcat(VanFileName,".van");
-      fpos.open(VanFileName);
-      CurImage=0;
-      if (fpos) while (CurImage<NumImage)
-	{
-        for (i=0;i<NbrNodes;i++) fpos>>node[i].x>>node[i].y>>node[i].z;
-        CurImage++;
-        }
-      else std::cout << "Cannot reopen file " << VanFileName << "\n";
-      }
-    }
-  }
+void
+def_volvan::LoadImage(int NumImage)
+{
+	if (NbrImages) {
+		if (NumImage >= NbrImages) {
+			NumImage = NbrImages - 1;
+		}
+
+		if (NumImage < 0) {
+			NumImage = 0;
+		}
+
+		for (unsigned n = 0; n < node.size(); n++) {
+			node[n].coords.x = vandata[NumImage][n].x;
+			node[n].coords.y = vandata[NumImage][n].y;
+			node[n].coords.z = vandata[NumImage][n].z;
+		}
+		CurImage = NumImage;
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
@@ -301,253 +299,217 @@
 
 /*---------------------------------------------------------------------*/
 
-def_volvmo::def_volvmo(const char *VolFileName, int &errcode)
+def_volvmo::def_volvmo(std::string &VolFileName, def_err &err)
 {
- int ll=strlen(VolFileName);
- strcpy(FileName,VolFileName);
- FileName[ll-4]=0;
- errcode=0;
- /* lecture du fichier *.VOL */
- char titre[180];
- int i,j,k,l,num;
- ifstream VolFile(VolFileName);
- if (!VolFile) { errcode=6; return; }
-
- //Reading the title
- VolFile.getline(titre,179);
-
- // Reading the nodes
- VolFile >> NbrNodes >> toeol;
- if (NbrNodes<=0) { errcode=4; return; }
- node=new NodeStruct[NbrNodes];
- if (node==NULL) { errcode=5; return; }
- PosRef=new VecStruct[NbrNodes];
- if (PosRef==NULL) { errcode=5; return; }
- DepReal=new VecStruct[NbrNodes];
- if (DepReal==NULL) { errcode=5; return; }
- DepImag=new VecStruct[NbrNodes];
- if (DepImag==NULL) { errcode=5; return; }
- xmin=1E10; xmax=-1E10; ymin=1E10; ymax=-1E10; zmin=1E10; zmax=-1E10;
- for (i=0;i<NbrNodes;i++)
-   {
-   VolFile >> node[i].name >> node[i].x >> node[i].y >> node[i].z >> toeol;
-   if(node[i].x<xmin) xmin=node[i].x;
-   if(node[i].x>xmax) xmax=node[i].x;
-   if(node[i].y<ymin) ymin=node[i].y;
-   if(node[i].y>ymax) ymax=node[i].y;
-   if(node[i].z<zmin) zmin=node[i].z;
-   if(node[i].z>zmax) zmax=node[i].z;
-   PosRef[i].x=node[i].x;
-   PosRef[i].y=node[i].y;
-   PosRef[i].z=node[i].z;
-   DepReal[i].x=0.0; DepImag[i].x=0.0;
-   DepReal[i].y=0.0; DepImag[i].y=0.0;
-   DepReal[i].z=0.0; DepImag[i].z=0.0;
-   }/*endfor i*/
-
-  // Memory allocation for the spheres representing the nodes
-  NodeSphere=gluNewQuadric();
-  gluQuadricNormals(NodeSphere,GLU_FLAT);
-  gluQuadricTexture(NodeSphere,GL_FALSE);
-  gluQuadricOrientation(NodeSphere,GLU_OUTSIDE);
-  gluQuadricDrawStyle(NodeSphere,GLU_FILL);
-
- // Reading the edges
- VolFile >> NbrEdges >> toeol;
- if (NbrEdges<0) { errcode=4; return; }
- if (NbrEdges) 
-    {
-    edge=new EdgeStruct[NbrEdges];
-    if (edge==NULL) { errcode=5; return; }
-    }
- for (i=0;i<NbrEdges;i++)
-   {
-   char Node1Name[40],Node2Name[40];
-   VolFile >> edge[i].name >> Node1Name >> Node2Name >> edge[i].color;
-   edge[i].node1=GetNumNodeOfName(Node1Name);
-   edge[i].node2=GetNumNodeOfName(Node2Name);
-   if (edge[i].node1==-1) { errcode=4; return; }
-   if (edge[i].node2==-1) { errcode=4; return; }
-   }/*endfor i*/
-
- // Reading the sides
- VolFile >> NbrSides >> toeol;
- if (NbrSides<0) { errcode=4; return; }
- if (NbrSides) 
-    {
-    side=new SideStruct[NbrSides];
-    if (side==NULL) { errcode=5; return; }
-    }
- for (i=0;i<NbrSides;i++)
-    {
-    VolFile >> side[i].name >> side[i].NbrNodes;
-    if (side[i].NbrNodes<=0) { errcode=4; return; }
-    side[i].NumNode=new int[side[i].NbrNodes];
-    if (side[i].NumNode==NULL) { errcode=5; return; }
-    for (k=0;k<side[i].NbrNodes;k++)
-       {
-       char NodeName[40];
-       VolFile >> NodeName;
-       side[i].NumNode[k]=GetNumNodeOfName(NodeName);
-       if (side[i].NumNode[k]==-1) { errcode=4; return; }
-       }
-    VolFile >> side[i].color >> toeol;
-    } /*endfor i*/
- VolFile.close();
-
- // Reading vmo file if existing
- if (LoadMode(1)) errcode=2;
-
- // reading cfg if existing
- char nomf[200];
- strcpy(nomf,FileName);
- strcat(nomf,".cfg");
- if (Lecture_Config(nomf)) { errcode+=1; return; }
+	FileName = VolFileName;
+	FileName.erase(VolFileName.length() - 4, 4);
 
- }
+	def_scene::ReadVol(VolFileName, err);
+	if (err.geterr() != 0) {
+		return;
+	}
+
+	PosRef.resize(node.size());
+	DepReal.resize(node.size());
+	DepImag.resize(node.size());
+	for (unsigned i = 0; i < node.size(); i++) {
+		PosRef[i].x = node[i].coords.x;
+		PosRef[i].y = node[i].coords.y;
+		PosRef[i].z = node[i].coords.z;
+		DepReal[i].x = 0.0;
+		DepImag[i].x = 0.0;
+		DepReal[i].y = 0.0;
+		DepImag[i].y = 0.0;
+		DepReal[i].z = 0.0;
+		DepImag[i].z = 0.0;
+	}/*endfor i*/
+
+	// Reading vmo file if existing
+	if (LoadMode(1)) {
+		err.set(2, std::string("unable to load mode"));
+	}
+
+	// reading cfg if existing
+	std::string CfgFileName = FileName + ".cfg";
+	if (Lecture_Config(CfgFileName)) {
+		err.set(err.geterr() + 1);
+		return;
+	}
+}
 
 // destructeur
 def_volvmo::~def_volvmo()
 {
-}	
+}
 
 /*---------------------------------------------------------------------*/
 
 // destructeur
-int def_volvmo::LoadMode(int num)
+int
+def_volvmo::LoadMode(int num)
 {
- char nomf[200]="";
- int imode, ipt,nbrmode;
- strcpy(nomf,FileName);
- strcat(nomf,".vmo");
- ifstream vmofile(nomf);
- // vmofile >> nbrmode;
- if (num<1) return 1;
- for (imode=0; imode<num; imode++)
-   {
-   // Lecture des infos sur le pole correspondant
-   vmofile >> alpha >> beta >> freq >> amor;
-   // Initialisation de DepMax pour eviter des divisions par zero
-   DepMax=1E-9;
-   // Lecture de la partie relle du mode 
-   for (ipt=0; ipt<NbrNodes; ipt++)
-     {
-     vmofile >> DepReal[ipt].x >> DepReal[ipt].y >> DepReal[ipt].z;
-     if (fabs(DepReal[ipt].x-PosRef[ipt].x)>DepMax) 
-       DepMax=fabs(DepReal[ipt].x-PosRef[ipt].x);
-     if (fabs(DepReal[ipt].y-PosRef[ipt].y)>DepMax) 
-       DepMax=fabs(DepReal[ipt].y-PosRef[ipt].y);
-     if (fabs(DepReal[ipt].z-PosRef[ipt].z)>DepMax) 
-       DepMax=fabs(DepReal[ipt].z-PosRef[ipt].z);
-     }
-   // Lecture de la partie imaginaire du mode 
-   for (ipt=0; ipt<NbrNodes; ipt++)
-     {
-     vmofile >> DepImag[ipt].x >> DepImag[ipt].y >> DepImag[ipt].z;
-     if (fabs(DepImag[ipt].x-PosRef[ipt].x)>DepMax) 
-       DepMax=fabs(DepImag[ipt].x-PosRef[ipt].x);
-     if (fabs(DepImag[ipt].y-PosRef[ipt].y)>DepMax) 
-       DepMax=fabs(DepImag[ipt].y-PosRef[ipt].y);
-     if (fabs(DepImag[ipt].z-PosRef[ipt].z)>DepMax) 
-       DepMax=fabs(DepImag[ipt].z-PosRef[ipt].z);
-     }
-   }
- if (vmofile.rdstate()) 
-   {
-   // Puisque ca n'a pas marche, on remet tout a zero
-     alpha=0.0; beta=0.0; freq=0.0; amor=0.0;
-   for (ipt=0; ipt<NbrNodes; ipt++)
-     { DepReal[ipt].x=PosRef[ipt].x; DepImag[ipt].x=PosRef[ipt].x; 
-       DepReal[ipt].y=PosRef[ipt].y; DepImag[ipt].y=PosRef[ipt].y; 
-       DepReal[ipt].z=PosRef[ipt].z; DepImag[ipt].z=PosRef[ipt].z; 
-       node[ipt].x=PosRef[ipt].x; node[ipt].y=PosRef[ipt].y;
-       node[ipt].z=PosRef[ipt].z; }
-   NbrImages=0;
-   return 2;
-   }
- vmofile.close();
- float lcaract;
- lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-               +(zmax-zmin)*(zmax-zmin));
- for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract/DepMax;
-      }
- CurImage=0;
- NbrImages=50;
- return 0;
-}	
+	int imode;
+	std::string VmoFileName = FileName + ".vmo";
+	std::ifstream vmofile(VmoFileName.c_str());
+	// vmofile >> nbrmode;
+	if (num < 1) {
+		return 1;
+	}
+	for (imode = 0; imode < num; imode++) {
+		// Lecture des infos sur le pole correspondant
+		vmofile >> alpha >> beta >> freq >> amor;
+		// Initialisation de DepMax pour eviter des divisions par zero
+		DepMax = 1.E-9;
+		// Lecture de la partie relle du mode
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			vmofile >> DepReal[ipt].x
+				>> DepReal[ipt].y
+				>> DepReal[ipt].z;
+
+			double d;
+			d = fabs(DepReal[ipt].x - PosRef[ipt].x);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+			d = fabs(DepReal[ipt].y - PosRef[ipt].y);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+			d = fabs(DepReal[ipt].z - PosRef[ipt].z);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+		}
+		// Lecture de la partie imaginaire du mode
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			vmofile >> DepImag[ipt].x
+				>> DepImag[ipt].y
+				>> DepImag[ipt].z;
+
+			double d = fabs(DepImag[ipt].x - PosRef[ipt].x);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+			d = fabs(DepImag[ipt].y - PosRef[ipt].y);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+			d = fabs(DepImag[ipt].z - PosRef[ipt].z);
+			if (d > DepMax) {
+				DepMax = d;
+			}
+		}
+	}
+
+	if (vmofile.rdstate()) {
+		// Puisque ca n'a pas marche, on remet tout a zero
+		alpha = 0.0;
+		beta = 0.0;
+		freq = 0.0;
+		amor = 0.0;
+
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			DepReal[ipt].x = PosRef[ipt].x;
+			DepImag[ipt].x = PosRef[ipt].x;
+			DepReal[ipt].y = PosRef[ipt].y;
+			DepImag[ipt].y = PosRef[ipt].y;
+			DepReal[ipt].z = PosRef[ipt].z;
+			DepImag[ipt].z = PosRef[ipt].z;
+			node[ipt].coords.x = PosRef[ipt].x;
+			node[ipt].coords.y = PosRef[ipt].y;
+			node[ipt].coords.z = PosRef[ipt].z;
+		}
+
+		NbrImages = 0;
+		return 2;
+	}
+
+	vmofile.close();
+	float lcaract;
+	lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+	for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+		node[ipt].coords.x = PosRef[ipt].x
+                	+ (DepReal[ipt].x - PosRef[ipt].x)*0.05*lcaract/DepMax;
+		node[ipt].coords.y = PosRef[ipt].y
+			+ (DepReal[ipt].y - PosRef[ipt].y)*0.05*lcaract/DepMax;
+		node[ipt].coords.z = PosRef[ipt].z
+			+ (DepReal[ipt].z - PosRef[ipt].z)*0.05*lcaract/DepMax;
+	}
+
+	CurImage = 0;
+	NbrImages = 50;
+	return 0;
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_volvmo::Next()
 // Construction de l'image modale
-  {
-  if (NbrImages)
-    {
-    int ipt;
-    float lcaract, pi=3.14151695;
-    lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                +(zmax-zmin)*(zmax-zmin));
-    CurImage=(CurImage++)%NbrImages;
-    for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                 +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                 +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                 +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      }
-    }
-  }
+void
+def_volvmo::Next(bool next)
+{
+	if (NbrImages) {
+		float lcaract;
+
+		lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+		float c = 0.05*lcaract*cos(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		float s = 0.05*lcaract*sin(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			node[ipt].coords.x = PosRef[ipt].x
+				+ (DepReal[ipt].x - PosRef[ipt].x)*c
+				+ (DepImag[ipt].x - PosRef[ipt].x)*s;
+			node[ipt].coords.y = PosRef[ipt].y
+				+ (DepReal[ipt].y - PosRef[ipt].y)*c
+				+ (DepImag[ipt].y - PosRef[ipt].y)*s;
+			node[ipt].coords.z = PosRef[ipt].z
+				+ (DepReal[ipt].z - PosRef[ipt].z)*c
+				+ (DepImag[ipt].z - PosRef[ipt].z)*s;
+		}
+	}
+
+	if (next) {
+		CurImage = (++CurImage) % NbrImages;
+
+	} else {
+		if (--CurImage < 0) {
+			CurImage = NbrImages - 1;
+		}
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_volvmo::LoadImage(int NumImage)
 // Building a requested image
-  {
-  if (NbrImages) 
-    {
-    int ipt;
-    float lcaract, pi=3.14151695;
-    lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                 +(zmax-zmin)*(zmax-zmin));
-    CurImage=NumImage%NbrImages;
-    for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                 +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                 +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                 +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      }
-    }
-  }
+void
+def_volvmo::LoadImage(int NumImage)
+{
+	if (NbrImages) {
+		float lcaract;
+
+		lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+		CurImage = NumImage % NbrImages;
+		float c = 0.05*lcaract*cos(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		float s = 0.05*lcaract*sin(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			node[ipt].coords.x = PosRef[ipt].x
+				+ (DepReal[ipt].x - PosRef[ipt].x)*c
+				+ (DepImag[ipt].x - PosRef[ipt].x)*s;
+			node[ipt].coords.y = PosRef[ipt].y
+				+ (DepReal[ipt].y - PosRef[ipt].y)*c
+				+ (DepImag[ipt].y - PosRef[ipt].y)*s;
+			node[ipt].coords.z=PosRef[ipt].z
+				+ (DepReal[ipt].z - PosRef[ipt].z)*c
+				+ (DepImag[ipt].z - PosRef[ipt].z)*s;
+		}
+	}
+}
+
+/***************************************************************************/
 
 /*---------------------------------------------------------------------*/
 
@@ -557,478 +519,823 @@
 
 /*---------------------------------------------------------------------*/
 
-int GetWords2(const char *Ligne, int &nbrmotslus, char **Mot)
 
 /* Fonction permettant d'extraire d'une ligne tous les mots separes par un
    ou plusieurs espaces et tabulations */
+int
+GetWords2(const char *Ligne, strvec &Mot)
+{
+	std::stringstream L(Ligne);
+	return GetWordsInLine(L, Mot);
+} // fin de GetWords
 
-  {
+int
+FindNextMinusOne(std::istream &s, strvec &Mot)
+{
+	while (true) {
+		if (GetWordsInLine(s, Mot) || !s) {
+			return 1;
+		}
+		if (Mot.size() == 1 && Mot[0] == "-1") {
+			return 0;
+		}
+	}
+	return 0;
+}
 
-  char c;
-  int ich,lncrtword=0; // longueur du mot courant;
+/***************************************************************************/
 
-  nbrmotslus=0; // nombre de mots
-  for (ich=0; ich<strlen(Ligne); ich++) // boucle principale
-    {
-      c=Ligne[ich];
-      if (isspace(c) && (lncrtword>0))  // cloture du mot si premier
-        {                               // espace apres un mot
-        Mot[nbrmotslus-1][lncrtword]='\0';
-        lncrtword=0;
-        }
-      // construction du mot si caractere adequat
-      if (!isspace(c))
-        {
-        if (lncrtword==0) nbrmotslus++; // nouveau mot si prem. car. apres espaces
-	//if (nbrmotslus>DIMMOT) RunPrepError(nli,"Too many words in the command");
-        lncrtword++;
-        //if (lncrtword>=LONGMOT) RunPrepError(nli,"Word too long");
-        Mot[nbrmotslus-1][lncrtword-1]=c;
-        }
-     }
+int
+FindNextUff(std::istream &s, int type, strvec &Mot)
+{
+	do {
+		if (FindNextMinusOne(s, Mot)) {
+			return 1;
+		}
+		if (GetWordsInLine(s, Mot)) {
+			return 1;
+		}
+		if (Mot.size() == 1) {
+			char *next = 0;
+			int val = strtol(Mot[0].c_str(), &next, 10);
+			if (next != Mot[0].c_str() && next[0] == '\0') {
+				return 1;
+			}
+			if (val == type) {
+				return 0;
+			}
+		} else if (FindNextMinusOne(s, Mot)) {
+			return 1;
+		}
+	} while (!s.rdstate());
 
-} // fin de GetWords
+	return 1;
+}
 
 /***************************************************************************/
 
-int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
+def_uff::def_uff(std::string &UffFileName1, std::string &UffFileName2,
+	def_err &err)
+{
+	strvec Mot;
+	// First reading for counting the nodes
+	std::ifstream UffFile1(UffFileName1.c_str());
+	if (!UffFile1) {
+		err.set(6, std::string("unable to open UFF file \"") + UffFileName1 + "\"");
+		return;
+	}
+	if (FindNextUff(UffFile1, 15, Mot)) {
+		err.set(8);
+		return;
+	}
+
+	int NbrNodes = 0;
+	do {
+		if (GetWordsInLine(UffFile1, Mot)) {
+			err.set(7);
+			NbrNodes = 0;
+			return;
+		}
+		NbrNodes++;
+	} while (Mot.size() != 1 || Mot[0] != "-1");
+
+	UffFile1.close();
+	NbrNodes--;
+	std::cout << "Number of nodes: " << NbrNodes << std::endl;
+	if (NbrNodes == 0) {
+		err.set(7);
+		return;
+	}
+
+	// Second reading for counting the edges
+	UffFile1.clear();
+	UffFile1.open(UffFileName1.c_str());
+	if (!UffFile1) {
+		err.set(6);
+		return;
+	}
+	if (FindNextUff(UffFile1, 82, Mot)) {
+		err.set(4);
+		return;
+	}
+
+	// Read number of items
+	GetWordsInLine(UffFile1, Mot);
+	int Nentry = atoi(Mot[1].c_str()), in, inode1, inode2;
+	// Drop one comment line
+	if (GetWordsInLine(UffFile1,Mot)) {
+		err.set(3);
+		return;
+	}
+	int NbrEdges = 0;
+	UffFile1 >> inode2;
+	for (in = 1; in < Nentry; in++) {
+		inode1 = inode2;
+		UffFile1 >> inode2;
+		if ((inode1 != 0) && (inode2 != 0)) {
+			NbrEdges++;
+		}
+	}
+	std::cout << "Number of edges: " << NbrEdges << std::endl;
+	if (FindNextMinusOne(UffFile1,Mot)) {
+		err.set(3);
+		NbrEdges = 0;
+		return;
+	}
+
+	UffFile1.close();
+
+	// Allocating memory
+	node.resize(NbrNodes);
+	PosRef.resize(NbrNodes);
+	DepReal.resize(NbrNodes);
+	DepImag.resize(NbrNodes);
+
+	if (NbrEdges) {
+		edge.resize(NbrEdges);
+	}
+
+	// Memory allocation for the spheres representing the nodes
+	NodeSphere = gluNewQuadric();
+	gluQuadricNormals(NodeSphere, GLU_FLAT);
+	gluQuadricTexture(NodeSphere, GL_FALSE);
+	gluQuadricOrientation(NodeSphere, GLU_OUTSIDE);
+	gluQuadricDrawStyle(NodeSphere, GLU_FILL);
+
+	// Second reading to assign the nodes
+	std::cout << "Third reading for the nodes" << std::endl;
+	UffFile1.clear();
+	UffFile1.open(UffFileName1.c_str());
+	if (!UffFile1) {
+		err.set(6, std::string("unable to open UFF file \"") + UffFileName1 + "\"");
+		return;
+	}
+	std::cout << "Third reading" << std::endl;
+	if (FindNextUff(UffFile1, 15, Mot)) {
+		err.set(8);
+		return;
+	}
+
+	xmin = FLT_MAX;
+	xmax = -FLT_MAX;
+	ymin = FLT_MAX;
+	ymax = -FLT_MAX;
+	zmin = FLT_MAX;
+	zmax = -FLT_MAX;
+
+	for (in = 0; in < NbrNodes; in++) {
+		if (GetWordsInLine(UffFile1,Mot)) {
+			err.set(7);
+			return;
+		}
+		node[in].name = Mot[0].c_str();
+		char *next;
+		node[in].coords.x = strtod(Mot[4].c_str(), &next);
+		if (next == Mot[4].c_str() || next[0] != '\0') {
+			err.set(7);
+			return;
+		}
+		node[in].coords.y = strtod(Mot[5].c_str(), &next);
+		if (next == Mot[5].c_str() || next[0] != '\0') {
+			err.set(7);
+			return;
+		}
+		node[in].coords.z = strtod(Mot[6].c_str(), &next);
+		if (next == Mot[6].c_str() || next[0] != '\0') {
+			err.set(7);
+			return;
+		}
+		if (node[in].coords.x < xmin) {
+			xmin = node[in].coords.x;
+		}
+		if (node[in].coords.x > xmax) {
+			xmax = node[in].coords.x;
+		}
+		if (node[in].coords.y < ymin) {
+			ymin = node[in].coords.y;
+		}
+		if (node[in].coords.y > ymax) {
+			ymax = node[in].coords.y;
+		}
+		if (node[in].coords.z < zmin) {
+			zmin = node[in].coords.z;
+		}
+		if (node[in].coords.z > zmax) {
+			zmax = node[in].coords.z;
+		}
+		PosRef[in].x = node[in].coords.x;
+		PosRef[in].y = node[in].coords.y;
+		PosRef[in].z = node[in].coords.z;
+		DepReal[in].x = 0.0;
+		DepImag[in].x = 0.0;
+		DepReal[in].y = 0.0;
+		DepImag[in].y = 0.0;
+		DepReal[in].z = 0.0;
+		DepImag[in].z = 0.0;
+	}
+
+	if (FindNextMinusOne(UffFile1,Mot)) {
+		err.set(7);
+		return;
+	}
+
+	UffFile1.close();
+
+	// Third reading to assign the edges
+	std::cout << "Fourth reading for the edges" << std::endl;
+	UffFile1.clear();
+	UffFile1.open(UffFileName1.c_str());
+	if (!UffFile1) {
+		err.set(6, std::string("unable to open UFF file \"") + UffFileName1 + "\"");
+		return;
+	}
+	std::cout << "Fourth reading" << std::endl;
+	if (FindNextUff(UffFile1, 82, Mot)) {
+		err.set(4);
+		return;
+	}
+
+	// Read number of items
+	if (GetWordsInLine(UffFile1, Mot)) {
+		err.set(3);
+		return;
+	}
+	Nentry = atoi(Mot[1].c_str());
+	// Drop one comment line
+	if (GetWordsInLine(UffFile1,Mot)) {
+		err.set(3);
+		return;
+	}
+
+	NbrEdges = 0;
+	std::string nomnode1, nomnode2;
+	UffFile1 >> nomnode2;
+	EdgePropMap::iterator defedgeprop = edgepropmap.find("1");
+	if (defedgeprop == edgepropmap.end()) {
+		err.set(98, std::string("unable to find edge prop \"1\""));
+		return;
+	}
+
+	for (in = 1; in < Nentry; in++) {
+		nomnode1 = nomnode2;
+		UffFile1 >> nomnode2;
+		if (nomnode1 != "0" && nomnode2 != "0") {
+			edge[NbrEdges].node1 = GetNumNodeOfName(nomnode1);
+			edge[NbrEdges].node2 = GetNumNodeOfName(nomnode2);
+			edge[NbrEdges].prop = defedgeprop->second;
+			if (edge[NbrEdges].node1 == -1) {
+				err.set(4, std::string("unable to find node 1 \"") + nomnode1 + "\" for edge \"" + edge[NbrEdges].name + "\"");
+				return;
+			}
+			if (edge[NbrEdges].node2 == -1) {
+				err.set(4, std::string("unable to find node 2 \"") + nomnode2 + "\" for edge \"" + edge[NbrEdges].name + "\"");
+				return;
+			}
+			std::cout << nomnode1 << " " << nomnode2 << std::endl;
+			std::cout << edge[NbrEdges].node1
+				<< " " << edge[NbrEdges].node2 << std::endl;
+			NbrEdges++;
+		}
+	}
+	std::cout << "Number of edges: " << NbrEdges << std::endl;
+	if (FindNextMinusOne(UffFile1,Mot)) {
+		err.set(3);
+		return;
+	}
+
+	UffFile1.close();
+
+	std::cout << "Number of nodes: " << NbrNodes << std::endl;
+	std::cout << "Number of edges: " << NbrEdges << std::endl;
+	FileName = UffFileName2;
 
-/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
-   ou plusieurs espaces et tabulations */
+	// Reading modes if existing
+	err.set(LoadMode(1));
+}
 
-  {
-  char c;
-  int lncrtword=0; // longueur du mot courant;
-  nbrmotslus=0; // nombre de mots
-  if (stream.rdstate()) return 1;
-  do
-    {
-    // Reading spaces
-    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
-    // Reading word
-    nbrmotslus++; lncrtword=0;
-    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
-           (stream.peek()!='\n') && (stream.peek()!='\r') &&
-           (stream.peek()!='\f') && (stream.peek()!=EOF))
-      {
-      Mot[nbrmotslus-1][lncrtword]=stream.get();
-      lncrtword++;
-      }
-    if (lncrtword==0) nbrmotslus--;
-    else Mot[nbrmotslus-1][lncrtword]='\0';
-    }
-  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
-         &&(stream.peek()!='\r') && !stream.rdstate()); 
-  // Reading end of line characters
-  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
-         || (stream.peek()=='\r')) c=stream.get(); 
-  // Looking for end of file before returning
-  if (stream.peek()==EOF) c=stream.get(); 
-  return 0;
-  } // fin de GetWords
+/*---------------------------------------------------------------------*/
 
-/***************************************************************************/
+// destructeur
+def_uff::~def_uff()
+{
+}
+
+/*---------------------------------------------------------------------*/
 
-int FindNextMinusOne(istream &stream, char **Mot)
+// destructeur
+int
+def_uff::LoadMode(int num)
 {
-int NbrWords;
-do
-  {
-  if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-  }
-  while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
-return 0;
+	int imode, ipt;
+	// Resetting everything
+	for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+		DepReal[ipt].x = PosRef[ipt].x;
+		DepImag[ipt].x = PosRef[ipt].x;
+		DepReal[ipt].y = PosRef[ipt].y;
+		DepImag[ipt].y = PosRef[ipt].y;
+		DepReal[ipt].z = PosRef[ipt].z;
+		DepImag[ipt].z = PosRef[ipt].z;
+		node[ipt].coords.x = PosRef[ipt].x;
+		node[ipt].coords.y = PosRef[ipt].y;
+		node[ipt].coords.z = PosRef[ipt].z;
+	}
+
+	NbrImages = 0;
+
+	// Controlling mode number
+	if (num < 1) {
+		return 1;
+	}
+
+	std::ifstream UffFile(FileName.c_str());
+	if (!UffFile) {
+		return 1;
+	}
+
+	strvec Mot;
+	int ComplexData = 0, WithRot = 0, im;
+	// Skipping the first blocks of type 55
+	for (imode = 1; imode < num; imode++) {
+		if (FindNextUff(UffFile, 55, Mot)) {
+			NbrImages = 0;
+			return 1;
+		}
+
+		if (FindNextMinusOne(UffFile,Mot)) {
+			NbrImages = 0;
+			return 1;
+		}
+	}
+
+	// up to the right one
+	if (FindNextUff(UffFile, 55, Mot)) {
+		NbrImages = 0;
+		return 1;
+	}
+
+	// Skipping the 5 comment lines
+	for (im = 0; im < 5; im++) {
+		if (GetWordsInLine(UffFile,Mot)) {
+			NbrImages = 0;
+			return 2;
+		}
+	}
+
+	// Reading data parameters
+	if (GetWordsInLine(UffFile,Mot)) {
+		NbrImages = 0;
+		return 2;
+	}
+
+	if (Mot.size() != 6) {
+		NbrImages = 0;
+		std::cout << "Record 6: incorrect number of values\n";
+		return 2;
+	}
+
+	if (Mot[0] != "1") {
+		NbrImages = 0;
+		std::cout << "Model not structural\n";
+		return 2;
+	}
+
+	if (Mot[1] != "2") {
+		NbrImages = 0;
+		std::cout << "Analysis not modal\n";
+		return 2;
+	}
+
+	if (Mot[2] != "2" && Mot[2] != "3") {
+		NbrImages = 0;
+		std::cout << "Bad data type\n";
+		return 2;
+	}
+
+	if (Mot[2] == "2") {
+		WithRot = 0;
+
+	} else if (Mot[2] == "3") {
+		WithRot = 1;
+	}
+
+	if (Mot[4] != "2" && Mot[4] != "5") {
+		NbrImages = 0;
+		std::cout << "Bad data type\n";
+		return 2;
+	}
+
+	if (Mot[4] == "2") {
+		ComplexData = 0;
+
+	} else if (Mot[4] == "5") {
+		ComplexData = 1;
+	}
+
+	if (WithRot && Mot[5] != "6") {
+		NbrImages = 0;
+		std::cout << "NDV incorrect\n";
+		return 2;
+	}
+
+	if ((WithRot == 0) && Mot[5] != "3") {
+		NbrImages = 0;
+		std::cout << "NDV incorrect\n";
+		return 2;
+	}
+
+	// Skipping record 7
+	if (GetWordsInLine(UffFile, Mot)) {
+		NbrImages = 0;
+		return 2;
+	}
+
+	// Reading record 8
+	if (GetWordsInLine(UffFile, Mot)) {
+		NbrImages = 0;
+		return 2;
+	}
+
+	if (Mot.size() != 4) {
+		NbrImages = 0;
+		std::cout << "Record 8: incorrect number of values\n";
+		return 2;
+	}
+
+	char *next;
+	freq = strtod(Mot[0].c_str(), &next);
+	if (next == Mot[0].c_str() || next[0] != '\0') {
+		NbrImages = 0;
+		return 2;
+	}
+
+	amor = strtod(Mot[2].c_str(), &next);
+	if (next == Mot[2].c_str() || next[0] != '\0') {
+		NbrImages = 0;
+		return 2;
+	}
+
+	std::cout << "freq=" << freq << " amor=" << amor << std::endl;
+	// Initialisation of DepMax to avoid divisions by zero
+	DepMax = 1.E-9;
+	do {
+		if (GetWordsInLine(UffFile,Mot)) {
+			NbrImages = -1;
+		}
+
+		if (Mot[0] != "-1") {
+			ipt = GetNumNodeOfName(Mot[0]);
+			std::cout << "Node " << Mot[0] << std::endl;
+			if (ipt < 0) {
+				NbrImages=-1;
+			}
+ 
+			if (ipt != -1) {
+				if (GetWordsInLine(UffFile,Mot)) {
+					NbrImages = -1;
+				}
+				std::cout << "NbrWords=" << Mot.size()
+					<< " WithRot=" << WithRot
+					<< " Cplx=" << ComplexData
+					<< std::endl;
+				if (Mot.size() != unsigned(3*(1 + ComplexData)*(1 + WithRot))) {
+					NbrImages = -1;
+					std::cout << "Record 10: "
+						"incorrect number of data\n";
+					return 2;
+				}
+
+				if (ComplexData) {
+					char *next;
+					DepReal[ipt].x = PosRef[ipt].x
+						+ strtod(Mot[0].c_str(), &next);
+					if (next == Mot[0].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepImag[ipt].x = PosRef[ipt].x
+						+ strtod(Mot[1].c_str(), &next);
+					if (next == Mot[1].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepReal[ipt].y = PosRef[ipt].y
+						+ strtod(Mot[2].c_str(), &next);
+					if (next == Mot[2].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepImag[ipt].y = PosRef[ipt].y
+						+ strtod(Mot[3].c_str(), &next);
+					if (next == Mot[3].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepReal[ipt].z = PosRef[ipt].z
+						+ strtod(Mot[4].c_str(), &next);
+					if (next == Mot[4].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepImag[ipt].z = PosRef[ipt].z
+						+ strtod(Mot[6].c_str(), &next);
+					if (next == Mot[5].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+
+				} else {
+					char *next;
+					DepReal[ipt].x = PosRef[ipt].x
+						+ strtod(Mot[0].c_str(), &next);
+					if (next == Mot[0].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepReal[ipt].y = PosRef[ipt].y
+						+ strtod(Mot[1].c_str(), &next);
+					if (next == Mot[1].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+					DepReal[ipt].z = PosRef[ipt].z
+						+ strtod(Mot[2].c_str(), &next);
+					if (next == Mot[2].c_str() || next[0] != '\0') {
+						NbrImages = -1;
+						return 2;
+					}
+				}
+
+				double d;
+				d = fabs(DepReal[ipt].x - PosRef[ipt].x);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+				d = fabs(DepReal[ipt].y - PosRef[ipt].y);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+				d = fabs(DepReal[ipt].z - PosRef[ipt].z);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+				d = fabs(DepImag[ipt].x - PosRef[ipt].x);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+				d = fabs(DepImag[ipt].y - PosRef[ipt].y);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+				d = fabs(DepImag[ipt].z - PosRef[ipt].z);
+				if (d > DepMax) {
+					DepMax = d;
+				}
+			}
+		}
+	} while (Mot.size() != 1 || Mot[0] != "-1");
+
+	UffFile.close();
+	if (NbrImages == -1) {
+		// Puisque ca n'a pas marche, on remet tout a zero
+		alpha = 0.0;
+		beta = 0.0;
+		freq = 0.0;
+		amor = 0.0;
+
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			DepReal[ipt].x = PosRef[ipt].x;
+			DepImag[ipt].x = PosRef[ipt].x;
+			DepReal[ipt].y = PosRef[ipt].y;
+			DepImag[ipt].y = PosRef[ipt].y;
+			DepReal[ipt].z = PosRef[ipt].z;
+			DepImag[ipt].z = PosRef[ipt].z;
+			node[ipt].coords.x = PosRef[ipt].x;
+			node[ipt].coords.y = PosRef[ipt].y;
+			node[ipt].coords.z = PosRef[ipt].z;
+		}
+
+		NbrImages = 0;
+		return 2;
+	}
+
+	float lcaract;
+	lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+		+ (ymax - ymin)*(ymax - ymin)
+		+ (zmax - zmin)*(zmax - zmin));
+	float d = 0.05*lcaract/DepMax;
+	for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+		node[ipt].coords.x = PosRef[ipt].x
+			+ (DepReal[ipt].x - PosRef[ipt].x)*d;
+		node[ipt].coords.y = PosRef[ipt].y
+			+ (DepReal[ipt].y - PosRef[ipt].y)*d;
+		node[ipt].coords.z = PosRef[ipt].z
+			+ (DepReal[ipt].z - PosRef[ipt].z)*d;
+	}
+
+	CurImage = 0;
+	NbrImages = 50;
+	return 0;
 }
 
-/***************************************************************************/
+/*---------------------------------------------------------------------*/
 
-int FindNextUff(istream &stream, int type, char **Mot)
+// Construction de l'image modale
+void
+def_uff::Next(bool next)
 {
-int NbrWords;
- do
-   {
-   if (FindNextMinusOne(stream,Mot)) return 1;
-   if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-   if ((NbrWords==1) && (atoi(Mot[0])==type))
-     return 0;
-   else if (FindNextMinusOne(stream,Mot)) return 1;
-   }
-   while (!stream.rdstate());
- return 1;
+	if (NbrImages) {
+		float lcaract;
+
+		lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+
+		if (next) {
+			CurImage = (CurImage++) % NbrImages;
+
+		} else {
+			--CurImage;
+			if (CurImage < 0) {
+				CurImage = NbrImages - 1;
+			}
+		}
+		float c = 0.05*lcaract*cos(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		float s = 0.05*lcaract*sin(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			node[ipt].coords.x = PosRef[ipt].x
+				+ (DepReal[ipt].x - PosRef[ipt].x)*c
+				+ (DepImag[ipt].x - PosRef[ipt].x)*s;
+			node[ipt].coords.y = PosRef[ipt].y
+				+ (DepReal[ipt].y - PosRef[ipt].y)*c
+				+ (DepImag[ipt].y - PosRef[ipt].y)*s;
+			node[ipt].coords.z = PosRef[ipt].z
+				+ (DepReal[ipt].z - PosRef[ipt].z)*c
+				+ (DepImag[ipt].z - PosRef[ipt].z)*s;
+		}
+ 	}
 }
 
-/***************************************************************************/
+/*---------------------------------------------------------------------*/
 
-def_uff::def_uff(const char *UffFileName1,const char *UffFileName2, 
-                       int &errcode)
+// Building a requested image
+void
+def_uff::LoadImage(int NumImage)
 {
- char Ligne[181],**Mot;
- Mot=new char*[20];
- int im;
- for (im=0;im<20;im++) Mot[im]=new char[30];
- int NbrWords;
- // First reading for counting the nodes
- ifstream UffFile1(UffFileName1);
- if (!UffFile1) { errcode=6; return; }
- if (FindNextUff(UffFile1,15,Mot)) { errcode=8; return; }
- NbrNodes=0;
- do
-  {
-  if (GetWordsInLine(UffFile1,NbrWords,Mot)) { errcode=7; NbrNodes=0; return; }
-  NbrNodes++;
-  }
- while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
- UffFile1.close();
- NbrNodes--;
- cout << "Number of nodes:" << NbrNodes <<  endl;
- if (NbrNodes==0) { errcode=7; return; }  
-
- // Second reading for counting the edges
- UffFile1.clear();
- UffFile1.open(UffFileName1);
- if (!UffFile1) { errcode=6; return; }
- if (FindNextUff(UffFile1,82,Mot)) { errcode=4; return; }
- // Read number of items
- GetWordsInLine(UffFile1,NbrWords,Mot);
- int Nentry=atoi(Mot[1]),in,inode1,inode2;
- // Drop one comment line
- if (GetWordsInLine(UffFile1,NbrWords,Mot)) { errcode=3; NbrEdges=0; return; }
- NbrEdges=0;
- UffFile1 >> inode2;
- for (in=1; in<Nentry; in++)
-       {
-       inode1=inode2;
-       UffFile1 >> inode2;
-       if ((inode1!=0) && (inode2!=0)) NbrEdges++;
-       }
- cout << "NbrEdges=" << NbrEdges << endl;
- if (FindNextMinusOne(UffFile1,Mot)) { errcode=3; NbrEdges=0; return; } 
- UffFile1.close();
-
- // Allocating memory
- node=new NodeStruct[NbrNodes];
- if (node==NULL) { errcode=5; return; }
- PosRef=new VecStruct[NbrNodes];
- if (PosRef==NULL) { errcode=5; return; }
- DepReal=new VecStruct[NbrNodes];
- if (DepReal==NULL) { errcode=5; return; }
- DepImag=new VecStruct[NbrNodes];
- if (DepImag==NULL) { errcode=5; return; }
-
- if (NbrEdges) edge=new EdgeStruct[NbrEdges];
-
- // Memory allocation for the spheres representing the nodes
- NodeSphere=gluNewQuadric();
- gluQuadricNormals(NodeSphere,GLU_FLAT);
- gluQuadricTexture(NodeSphere,GL_FALSE);
- gluQuadricOrientation(NodeSphere,GLU_OUTSIDE);
- gluQuadricDrawStyle(NodeSphere,GLU_FILL);
-
- // Second reading to assign the nodes
- cout << "Third reading for the nodes" << endl;
- UffFile1.clear();
- UffFile1.open(UffFileName1);
- if (!UffFile1) { errcode=6; return; }
- cout << "Third reading" << endl;
- if (FindNextUff(UffFile1,15,Mot)) 
-     { errcode=8; NbrNodes=0; NbrEdges=0; return; }
- xmin=1E10; xmax=-1E10; ymin=1E10; ymax=-1E10; zmin=1E10; zmax=-1E10;
- for (in=0; in<NbrNodes; in++)
-       {
-       if (GetWordsInLine(UffFile1,NbrWords,Mot))
-           { errcode=7; NbrNodes=0; NbrEdges=0; return; }
-       strcpy(node[in].name,Mot[0]);
-       node[in].x=atof(Mot[4]);
-       node[in].y=atof(Mot[5]);
-       node[in].z=atof(Mot[6]);
-       if(node[in].x<xmin) xmin=node[in].x;
-       if(node[in].x>xmax) xmax=node[in].x;
-       if(node[in].y<ymin) ymin=node[in].y;
-       if(node[in].y>ymax) ymax=node[in].y;
-       if(node[in].z<zmin) zmin=node[in].z;
-       if(node[in].z>zmax) zmax=node[in].z;
-       PosRef[in].x=node[in].x;
-       PosRef[in].y=node[in].y;
-       PosRef[in].z=node[in].z;
-       DepReal[in].x=0.0; DepImag[in].x=0.0;
-       DepReal[in].y=0.0; DepImag[in].y=0.0;
-       DepReal[in].z=0.0; DepImag[in].z=0.0;
-       }
- if (FindNextMinusOne(UffFile1,Mot)) 
-    { errcode=7; NbrNodes=0; NbrEdges=0; return; } 
- UffFile1.close();
-
- // Third reading to assign the edges
- cout << "Fourth reading for the edges" << endl;
- UffFile1.clear();
- UffFile1.open(UffFileName1);
- if (!UffFile1) { errcode=6; return; }
- cout << "Fourth reading" << endl;
- if (FindNextUff(UffFile1,82,Mot))
-    { errcode=4; NbrNodes=0; NbrEdges=0; return; } 
- // Read number of items
- if (GetWordsInLine(UffFile1,NbrWords,Mot))
-    { errcode=3; NbrNodes=0; NbrEdges=0; return; } 
- Nentry=atoi(Mot[1]);
- // Drop one comment line
- if (GetWordsInLine(UffFile1,NbrWords,Mot))
-    { errcode=3; NbrNodes=0; NbrEdges=0; return; } 
- NbrEdges=0;
- char nomnode1[20],nomnode2[20];
- UffFile1 >> nomnode2;
- for (in=1; in<Nentry; in++)
-       {
-       strcpy(nomnode1,nomnode2);
-       UffFile1 >> nomnode2;
-       if ((strcmp(nomnode1,"0")!=0) && (strcmp(nomnode2,"0")!=0)) 
-           { 
-           NbrEdges++; 
-           edge[NbrEdges-1].node1=GetNumNodeOfName(nomnode1);
-           edge[NbrEdges-1].node2=GetNumNodeOfName(nomnode2);
-           edge[NbrEdges-1].color=1;
-           if (edge[NbrEdges-1].node1==-1) { errcode=4; return; }
-           if (edge[NbrEdges-1].node2==-1) { errcode=4; return; }
-           cout << nomnode1 << " " << nomnode2 << endl;
-           cout << edge[NbrEdges-1].node1 << " " 
-                << edge[NbrEdges-1].node2 << endl;
-	   }
-       }
- cout << "NbrEdges=" << NbrEdges << endl;
- if (FindNextMinusOne(UffFile1,Mot))
-    { errcode=3; NbrNodes=0; NbrEdges=0; return; } 
- UffFile1.close();
-
- cout << "Number of nodes:" << NbrNodes <<  endl;
- cout << "Number of edges:" << NbrEdges <<  endl;
- strcpy(FileName,UffFileName2);
+	if (NbrImages) {
+		float lcaract;
 
- // Reading modes if existing
- errcode=LoadMode(1);
- 
+		lcaract = sqrt((xmax - xmin)*(xmax - xmin)
+			+ (ymax - ymin)*(ymax - ymin)
+			+ (zmax - zmin)*(zmax - zmin));
+		CurImage = NumImage % NbrImages;
+		float c = 0.05*lcaract*cos(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		float s = 0.05*lcaract*sin(2.0*CurImage*M_PI/NbrImages)/DepMax;
+		for (unsigned ipt = 0; ipt < node.size(); ipt++) {
+			node[ipt].coords.x = PosRef[ipt].x
+				+ (DepReal[ipt].x - PosRef[ipt].x)*c
+				+ (DepImag[ipt].x - PosRef[ipt].x)*s;
+			node[ipt].coords.y = PosRef[ipt].y
+				+ (DepReal[ipt].y - PosRef[ipt].y)*c
+				+ (DepImag[ipt].y - PosRef[ipt].y)*s;
+			node[ipt].coords.z = PosRef[ipt].z
+				+ (DepReal[ipt].z - PosRef[ipt].z)*c
+				+ (DepImag[ipt].z - PosRef[ipt].z)*s;
+		}
+	}
 }
 
 /*---------------------------------------------------------------------*/
+/*                    Methods relative to def_volstream                */
+/*---------------------------------------------------------------------*/
 
-// destructeur
-def_uff::~def_uff()
+/*---------------------------------------------------------------------*/
+def_volstream::def_volstream(std::string &VolFileName, UseSocket *s,
+	def_err &err)
+: FileName(VolFileName),
+sock(s),
+vandata(0)
 {
-}	
+	// remove the ".vol" part from the name
+	FileName.erase(VolFileName.length() - 4, 4);
+
+	def_scene::ReadVol(VolFileName, err);
+	if (err.geterr() != 0) {
+		return;
+	}
+
+	// Lecture du fichier cfg s'il existe
+	std::string CfgFileName = FileName + ".cfg";
+	if (Lecture_Config(CfgFileName)) {
+		err.set(err.geterr() + 1 );
+	}
+
+	size = 3*node.size();
+	vandata = new double[size];
+	size *= sizeof(double);
+	recv_flags = MSG_WAITALL|MSG_NOSIGNAL;
+
+	NbrImages = 1;
+}
 
 /*---------------------------------------------------------------------*/
 
 // destructeur
-int def_uff::LoadMode(int num)
+def_volstream::~def_volstream()
 {
- int imode, ipt,nbrmode;
- // Resetting everything
- for (ipt=0; ipt<NbrNodes; ipt++)
-     { DepReal[ipt].x=PosRef[ipt].x; DepImag[ipt].x=PosRef[ipt].x; 
-       DepReal[ipt].y=PosRef[ipt].y; DepImag[ipt].y=PosRef[ipt].y; 
-       DepReal[ipt].z=PosRef[ipt].z; DepImag[ipt].z=PosRef[ipt].z; 
-       node[ipt].x=PosRef[ipt].x; node[ipt].y=PosRef[ipt].y;
-       node[ipt].z=PosRef[ipt].z; }
- NbrImages=0;
-
- // Controlling mode number
- if (num<1) return 1;
-
- ifstream UffFile(FileName);
- if (!UffFile) { return 1; }
- char **Mot;
- Mot=new char*[20];
- int im;
- for (im=0;im<20;im++) Mot[im]=new char[30];
-
- int ComplexData, WithRot,NbrWords;
- // Skipping the first blocks of type 55
- for (imode=1; imode<num; imode++)
-   {
-   if (FindNextUff(UffFile,55,Mot)) { NbrImages=0; return 1; }
-   if (FindNextMinusOne(UffFile,Mot)) { NbrImages=0; return 1; }
-   }
- // up to the right one 
- if (FindNextUff(UffFile,55,Mot)) { NbrImages=0; return 1; }
- // Skipping the 5 comment lines
- for (im=0; im<5; im++)  if (GetWordsInLine(UffFile,NbrWords,Mot))
-   { NbrImages=0; return 2; } 
- // Reading data parameters
- if (GetWordsInLine(UffFile,NbrWords,Mot))
-   { NbrImages=0; return 2; }  
- if (NbrWords!=6)
-   { NbrImages=0; cout << "Record 6: incorrect number of values\n"; return 2; }  
- if (strcmp(Mot[0],"1")!=0)
-   { NbrImages=0; cout << "Model not structural\n"; return 2; }  
- if (strcmp(Mot[1],"2")!=0)
-   { NbrImages=0; cout << "Analysis not modal\n"; return 2; }  
- if ((strcmp(Mot[2],"2")!=0) && (strcmp(Mot[2],"3")!=0))
-   { NbrImages=0; cout << "Bad data type\n"; return 2; }  
- if (!strcmp(Mot[2],"2")) WithRot=0;
- if (!strcmp(Mot[2],"3")) WithRot=1;
- if ((strcmp(Mot[4],"2")!=0) && (strcmp(Mot[4],"5")!=0))
-   { NbrImages=0; cout << "Bad data type\n"; return 2; }  
- if (!strcmp(Mot[4],"2")) ComplexData=0;
- if (!strcmp(Mot[4],"5")) ComplexData=1;
- if (WithRot &&  (strcmp(Mot[5],"6")!=0))
-   { NbrImages=0; cout << "NDV incorrect\n"; return 2; }  
- if ((WithRot==0) &&  (strcmp(Mot[5],"3")!=0))
-   { NbrImages=0; cout << "NDV incorrect\n"; return 2; }  
- // Skipping record 7
- if (GetWordsInLine(UffFile,NbrWords,Mot))
-   { NbrImages=0; return 2; }  
- // Reading record 8
- if (GetWordsInLine(UffFile,NbrWords,Mot))
-   { NbrImages=0; return 2; }  
- if (NbrWords!=4)
-   { NbrImages=0; cout << "Record 8: incorrect number of values\n"; return 2; }
- freq=atof(Mot[0]);
- amor=atof(Mot[2]);
- cout << "freq=" << freq << " amor=" << amor << endl;
- // Initialisation of DepMax to avoid divisions by zero
- DepMax=1E-9;
- do
-  {
-  if (GetWordsInLine(UffFile,NbrWords,Mot)) { NbrImages=-1; }
-  if (strcmp(Mot[0],"-1")!=0)
-   {
-   ipt=GetNumNodeOfName(Mot[0]);
-   cout << "Node " << Mot[0] << endl;
-   if (ipt<0) { NbrImages=-1; }
-   if(ipt!=-1)
-     {
-     if (GetWordsInLine(UffFile,NbrWords,Mot)) { NbrImages=-1; }
-     cout << "NbrWords=" << NbrWords << " WithRot=" << WithRot 
-          << " Cplx=" << ComplexData << endl;
-     if (NbrWords!=(3*(1+ComplexData)*(1+WithRot)))
-      { NbrImages=-1; cout<<"Record 10: incorrect number of data\n"; }
-     if (ComplexData)
-       {
-       DepReal[ipt].x=PosRef[ipt].x+atof(Mot[0]);
-       DepImag[ipt].x=PosRef[ipt].x+atof(Mot[1]);
-       DepReal[ipt].y=PosRef[ipt].y+atof(Mot[2]); 
-       DepImag[ipt].y=PosRef[ipt].y+atof(Mot[3]);
-       DepReal[ipt].z=PosRef[ipt].z+atof(Mot[4]); 
-       DepImag[ipt].z=PosRef[ipt].z+atof(Mot[6]);
-       }
-     else
-       {
-       DepReal[ipt].x=PosRef[ipt].x+atof(Mot[0]);
-       DepReal[ipt].y=PosRef[ipt].y+atof(Mot[1]);
-       DepReal[ipt].z=PosRef[ipt].z+atof(Mot[2]);
-       }
-     if (fabs(DepReal[ipt].x-PosRef[ipt].x)>DepMax) 
-       DepMax=fabs(DepReal[ipt].x-PosRef[ipt].x);
-     if (fabs(DepReal[ipt].y-PosRef[ipt].y)>DepMax) 
-       DepMax=fabs(DepReal[ipt].y-PosRef[ipt].y);
-     if (fabs(DepReal[ipt].z-PosRef[ipt].z)>DepMax) 
-       DepMax=fabs(DepReal[ipt].z-PosRef[ipt].z);
-     if (fabs(DepImag[ipt].x-PosRef[ipt].x)>DepMax) 
-       DepMax=fabs(DepImag[ipt].x-PosRef[ipt].x);
-     if (fabs(DepImag[ipt].y-PosRef[ipt].y)>DepMax) 
-       DepMax=fabs(DepImag[ipt].y-PosRef[ipt].y);
-     if (fabs(DepImag[ipt].z-PosRef[ipt].z)>DepMax) 
-       DepMax=fabs(DepImag[ipt].z-PosRef[ipt].z);
-     }
-   }
-  }
- while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
-
- UffFile.close();
- if (NbrImages==-1) 
-   {
-   // Puisque ca n'a pas marche, on remet tout a zero
-     alpha=0.0; beta=0.0; freq=0.0; amor=0.0;
-   for (ipt=0; ipt<NbrNodes; ipt++)
-     { DepReal[ipt].x=PosRef[ipt].x; DepImag[ipt].x=PosRef[ipt].x; 
-       DepReal[ipt].y=PosRef[ipt].y; DepImag[ipt].y=PosRef[ipt].y; 
-       DepReal[ipt].z=PosRef[ipt].z; DepImag[ipt].z=PosRef[ipt].z; 
-       node[ipt].x=PosRef[ipt].x; node[ipt].y=PosRef[ipt].y;
-       node[ipt].z=PosRef[ipt].z; }
-   NbrImages=0;
-   return 2;
-   }
-
- float lcaract;
- lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-               +(zmax-zmin)*(zmax-zmin));
- for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract/DepMax;
-      }
- CurImage=0;
- NbrImages=50;
- return 0;
-}	
+	if (sock) {
+		delete sock;
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_uff::Next()
-// Construction de l'image modale
-  {
-  if (NbrImages)
-    {
-    int ipt;
-    float lcaract, pi=3.14151695;
-    lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                +(zmax-zmin)*(zmax-zmin));
-    CurImage=(CurImage++)%NbrImages;
-    for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                 +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                 +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                 +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      }
-    }
-  }
+// Lecture des coordonnées
+void
+def_volstream::Next(bool next)
+{
+	if (next) {
+		LoadImage(CurImage);
+		CurImage++;
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
-void def_uff::LoadImage(int NumImage)
-// Building a requested image
-  {
-  if (NbrImages) 
-    {
-    int ipt;
-    float lcaract, pi=3.14151695;
-    lcaract=sqrt((xmax-xmin)*(xmax-xmin)+(ymax-ymin)*(ymax-ymin)
-                 +(zmax-zmin)*(zmax-zmin));
-    CurImage=NumImage%NbrImages;
-    for (ipt=0;ipt<NbrNodes;ipt++)
-      {
-      node[ipt].x=PosRef[ipt].x
-                 +(DepReal[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].x-PosRef[ipt].x)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].y=PosRef[ipt].y
-                 +(DepReal[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].y-PosRef[ipt].y)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      node[ipt].z=PosRef[ipt].z
-                 +(DepReal[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *cos(2.0*CurImage*pi/NbrImages)/DepMax
-                 +(DepImag[ipt].z-PosRef[ipt].z)*0.05*lcaract
-                       *sin(2.0*CurImage*pi/NbrImages)/DepMax;
-      }
-    }
-  }
+// Lecture des coordonnées
+void
+def_volstream::LoadImage(int NumImage)
+{
+	if (!sock->Connected()) {
+		try {
+			sock->Connect();
+
+		} catch (UseSocket::Error) {
+			stop_anime();
+			return;
+		}
+	}
+
+	switch (recv(sock->GetSock(), (void *)vandata, size, recv_flags)) {
+	case 0:
+do_abandon:;
+		std::cout << "communication closed by peer" << std::endl;
+		sock->Abandon();
+		stop_anime();
+		break;
+
+	case -1: {
+		int save_errno = errno;
+
+		/* some errno values may be legal */
+		switch (save_errno) {
+		case ECONNRESET:
+			goto do_abandon;
+		}
+
+		char *err_msg = strerror(save_errno);
+
+		std::cout << "recv failed (" << save_errno << ": "
+				<< err_msg << ")" << std::endl;
+		throw;
+	}
+
+	default: {
+		double *d = vandata;
+		for (unsigned n = 0; n < node.size(); n++, d += 3) {
+			/* load from stream */
+			node[n].coords.x = d[0];
+			node[n].coords.y = d[1];
+			node[n].coords.z = d[2];
+		}
+		} break;
+	}
+}
+
+int
+def_volstream::SetSocket(std::string& host, int port)
+{
+	if (sock != 0) {
+		delete sock;
+	}
+
+	sock = new UseInetSocket(host, port, false);
+
+	return 0;
+}
+
+int
+def_volstream::SetSocket(std::string& path)
+{
+	if (sock != 0) {
+		delete sock;
+	}
+
+	sock = new UseLocalSocket(path, false);
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------*/
 
 /*---------------------------------------------------------------------*/
 /*                    Methods relative to def_repere                   */
@@ -1038,242 +1345,460 @@
 
 //dessine un repere a partir du fichier repere.vol
 def_repere::def_repere()
-  {
-  NbrNodes=40;
-  NbrEdges=31;
-  xmin=-0.3; xmax=1.0;
-  ymin=-0.3; ymax=1.0;
-  zmin=-0.3; zmax=1.0;
-  node = new NodeStruct[NbrNodes];
-  if (node==NULL) ErreurMessage(_FATAL,"Memory allocation problem");
-  edge= new EdgeStruct[NbrEdges];
-  if (edge==NULL) ErreurMessage(_FATAL,"Memory allocation problem");
-	
-  node[0].x=0.0f; node[0].y= 0.0f; node[0].z= 0.0f;
-  node[1].x=1.0f; node[1].y= 0.0f; node[1].z= 0.0f;
-  node[2].x=0.8f; node[2].y= 0.1f; node[2].z= 0.0f;
-  node[3].x=0.8f; node[3].y= 0.0f; node[3].z= 0.1f;
-  node[4].x=0.8f; node[4].y=-0.1f; node[4].z= 0.0f;
-  node[5].x=0.8f; node[5].y= 0.0f; node[5].z=-0.1f;
-  node[6].x=1.0f; node[6].y=-0.3f; node[6].z= 0.0f;
-  node[7].x=0.8f; node[7].y=-0.2f; node[7].z= 0.0f;
-  node[8].x=0.8f; node[8].y=-0.3f; node[8].z= 0.0f;
-  node[9].x=1.0f; node[9].y=-0.2f; node[9].z= 0.0f;
-  node[10].x= 1.0f; node[10].y= 0.0f; node[10].z=-0.2f;
-  node[11].x= 0.8f; node[11].y= 0.0f; node[11].z=-0.3f;
-  node[12].x= 0.8f; node[12].y= 0.0f; node[12].z=-0.2f; 
-  node[13].x= 1.0f; node[13].y= 0.0f; node[13].z=-0.3f; 
-  node[14].x= 0.0f; node[14].y= 1.0f; node[14].z= 0.0f;
-  node[15].x= 0.1f; node[15].y= 0.8f; node[15].z= 0.0f;
-  node[16].x= 0.0f; node[16].y= 0.8f; node[16].z= 0.1f;
-  node[17].x=-0.1f; node[17].y= 0.8f; node[17].z= 0.0f;
-  node[18].x= 0.0f; node[18].y= 0.8f; node[18].z=-0.1f;
-  node[19].x=-0.25f;node[19].y= 0.8f; node[19].z= 0.0f;
-  node[20].x=-0.2f; node[20].y= 1.0f; node[20].z= 0.0f;
-  node[21].x=-0.3f; node[21].y= 1.0f; node[21].z= 0.0f;
-  node[22].x=-0.25f;node[22].y= 0.9f; node[22].z= 0.0f;
-  node[23].x= 0.0f; node[23].y= 1.0f; node[23].z= -0.2f;
-  node[24].x= 0.0f; node[24].y= 1.0f; node[24].z= -0.3f;
-  node[25].x= 0.0f; node[25].y= 0.8f; node[25].z= -0.25f;
-  node[26].x= 0.0f; node[26].y= 0.9f; node[26].z= -0.25f;
-  node[27].x= 0.0f; node[27].y= 0.0f; node[27].z= 1.0f;
-  node[28].x= 0.0f; node[28].y= -0.1f;node[28].z= 0.8f;
-  node[29].x= -0.1f;node[29].y= 0.0f; node[29].z= 0.8f; 
-  node[30].x= 0.0f; node[30].y= 0.1f; node[30].z= 0.8f;
-  node[31].x= 0.1f; node[31].y= 0.0f; node[31].z= 0.8f; 
-  node[32].x= 0.0f; node[32].y= -0.2f;node[32].z= 0.8f;
-  node[33].x= 0.0f; node[33].y= -0.3f;node[33].z= 0.8f;
-  node[34].x= 0.0f; node[34].y= -0.2f;node[34].z= 1.0f;
-  node[35].x= 0.0f; node[35].y= -0.3f;node[35].z= 1.0f;
-  node[36].x= -0.2f;node[36].y= 0.0f; node[36].z= 0.8f;
-  node[37].x= -0.3f;node[37].y= 0.0f; node[37].z= 0.8f;
-  node[38].x= -0.2f;node[38].y= 0.0f; node[38].z= 1.0f;
-  node[39].x= -0.3f;node[39].y= 0.0f; node[39].z= 1.0f;
-
-  edge[0].node1=0; edge[0].node2=1; edge[0].color=1;
-  edge[1].node1=1; edge[1].node2=2; edge[1].color=1;
-  edge[2].node1=1; edge[2].node2=3; edge[2].color=1;
-  edge[3].node1=1; edge[3].node2=4; edge[3].color=1;
-  edge[4].node1=1; edge[4].node2=5; edge[4].color=1;
-  edge[5].node1=6; edge[5].node2=7; edge[5].color=1;
-  edge[6].node1=8; edge[6].node2=9; edge[6].color=1;
-  edge[7].node1=10;edge[7].node2=11; edge[7].color=1;
-  edge[8].node1=12;edge[8].node2=13; edge[8].color=1;
-  edge[9].node1=0; edge[9].node2=14; edge[9].color=4;
-  edge[10].node1=14; edge[10].node2=15; edge[10].color=4;
-  edge[11].node1=14; edge[11].node2=16; edge[11].color=4;
-  edge[12].node1=14; edge[12].node2=17; edge[12].color=4; 
-  edge[13].node1=14; edge[13].node2=18; edge[13].color=4; 
-  edge[14].node1=19; edge[14].node2=22; edge[14].color=4; 
-  edge[15].node1=22; edge[15].node2=20; edge[15].color=4; 
-  edge[16].node1=22; edge[16].node2=21; edge[16].color=4; 
-  edge[17].node1=25; edge[17].node2=26; edge[17].color=4; 
-  edge[18].node1=26; edge[18].node2=23; edge[18].color=4; 
-  edge[19].node1=26; edge[19].node2=24; edge[19].color=4; 
-  edge[20].node1=0;  edge[20].node2=27; edge[20].color=5;
-  edge[21].node1=27; edge[21].node2=28; edge[21].color=5;
-  edge[22].node1=27; edge[22].node2=29; edge[22].color=5;
-  edge[23].node1=27; edge[23].node2=30; edge[23].color=5;
-  edge[24].node1=27; edge[24].node2=31; edge[24].color=5;
-  edge[25].node1=32; edge[25].node2=33; edge[25].color=5;
-  edge[26].node1=33; edge[26].node2=34; edge[26].color=5;
-  edge[27].node1=34; edge[27].node2=35; edge[27].color=5;
-  edge[28].node1=36; edge[28].node2=37; edge[28].color=5;
-  edge[29].node1=37; edge[29].node2=38; edge[29].color=5;
-  edge[30].node1=38; edge[30].node2=39; edge[30].color=5;
-  }
+{
+	int NbrNodes = 40;
+	int NbrEdges = 31;
+
+	xmin = -0.3;
+	xmax = 1.0;
+	ymin = -0.3;
+	ymax = 1.0;
+	zmin = -0.3;
+	zmax = 1.0;
+	node.resize(NbrNodes);
+	edge.resize(NbrEdges);
+
+	EdgePropMap::iterator p = edgepropmap.find("1");
+	if (p == edgepropmap.end()) {
+		ErreurMessage(_FATAL, "Missing edge property");
+	}
+	EdgeProp *p1 = p->second;
+
+	p = edgepropmap.find("4");
+	if (p == edgepropmap.end()) {
+		ErreurMessage(_FATAL, "Missing edge property");
+	}
+	EdgeProp *p4 = p->second;
+
+	p = edgepropmap.find("5");
+	if (p == edgepropmap.end()) {
+		ErreurMessage(_FATAL, "Missing edge property");
+	}
+	EdgeProp *p5 = p->second;
+
+	node[0].coords.x = 0.0f;
+	node[0].coords.y = 0.0f;
+	node[0].coords.z = 0.0f;
+	node[1].coords.x = 1.0f;
+	node[1].coords.y = 0.0f;
+	node[1].coords.z = 0.0f;
+	node[2].coords.x = 0.8f;
+	node[2].coords.y = 0.1f;
+	node[2].coords.z = 0.0f;
+	node[3].coords.x = 0.8f;
+	node[3].coords.y = 0.0f;
+	node[3].coords.z = 0.1f;
+	node[4].coords.x = 0.8f;
+	node[4].coords.y = -0.1f;
+	node[4].coords.z = 0.0f;
+	node[5].coords.x = 0.8f;
+	node[5].coords.y = 0.0f;
+	node[5].coords.z = -0.1f;
+	node[6].coords.x = 1.0f;
+	node[6].coords.y = -0.3f;
+	node[6].coords.z = 0.0f;
+	node[7].coords.x = 0.8f;
+	node[7].coords.y = -0.2f;
+	node[7].coords.z = 0.0f;
+	node[8].coords.x = 0.8f;
+	node[8].coords.y = -0.3f;
+	node[8].coords.z = 0.0f;
+	node[9].coords.x = 1.0f;
+	node[9].coords.y = -0.2f;
+	node[9].coords.z = 0.0f;
+	node[10].coords.x = 1.0f;
+	node[10].coords.y = 0.0f;
+	node[10].coords.z = -0.2f;
+	node[11].coords.x = 0.8f;
+	node[11].coords.y = 0.0f;
+	node[11].coords.z = -0.3f;
+	node[12].coords.x = 0.8f;
+	node[12].coords.y = 0.0f;
+	node[12].coords.z = -0.2f;
+	node[13].coords.x = 1.0f;
+	node[13].coords.y = 0.0f;
+	node[13].coords.z = -0.3f;
+	node[14].coords.x = 0.0f;
+	node[14].coords.y = 1.0f;
+	node[14].coords.z = 0.0f;
+	node[15].coords.x = 0.1f;
+	node[15].coords.y = 0.8f;
+	node[15].coords.z = 0.0f;
+	node[16].coords.x = 0.0f;
+	node[16].coords.y = 0.8f;
+	node[16].coords.z = 0.1f;
+	node[17].coords.x = -0.1f;
+	node[17].coords.y = 0.8f;
+	node[17].coords.z = 0.0f;
+	node[18].coords.x = 0.0f;
+	node[18].coords.y = 0.8f;
+	node[18].coords.z = -0.1f;
+	node[19].coords.x = -0.25f;
+	node[19].coords.y = 0.8f;
+	node[19].coords.z = 0.0f;
+	node[20].coords.x = -0.2f;
+	node[20].coords.y = 1.0f;
+	node[20].coords.z = 0.0f;
+	node[21].coords.x = -0.3f;
+	node[21].coords.y = 1.0f;
+	node[21].coords.z = 0.0f;
+	node[22].coords.x = -0.25f;
+	node[22].coords.y = 0.9f;
+	node[22].coords.z = 0.0f;
+	node[23].coords.x = 0.0f;
+	node[23].coords.y = 1.0f;
+	node[23].coords.z = -0.2f;
+	node[24].coords.x = 0.0f;
+	node[24].coords.y = 1.0f;
+	node[24].coords.z = -0.3f;
+	node[25].coords.x = 0.0f;
+	node[25].coords.y = 0.8f;
+	node[25].coords.z = -0.25f;
+	node[26].coords.x = 0.0f;
+	node[26].coords.y = 0.9f;
+	node[26].coords.z = -0.25f;
+	node[27].coords.x = 0.0f;
+	node[27].coords.y = 0.0f;
+	node[27].coords.z = 1.0f;
+	node[28].coords.x = 0.0f;
+	node[28].coords.y = -0.1f;
+	node[28].coords.z = 0.8f;
+	node[29].coords.x = -0.1f;
+	node[29].coords.y = 0.0f;
+	node[29].coords.z = 0.8f;
+	node[30].coords.x = 0.0f;
+	node[30].coords.y = 0.1f;
+	node[30].coords.z = 0.8f;
+	node[31].coords.x = 0.1f;
+	node[31].coords.y = 0.0f;
+	node[31].coords.z = 0.8f;
+	node[32].coords.x = 0.0f;
+	node[32].coords.y = -0.2f;
+	node[32].coords.z = 0.8f;
+	node[33].coords.x = 0.0f;
+	node[33].coords.y = -0.3f;
+	node[33].coords.z = 0.8f;
+	node[34].coords.x = 0.0f;
+	node[34].coords.y = -0.2f;
+	node[34].coords.z = 1.0f;
+	node[35].coords.x = 0.0f;
+	node[35].coords.y = -0.3f;
+	node[35].coords.z = 1.0f;
+	node[36].coords.x = -0.2f;
+	node[36].coords.y = 0.0f;
+	node[36].coords.z = 0.8f;
+	node[37].coords.x = -0.3f;
+	node[37].coords.y = 0.0f;
+	node[37].coords.z = 0.8f;
+	node[38].coords.x = -0.2f;
+	node[38].coords.y = 0.0f;
+	node[38].coords.z = 1.0f;
+	node[39].coords.x = -0.3f;
+	node[39].coords.y = 0.0f;
+	node[39].coords.z = 1.0f;
+
+	edge[0].node1 = 0;
+	edge[0].node2 = 1;
+	edge[0].prop = p1;
+	edge[1].node1 = 1;
+	edge[1].node2 = 2;
+	edge[1].prop = p1;
+	edge[2].node1 = 1;
+	edge[2].node2 = 3;
+	edge[2].prop = p1;
+	edge[3].node1 = 1;
+	edge[3].node2 = 4;
+	edge[3].prop = p1;
+	edge[4].node1 = 1;
+	edge[4].node2 = 5;
+	edge[4].prop = p1;
+	edge[5].node1 = 6;
+	edge[5].node2 = 7;
+	edge[5].prop = p1;
+	edge[6].node1 = 8;
+	edge[6].node2 = 9;
+	edge[6].prop = p1;
+	edge[7].node1 = 10;
+	edge[7].node2 = 11;
+	edge[7].prop = p1;
+	edge[8].node1 = 12;
+	edge[8].node2 = 13;
+	edge[8].prop = p1;
+	edge[9].node1 = 0;
+	edge[9].node2 = 14;
+	edge[9].prop = p4;
+	edge[10].node1 = 14;
+	edge[10].node2 = 15;
+	edge[10].prop = p4;
+	edge[11].node1 = 14;
+	edge[11].node2 = 16;
+	edge[11].prop = p4;
+	edge[12].node1 = 14;
+	edge[12].node2 = 17;
+	edge[12].prop = p4;
+	edge[13].node1 = 14;
+	edge[13].node2 = 18;
+	edge[13].prop = p4;
+	edge[14].node1 = 19;
+	edge[14].node2 = 22;
+	edge[14].prop = p4;
+	edge[15].node1 = 22;
+	edge[15].node2 = 20;
+	edge[15].prop = p4;
+	edge[16].node1 = 22;
+	edge[16].node2 = 21;
+	edge[16].prop = p4;
+	edge[17].node1 = 25;
+	edge[17].node2 = 26;
+	edge[17].prop = p4;
+	edge[18].node1 = 26;
+	edge[18].node2 = 23;
+	edge[18].prop = p4;
+	edge[19].node1 = 26;
+	edge[19].node2 = 24;
+	edge[19].prop = p4;
+	edge[20].node1 = 0;
+	edge[20].node2 = 27;
+	edge[20].prop = p5;
+	edge[21].node1 = 27;
+	edge[21].node2 = 28;
+	edge[21].prop = p5;
+	edge[22].node1 = 27;
+	edge[22].node2 = 29;
+	edge[22].prop = p5;
+	edge[23].node1 = 27;
+	edge[23].node2 = 30;
+	edge[23].prop = p5;
+	edge[24].node1 = 27;
+	edge[24].node2 = 31;
+	edge[24].prop = p5;
+	edge[25].node1 = 32;
+	edge[25].node2 = 33;
+	edge[25].prop = p5;
+	edge[26].node1 = 33;
+	edge[26].node2 = 34;
+	edge[26].prop = p5;
+	edge[27].node1 = 34;
+	edge[27].node2 = 35;
+	edge[27].prop = p5;
+	edge[28].node1 = 36;
+	edge[28].node2 = 37;
+	edge[28].prop = p5;
+	edge[29].node1 = 37;
+	edge[29].node2 = 38;
+	edge[29].prop = p5;
+	edge[30].node1 = 38;
+	edge[30].node2 = 39;
+	edge[30].prop = p5;
+}
 
 /*---------------------------------------------------------------------*/
 
 // routine de dessin
-void def_repere::Trace()
-  {
-  //creation de la liste GL
-  int i,j,k;
-  GLfloat  mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f};
-  GLfloat  mat_diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f};
-  GLfloat  mat_gray[] = { 0.2f, 0.2f, 0.2f, 1.0f};
-  GLfloat  mat_black[] = { 0.0f, 0.0f, 0.0f, 0.0f};
-
-  if (!hidden)
-    {
-    glBegin(GL_LINES);
-    for (i=0;i<NbrEdges;i++) 
-      {
-      mat_ambient[0]=COULEUR[edge[i].color][0];
-      mat_ambient[1]=COULEUR[edge[i].color][1];
-      mat_ambient[2]=COULEUR[edge[i].color][2];
-      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
-      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_black);
-      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_black);
-      glVertex3f(node[edge[i].node1].x,node[edge[i].node1].y,
-                 node[edge[i].node1].z);/*origine*/
-      glVertex3f(node[edge[i].node2].x,node[edge[i].node2].y,
-                 node[edge[i].node2].z);/*extremite*/
-      }
-    glEnd();
-
-    glFlush();
-    }
-  }
+void
+def_repere::Trace()
+{
+	// creation de la liste GL
+	GLfloat  mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f};
+	GLfloat  mat_black[] = { 0.0f, 0.0f, 0.0f, 0.0f};
+
+	if (!hidden) {
+		glBegin(GL_LINES);
+		for (unsigned i = 0; i < edge.size(); i++) {
+			mat_ambient[0] = COULEUR[edge[i].prop->color][0];
+			mat_ambient[1] = COULEUR[edge[i].prop->color][1];
+			mat_ambient[2] = COULEUR[edge[i].prop->color][2];
+			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
+				mat_ambient);
+			glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
+				mat_black);
+			glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
+				mat_black);
+			// origine
+			glVertex3f(node[edge[i].node1].coords.x,
+				node[edge[i].node1].coords.y,
+				node[edge[i].node1].coords.z);
+			// extremite
+			glVertex3f(node[edge[i].node2].coords.x,
+				node[edge[i].node2].coords.y,
+				node[edge[i].node2].coords.z);
+		}
+		glEnd();
+		glFlush();
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
 // routine de dessin
-void def_repere::LoadImage(int NumImage)
-  {
-  }
+void
+def_repere::LoadImage(int /* NumImage */)
+{
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage du repère
+void
+repere(void)
+{
+	if (s1->Hidden()) {
+		s1->Show();
+	} else {
+		s1->Hide();
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
 // routine pour l'affichage ou le masquage du repère
-void repere() 
-  {
-  if (s1->Hidden()) s1->Show();
-  else s1->Hide();
-  }
+void
+repere(bool show)
+{
+	if (show && s1->Hidden()) {
+		s1->Show();
+	} else if (!show && !s1->Hidden()) {
+		s1->Hide();
+	}
+}
+
+/*---------------------------------------------------------------------*/
+
+// routine pour l'affichage ou le masquage du repère
+bool
+is_repere(void)
+{
+	return !s1->Hidden();
+}
+
+// routine pour l'affichage ou le masquage du repère
+GLdouble
+get_repere_size(void)
+{
+	return repereSize;
+}
+
+void
+set_repere_size(GLdouble size)
+{
+	if (size > 0.) {
+		repereSize = size;
+		s1->Homothetie(repereSize);
+	}
+}
 
 /*---------------------------------------------------------------------*/
 
 // routines de dimensionnement du repère
-void repere_plus()
-  {	
-  s1->Homothetie(1.25f);	
-  }
+void
+repere_plus()
+{
+	repereSize *= 1.25f;
+	s1->Homothetie(1.25f);
+}
 
 /*---------------------------------------------------------------------*/
 
-void repere_moins() 
-  {
-  s1->Homothetie(0.8f);
-  }
+void
+repere_moins()
+{
+	repereSize *= 0.8f;
+	s1->Homothetie(0.8f);
+}
 
 /*---------------------------------------------------------------------*/
-					       
+
 //===================>>> myOGLCanvasPane::myOGLCanvasPane <<<====================
 // constructeur du canvas
-  myOGLCanvasPane::myOGLCanvasPane(unsigned int vGLmode, PaneType pt)
-    : vBaseGLCanvasPane(vGLmode,pt)
-  {
-    initDone = 0;
-  }
+myOGLCanvasPane::myOGLCanvasPane(unsigned int vGLmode, PaneType pt)
+: vBaseGLCanvasPane(vGLmode,pt)
+{
+	initDone = 0;
+}
 
 //===================>>> myOGLCanvasPane::~myOGLCanvasPane <<<====================
 // destructeur du canvas
-  myOGLCanvasPane::~myOGLCanvasPane()
-  {
-  }
+myOGLCanvasPane::~myOGLCanvasPane(void)
+{
+}
 
 //======================>>> myOGLCanvasPane::TimerAnimate <<<========================
 // instruction exécutées par le timer
-  void myOGLCanvasPane::TimerAnimate(void)
-  {
-  // **** Called by CmdWindow AuxTimer for animation.
-  vglMakeCurrent();  // Typically done here
-  anime();
-  vglFlush();  // After you draw, typically flush
-  }
+void
+myOGLCanvasPane::TimerAnimate(void)
+{
+	// **** Called by CmdWindow AuxTimer for animation.
+	vglMakeCurrent();  // Typically done here
+	anime();
+	vglFlush();  // After you draw, typically flush
+}
 
 //======================>>> myOGLCanvasPane::graphicsInit <<<========================
 // Initialmisation des graphiques OpenGL
 // Exécuté une fois lorsque le canvas est affiché
-  void myOGLCanvasPane::graphicsInit(void)
-  {
-    vBaseGLCanvasPane::graphicsInit();	// Always call the superclass first!
+void
+myOGLCanvasPane::graphicsInit(void)
+{
+	// Always call the superclass first!
+	vBaseGLCanvasPane::graphicsInit();
 
 	vglMakeCurrent();  // Typically done here
 	GLSetupRC();
-        s1=new def_repere;
-        s2=NULL;
+        s1 = new def_repere;
+        s2 = 0;
         Add_Scene(s1);
 	GLResize(GetWidth(),GetHeight());
 	GLRenderScene();
 	vglFlush();  // After you draw, typically flush
 	initDone = 1;
-  }
+}
 
 //======================>>> myOGLCanvasPane::MouseDown <<<======================
-  void myOGLCanvasPane::MouseDown(int X, int Y, int button)
-  {
-    vBaseGLCanvasPane::MouseDown(X,Y,button);
-  }
+void
+myOGLCanvasPane::MouseDown(int X, int Y, int button)
+{
+	vBaseGLCanvasPane::MouseDown(X,Y,button);
+}
 
 //========================>>> myOGLCanvasPane::MouseUp <<<======================
-  void myOGLCanvasPane::MouseUp(int X, int Y, int button)
-  {
-    vBaseGLCanvasPane::MouseUp(X,Y,button);
-  }
+void myOGLCanvasPane::MouseUp(int X, int Y, int button)
+{
+	vBaseGLCanvasPane::MouseUp(X,Y,button);
+}
 
 //======================>>> myOGLCanvasPane::MouseMove <<<======================
-  void myOGLCanvasPane::MouseMove(int x, int y, int button)
-  {
-    vBaseGLCanvasPane::MouseMove(x,y,button);
-  }
+void
+myOGLCanvasPane::MouseMove(int x, int y, int button)
+{
+	vBaseGLCanvasPane::MouseMove(x,y,button);
+}
 
 //=========================>>> myOGLCanvasPane::Redraw <<<======================
 // Routiine exécutée lorsque le canvas doir être redessiné
-  void myOGLCanvasPane::Redraw(int x, int y, int w, int h)
-  {
-    static int inRedraw = 0;
-
-    if (inRedraw || !initDone)  // Don't draw until initialized
-        return;
-
-    inRedraw = 1;  // Don't allow recursive redraws.
-    vglMakeCurrent();  // Typically done here
-    GLRenderScene();
-    inRedraw = 0;  // Out of Redraw
+void
+myOGLCanvasPane::Redraw(int /* x */, int /* y */, int /* w */, int /* h */)
+{
+	static int inRedraw = 0;
+
+	 // Don't draw until initialized
+	if (inRedraw || !initDone) {
+        	return;
+	}
 
-  }
+	inRedraw = 1;		// Don't allow recursive redraws.
+	vglMakeCurrent();	// Typically done here
+	GLRenderScene();
+	inRedraw = 0;		// Out of Redraw
+}
 
 
 //======================>>> myOGLCanvasPane::Resize <<<======================
 // routine exécutée lorsque le canvas est redimensionné
-  void myOGLCanvasPane::Resize(int w, int h)
-  {
-    vBaseGLCanvasPane::Resize(w,h);
+void
+myOGLCanvasPane::Resize(int w, int h)
+{
+	vBaseGLCanvasPane::Resize(w, h);
 	GLResize(w,h);
 	GLRenderScene();
-//	}
-  }
+}
 
Index: src/EasyAnimcnv.h
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimcnv.h,v
retrieving revision 1.1.1.1
retrieving revision 1.16
diff -u -r1.1.1.1 -r1.16
--- src/EasyAnimcnv.h	27 Jan 2006 19:53:27 -0000	1.1.1.1
+++ src/EasyAnimcnv.h	28 Nov 2006 00:35:06 -0000	1.16
@@ -24,97 +24,140 @@
 
 */
 
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
 #ifndef myCNV_H
 #define myCNV_H
 
 #include <fstream>
+#include <string>
+#include <vector>
 #include <v/vbglcnv.h>
 #include "EasyAnimGL.h"
-
-using namespace std;
+#include "usesock.h"
 
 class myOGLCanvasPane : public vBaseGLCanvasPane
-  {
-  public:		//---------------------------------------- public
-    //  myOGLCanvasPane(unsigned int vGLmode = (vGL_RGB|vGL_DoubleBuffer|vGL_Depth),
-  myOGLCanvasPane(unsigned int vGLmode = (vGL_RGB|vGL_DoubleBuffer|vGL_Depth),
-                  PaneType pt = P_Canvas);
-  virtual ~myOGLCanvasPane();
-
-  virtual void graphicsInit(void);
-  void TimerAnimate(void);	// for AuxTimer animation
-	
-  // Events
-  virtual void MouseDown(int x, int y, int button);
-  virtual void MouseUp(int x, int y, int button);
-  virtual void MouseMove(int x, int y, int button);
-
-  virtual void Redraw(int x, int y, int width, int height);
-  virtual void Resize(int newW, int newH);
-
-  protected:	//--------------------------------------- protected
-
-  private:		//--------------------------------------- private
-  int initDone;
-  };
-
-class def_volvan: public def_scene
-  {
-  ifstream fpos;
-  char FileName[200];
-  public :
-  def_volvan(const char *nom_fichier_vol, int &errcode);
-  ~def_volvan();
-  void Next();
-  void LoadImage(int NumImage);
-  };
-
-class def_volvmo: public def_scene
-  {
-  char FileName[200];
-  VecStruct *PosRef,*DepReal,*DepImag;
-  double DepMax;
-  public :
-  float alpha, beta, freq, amor;
-  def_volvmo(const char *VolFileName, int &errcode);
-  ~def_volvmo();
-  void Next();
-  int LoadMode(int num);
-  void LoadImage(int NumImage);
-  };
-
-class def_uff: public def_scene
-  {
-  char FileName[200];
-  VecStruct *PosRef,*DepReal,*DepImag;
-  double DepMax;
-  public :
-  float alpha, beta, freq, amor;
-  def_uff(const char *UffFileName1,const char *UffFileName2,
-	     int &errcode);
-  ~def_uff();
-  void Next();
-  int LoadMode(int num);
-  void LoadImage(int NumImage);
-  };
-
-class def_repere: public def_scene
-  {
-  public :
-  void Trace();
-  def_repere();
-  void LoadImage(int NumImage);
-  };
+{
+public:		//---------------------------------------- public
+	myOGLCanvasPane(unsigned int vGLmode
+			= (vGL_RGB|vGL_DoubleBuffer|vGL_Depth),
+		PaneType pt = P_Canvas);
+	virtual ~myOGLCanvasPane(void);
+
+	virtual void graphicsInit(void);
+	void TimerAnimate(void);	// for AuxTimer animation
+
+	// Events
+	virtual void MouseDown(int x, int y, int button);
+	virtual void MouseUp(int x, int y, int button);
+	virtual void MouseMove(int x, int y, int button);
+
+	virtual void Redraw(int x, int y, int width, int height);
+	virtual void Resize(int newW, int newH);
+
+protected:	//--------------------------------------- protected
+
+private:	//--------------------------------------- private
+	int initDone;
+};
+
+class def_volvan : public def_scene
+{
+	std::ifstream fpos;
+	std::string FileName;
+	VecStruct **vandata;
+public:
+	def_volvan(std::string &FileName, def_err &err);
+	~def_volvan(void);
+	void Next(bool next = true);
+	void LoadImage(int NumImage);
+	void LoadVan(def_err &err);
+};
+
+class def_volvmo : public def_scene
+{
+	std::string FileName;
+	std::vector<VecStruct> PosRef, DepReal, DepImag;
+	double DepMax;
+public:
+	float alpha, beta, freq, amor;
+	def_volvmo(std::string &VolFileName, def_err &err);
+	~def_volvmo(void);
+	void Next(bool next = true);
+	int LoadMode(int num);
+	void LoadImage(int NumImage);
+};
+
+class def_uff : public def_scene
+{
+	std::string FileName;
+	std::vector<VecStruct> PosRef, DepReal, DepImag;
+	double DepMax;
+public:
+	float alpha, beta, freq, amor;
+	def_uff(std::string &UffFileName1, std::string &UffFileName2,
+		def_err &err);
+	~def_uff(void);
+	void Next(bool next = true);
+	int LoadMode(int num);
+	void LoadImage(int NumImage);
+};
+
+class def_volstream : public def_scene
+{
+	std::string FileName;
+	UseSocket *sock;
+	// NOTE: endianness may be an issue
+	double *vandata;
+	size_t size;
+	int recv_flags;
+
+public:
+	def_volstream(std::string& VolFileName, UseSocket *sock, def_err &err);
+	~def_volstream();
+	void Next(bool next = true);
+	void LoadImage(int NumImage);
+	int SetSocket(std::string& host, int port);
+	int SetSocket(std::string& path);
+};
+
+class def_repere : public def_scene
+{
+public :
+	void Trace(void);
+	def_repere(void);
+	void LoadImage(int NumImage);
+};
 
 extern def_repere* s1;
 extern def_volvan* s2;
 extern def_volvmo* s3;
 extern def_uff* s4;
+extern def_volstream* s5;
 
-void repere();
-void repere_plus();
-void repere_moins();
-
-#endif
+void repere(void);
+void repere(bool);
+void repere_plus(void);
+void repere_moins(void);
+bool is_repere(void);
+void set_repere_size(GLdouble);
+GLdouble get_repere_size(void);
+
+// in EasyAnimcmdw.h
+void set_string(std::string &s);
+int set_stream(std::string& stream);
+const std::string& get_stream(void);
 
+#endif // myCNV_H
 
Index: src/EasyAnimmdlg.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimmdlg.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- src/EasyAnimmdlg.cpp	27 Jan 2006 19:53:27 -0000	1.1.1.1
+++ src/EasyAnimmdlg.cpp	16 Nov 2006 22:07:21 -0000	1.4
@@ -24,88 +24,109 @@
 
 */
 
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
 #include "EasyAnimmdlg.h"
 #include "EasyAnimcmdw.h"
 #include <v/vnotice.h>
 
 int retval;
+
 //@V@:BeginIDs
-    enum {
+enum {
 	cbxid = 0,
-    lblMainMsg = 1000,
-    // add your id's here
-  };
+	lblMainMsg = 1000,
+	// add your id's here
+	lblLast
+};
 //@V@:EndIds
 
 // Valeurs de la combo liste
-char* comboList[] = 
-	{
-		"Black",
-		"Blue",
-		"Green",
-		"Cyan",
-		"Red",
-		"Magenta",
-		"Brown",
-		"Light Gray",
-		"Dark Gray",
-		"Light Blue",
-		"Light Green",
-		"Light Cyan",
-		"Light Red",
-		"Light Magenta",
-		"Yellow",
-		"White",
-		0
-	};
+char* comboList[] = {
+	"Black",
+	"Blue",
+	"Green",
+	"Cyan",
+	"Red",
+	"Magenta",
+	"Brown",
+	"Light Gray",
+	"Dark Gray",
+	"Light Blue",
+	"Light Green",
+	"Light Cyan",
+	"Light Red",
+	"Light Magenta",
+	"Yellow",
+	"White",
+	0
+};
 
 //@V@:BeginDialogCmd DefaultCmds
-    static DialogCmd DefaultCmds[] =
-      {
-	{C_Label, lblMainMsg, 0,"Change background color",NoList,CA_None,isSens,NoFrame, 0, 0},
-	{C_Spinner, cbxid, cbxid,"",(void*)comboList,CA_Text,isSens,NoFrame,lblMainMsg,0,100},
-	{C_Button, M_Cancel, 0, " Cancel ",NoList,CA_None,isSens,NoFrame,0, lblMainMsg},
-	{C_Button, M_OK, 0, " OK ",NoList,CA_DefaultButton,isSens,NoFrame,M_Cancel,lblMainMsg},
-	{C_EndOfList,0,0,0,0,CA_None,0,0,0}
-    };
+static DialogCmd DefaultCmds[] = {
+	{C_Label, lblMainMsg, 0, "Change background color", NoList,
+		CA_None, isSens, NoFrame, 0, 0},
+	{C_Spinner, cbxid, cbxid, "", (void*)comboList,
+		CA_Text, isSens, NoFrame, lblMainMsg, 0, 100},
+	{C_Button, M_Cancel, 0, " Cancel ", NoList,
+		CA_None, isSens, NoFrame, 0, lblMainMsg},
+	{C_Button, M_OK, 0, " OK ", NoList,
+		CA_DefaultButton, isSens, NoFrame, M_Cancel, lblMainMsg},
+	{C_EndOfList, 0, 0, 0, 0,
+		CA_None, 0, 0, 0}
+};
 //@V@:EndDialogCmd
 
 
 //======================>>> myModalDialog::myModalDialog <<<==================
-  myModalDialog::myModalDialog(vBaseWindow* bw, char* title) :
-    vModalDialog(bw, title)
-  {
-    UserDebug(Constructor,"myModalDialog::myModalDialog()\n")
-    _myCmdWin = (myCmdWindow*) bw;
-    AddDialogCmds(DefaultCmds);		// add the predefined commands
-  }
+myModalDialog::myModalDialog(vBaseWindow* bw, char* title)
+: vModalDialog(bw, title)
+{
+	UserDebug(Constructor, "myModalDialog::myModalDialog()\n");
+	_myCmdWin = (myCmdWindow*)bw;
+	AddDialogCmds(DefaultCmds);		// add the predefined commands
+}
 
 //===================>>> myModalDialog::~myModalDialog <<<====================
-  myModalDialog::~myModalDialog()
-  {
-    UserDebug(Destructor,"myModalDialog::~myModalDialog() destructor\n")
-  }
+myModalDialog::~myModalDialog(void)
+{
+	UserDebug(Destructor, "myModalDialog::~myModalDialog() destructor\n");
+}
 
 //====================>>> myModalDialog::myAction <<<====================
-  int myModalDialog::myAction(char* msg)
-  {
-    ItemVal ans,rval;
-	ans = ShowModalDialog(msg,rval);
+int
+myModalDialog::myAction(char* msg)
+{
+	ItemVal ans,rval;
+	ans = ShowModalDialog(msg, rval);
 	retval = GetValue(cbxid);
-    if (ans == M_Cancel)
-	return 0;
-
+	if (ans == M_Cancel) {
+		return 0;
+	}
 
 	// *** Add code to process dialog values here
 
-    return ans == M_OK;
-  }
+	return (ans == M_OK);
+}
 
 //====================>>> myModalDialog::DialogCommand <<<====================
-  void myModalDialog::DialogCommand(ItemVal id, ItemVal retval, CmdType ctype)
-  {
-    UserDebug2(CmdEvents,"myModalDialog::DialogCommand(id:%d, val:%d)\n",id, retval)
+void
+myModalDialog::DialogCommand(ItemVal id, ItemVal retval, CmdType ctype)
+{
+	UserDebug2(CmdEvents, "myModalDialog::DialogCommand(id:%d, val:%d)\n",
+		id, retval)
 
-      vModalDialog::DialogCommand(id,retval,ctype);
-  }
+	vModalDialog::DialogCommand(id, retval, ctype);
+}
 
Index: src/EasyAnimmdlg.h
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/EasyAnimmdlg.h,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- src/EasyAnimmdlg.h	27 Jan 2006 19:53:25 -0000	1.1.1.1
+++ src/EasyAnimmdlg.h	16 Nov 2006 22:07:21 -0000	1.4
@@ -1,49 +1,62 @@
-/*
-
-Copyright (C) 2003 Olivier VERLINDEN
-    Service de Mecanique rationnelle, Dynamique et Vibrations
-    Faculte Polytechnique de Mons
-    31, Bd Dolez, 7000 MONS (Belgium)
-    Olivier.Verlinden@fpms.ac.be
-
-This file is part of EasyAnim
-
-EasyAnim is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-EasyAnim is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with EasyAnim; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-
-#ifndef EasyAnimMDLG_H
-#define EasyAnimMDLG_H
-
-#include <v/vmodald.h>
-
-    class myCmdWindow;
-
-    class myModalDialog : public vModalDialog
-      {
-      public:		//---------------------------------------- public
-	myModalDialog(vBaseWindow* bw, char* title = "Change Color");
-	virtual ~myModalDialog();		// Destructor
-	virtual void DialogCommand(ItemVal,ItemVal,CmdType); // action selected
-	virtual int myAction(char* msg);
-
-      protected:	//--------------------------------------- protected
-
-      private:		//--------------------------------------- private
-
-	myCmdWindow* _myCmdWin;
-      };
-#endif
-
+/*
+
+Copyright (C) 2003 Olivier VERLINDEN
+    Service de Mecanique rationnelle, Dynamique et Vibrations
+    Faculte Polytechnique de Mons
+    31, Bd Dolez, 7000 MONS (Belgium)
+    Olivier.Verlinden@fpms.ac.be
+
+This file is part of EasyAnim
+
+EasyAnim is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+EasyAnim is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with EasyAnim; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+
+/*
+ * Portions Copyright (C) 2006 Pierangelo MASARATI
+ * 	Dipartimento di Ingegneria Aerospaziale
+ * 	Politecnico di Milano
+ * 	via La Masa 34, 20156 MILANO (Italy)
+ * 	masarati@aero.polimi.it
+ * 
+ * EasyAnim has been modified by Pierangelo Masarati for better 
+ * interoperability with MBDyn <http://www.aero.polimi.it/~mbdyn/>.
+ * The same version of the GNU General Public License of the original 
+ * software applies.
+*/
+
+#ifndef EasyAnimmdlg_h
+#define EasyAnimmdlg_h
+
+#include <v/vmodald.h>
+
+class myCmdWindow;
+
+class myModalDialog : public vModalDialog {
+public:		//---------------------------------------- public
+	myModalDialog(vBaseWindow* bw, char* title = "Change Color");
+	virtual ~myModalDialog();
+	// action selected
+	virtual void DialogCommand(ItemVal, ItemVal, CmdType);
+	virtual int myAction(char* msg);
+
+protected:	//--------------------------------------- protected
+
+private:	//--------------------------------------- private
+
+	myCmdWindow* _myCmdWin;
+};
+
+#endif // EasyAnimmdlg_h
Index: src/decode.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/decode.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/decode.cpp	27 Jan 2006 19:53:25 -0000	1.1.1.1
+++ src/decode.cpp	25 Oct 2006 02:25:26 -0000	1.2
@@ -1,78 +1,78 @@
-#include<stdlib.h>
-#include<iostream>
-#include<fstream>
-
-using namespace std;
-
-/***************************************************************************/
-
-int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
-
-/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
-   ou plusieurs espaces et tabulations */
-
-  {
-  char c;
-  int lncrtword=0; // longueur du mot courant;
-  nbrmotslus=0; // nombre de mots
-  do
-    {
-    // Reading spaces
-    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
-    // Reading word
-    nbrmotslus++; lncrtword=0;
-    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
-           (stream.peek()!='\n') && (stream.peek()!='\r') &&
-           (stream.peek()!='\f') && (stream.peek()!=EOF))
-      {
-      Mot[nbrmotslus-1][lncrtword]=stream.get();
-      lncrtword++;
-      }
-    if (lncrtword==0) nbrmotslus--;
-    else Mot[nbrmotslus-1][lncrtword]='\0';
-    }
-  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
-         &&(stream.peek()!='\r') && !stream.rdstate()); 
-
-  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
-         && (stream.peek()=='\r')) c=stream.get(); 
-  if (stream.peek()==EOF) c=stream.get();
-  } // fin de GetWords
-
-/***************************************************************************/
-
-main(int argc, char *argv[])
-
-{
-
-if (argc!=2)
-  {
-  cout << "Usage: decode file" << endl;
-  cout << "Affiche les caracteres hexadecimaux" << endl;
-  exit(1);
-  }
-
-ifstream infile(argv[1]);
-if (!infile)
-  {
-  cout << "Cannot open file " << argv[1] << endl;
-  exit(1);
-  }
-
-
-int i;
-unsigned char c; unsigned int code;
-while (!infile.eof())
-  {
-  c=infile.get(); code=c;
-  if (!infile.eof())
-    {
-    cout << " " << code;
-    }
-  }
-
-infile.close();
-
-return 0;
-
-}
+#include<stdlib.h>
+#include<iostream>
+#include<fstream>
+
+using namespace std;
+
+/***************************************************************************/
+
+int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
+
+/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
+   ou plusieurs espaces et tabulations */
+
+  {
+  char c;
+  int lncrtword=0; // longueur du mot courant;
+  nbrmotslus=0; // nombre de mots
+  do
+    {
+    // Reading spaces
+    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
+    // Reading word
+    nbrmotslus++; lncrtword=0;
+    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
+           (stream.peek()!='\n') && (stream.peek()!='\r') &&
+           (stream.peek()!='\f') && (stream.peek()!=EOF))
+      {
+      Mot[nbrmotslus-1][lncrtword]=stream.get();
+      lncrtword++;
+      }
+    if (lncrtword==0) nbrmotslus--;
+    else Mot[nbrmotslus-1][lncrtword]='\0';
+    }
+  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
+         &&(stream.peek()!='\r') && !stream.rdstate()); 
+
+  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
+         && (stream.peek()=='\r')) c=stream.get(); 
+  if (stream.peek()==EOF) c=stream.get();
+  } // fin de GetWords
+
+/***************************************************************************/
+
+main(int argc, char *argv[])
+
+{
+
+if (argc!=2)
+  {
+  cout << "Usage: decode file" << endl;
+  cout << "Affiche les caracteres hexadecimaux" << endl;
+  exit(1);
+  }
+
+ifstream infile(argv[1]);
+if (!infile)
+  {
+  cout << "Cannot open file " << argv[1] << endl;
+  exit(1);
+  }
+
+
+int i;
+unsigned char c; unsigned int code;
+while (!infile.eof())
+  {
+  c=infile.get(); code=c;
+  if (!infile.eof())
+    {
+    cout << " " << code;
+    }
+  }
+
+infile.close();
+
+return 0;
+
+}
Index: src/makefile.x
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/makefile.x,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -r1.1.1.1 -r1.3
--- src/makefile.x	27 Jan 2006 19:53:21 -0000	1.1.1.1
+++ src/makefile.x	26 Oct 2006 19:41:57 -0000	1.3
@@ -29,11 +29,13 @@
                 $(oDir)/EasyAnimcnv.o \
                 $(oDir)/EasyAnimcmdw.o \
                 $(oDir)/EasyAnimmdlg.o \
-                $(oDir)/EasyAnimGL.o
+                $(oDir)/EasyAnimGL.o \
+                $(oDir)/usesock.o
 
 # Let's go to program building
 
-all:    $(Bin)/EasyAnimx $(Bin)/EasyAnimm
+#all:    $(Bin)/EasyAnimx $(Bin)/EasyAnimm
+all:    $(Bin)/EasyAnimm
 
 objs:	$(EXOBJS)
 
@@ -43,17 +45,23 @@
 $(Bin)/EasyAnimx:        $(EXOBJS)
 	$(CC) -o $@ $(LFLAGS) $(EXOBJS) $(LIBSX)
 
-$(oDir)/EasyAnim.o:      EasyAnim.cpp  EasyAnim.h EasyAnimcnv.h EasyAnimcmdw.h EasyAnimmdlg.h
+$(oDir)/EasyAnim.o:      EasyAnim.cpp  EasyAnim.h EasyAnimcnv.h EasyAnimcmdw.h EasyAnimmdlg.h usesock.h
 	$(CC) -c $(CFLAGS) -o $@ $<
 
-$(oDir)/EasyAnimcnv.o:   EasyAnimcnv.cpp  EasyAnimcnv.h EasyAnimGL.h 
+$(oDir)/EasyAnimcnv.o:   EasyAnimcnv.cpp  EasyAnimcnv.h EasyAnimGL.h usesock.h
 	$(CC) -c $(CFLAGS) -o $@ $<
 
-$(oDir)/EasyAnimcmdw.o:      EasyAnimcmdw.cpp EasyAnimcmdw.h EasyAnimcnv.h EasyAnimmdlg.h EasyAnimGL.h 
+$(oDir)/EasyAnimcmdw.o:      EasyAnimcmdw.cpp EasyAnimcmdw.h EasyAnimcnv.h EasyAnimmdlg.h EasyAnimGL.h usesock.h
 	$(CC) -c $(CFLAGS) -o $@ $<
 
-$(oDir)/EasyAnimGL.o:      EasyAnimGL.cpp EasyAnimGL.h EasyAnimcnv.h
+$(oDir)/EasyAnimGL.o:      EasyAnimGL.cpp EasyAnimGL.h EasyAnimcnv.h usesock.h
 	$(CC) -c $(CFLAGS) -o $@ $<
 
-$(oDir)/EasyAnimmdlg.o:      EasyAnimmdlg.cpp EasyAnimmdlg.h EasyAnimcmdw.h EasyAnimcnv.h
+$(oDir)/EasyAnimmdlg.o:      EasyAnimmdlg.cpp EasyAnimmdlg.h EasyAnimcmdw.h EasyAnimcnv.h usesock.h
 	$(CC) -c $(CFLAGS) -o $@ $<
+
+$(oDir)/usesock.o:      usesock.cpp usesock.h
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+clean:
+	rm -f *.o EasyAnimm EasyAnimx
Index: src/scanuff.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/scanuff.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/scanuff.cpp	27 Jan 2006 19:53:27 -0000	1.1.1.1
+++ src/scanuff.cpp	25 Oct 2006 02:25:26 -0000	1.2
@@ -1,112 +1,112 @@
-#include<stdlib.h>
-#include<iostream>
-#include<fstream>
-
-using namespace std;
-
-/***************************************************************************/
-
-int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
-
-/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
-   ou plusieurs espaces et tabulations */
-
-  {
-  char c;
-  int lncrtword=0; // longueur du mot courant;
-  nbrmotslus=0; // nombre de mots
-  if (stream.rdstate()) return 1;
-  do
-    {
-    // Reading spaces
-    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
-    // Reading word
-    nbrmotslus++; lncrtword=0;
-    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
-           (stream.peek()!='\n') && (stream.peek()!='\r') &&
-           (stream.peek()!='\f') && (stream.peek()!=EOF))
-      {
-      Mot[nbrmotslus-1][lncrtword]=stream.get();
-      lncrtword++;
-      }
-    if (lncrtword==0) nbrmotslus--;
-    else Mot[nbrmotslus-1][lncrtword]='\0';
-    }
-  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
-         &&(stream.peek()!='\r') && !stream.rdstate()); 
-  // Reading end of line characters
-  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
-         || (stream.peek()=='\r')) c=stream.get(); 
-  // Looking for end of file before returning
-  if (stream.peek()==EOF) c=stream.get(); 
-  return 0;
-  } // fin de GetWords
-
-/***************************************************************************/
-
-int FindNextMinusOne(istream &stream, char **Mot)
-{
-int NbrWords;
-do
-  {
-  if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-  }
-  while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
-return 0;
-}
-
-/***************************************************************************/
-
-int FindNextUff(istream &stream, int type, char **Mot)
-{
-int NbrWords;
- do
-   {
-   if (FindNextMinusOne(stream,Mot)) return 1;
-   if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-   if ((NbrWords==1) && (atoi(Mot[0])==type))
-     return 0;
-   else if (FindNextMinusOne(stream,Mot)) return 1;
-   }
-   while (!stream.rdstate());
- return 1;
-}
-
-/***************************************************************************/
-
-main(int argc, char *argv[])
-
-{
-
-if (argc!=3)
-  {
-  cout << "Usage: scanuff ufffile code" << endl;
-  cout << "Affiche les caracteres hexadecimaux" << endl;
-  exit(1);
-  }
-
-ifstream infile(argv[1]);
-if (!infile)
-  {
-  cout << "Cannot open file " << argv[1] << endl;
-  exit(1);
-  }
-
-
-int i;
- unsigned char c; unsigned int code; int nbrmots;
- char **Mot;
- Mot =new char*[20];
- for (i=0; i<20; i++) Mot[i]=new char[30];
-
- if (FindNextUff(infile,atoi(argv[2]),Mot))
-   { cout << "Not found" << endl; return 1; }
- GetWordsInLine(infile,nbrmots,Mot);
- for (i=0;i<nbrmots;i++) cout << " " << Mot[i];
- cout << endl;
-
-infile.close();
-
-return 0;
-
-}
+#include<stdlib.h>
+#include<iostream>
+#include<fstream>
+
+using namespace std;
+
+/***************************************************************************/
+
+int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
+
+/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
+   ou plusieurs espaces et tabulations */
+
+  {
+  char c;
+  int lncrtword=0; // longueur du mot courant;
+  nbrmotslus=0; // nombre de mots
+  if (stream.rdstate()) return 1;
+  do
+    {
+    // Reading spaces
+    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
+    // Reading word
+    nbrmotslus++; lncrtword=0;
+    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
+           (stream.peek()!='\n') && (stream.peek()!='\r') &&
+           (stream.peek()!='\f') && (stream.peek()!=EOF))
+      {
+      Mot[nbrmotslus-1][lncrtword]=stream.get();
+      lncrtword++;
+      }
+    if (lncrtword==0) nbrmotslus--;
+    else Mot[nbrmotslus-1][lncrtword]='\0';
+    }
+  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
+         &&(stream.peek()!='\r') && !stream.rdstate()); 
+  // Reading end of line characters
+  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
+         || (stream.peek()=='\r')) c=stream.get(); 
+  // Looking for end of file before returning
+  if (stream.peek()==EOF) c=stream.get(); 
+  return 0;
+  } // fin de GetWords
+
+/***************************************************************************/
+
+int FindNextMinusOne(istream &stream, char **Mot)
+{
+int NbrWords;
+do
+  {
+  if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
+  }
+  while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
+return 0;
+}
+
+/***************************************************************************/
+
+int FindNextUff(istream &stream, int type, char **Mot)
+{
+int NbrWords;
+ do
+   {
+   if (FindNextMinusOne(stream,Mot)) return 1;
+   if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
+   if ((NbrWords==1) && (atoi(Mot[0])==type))
+     return 0;
+   else if (FindNextMinusOne(stream,Mot)) return 1;
+   }
+   while (!stream.rdstate());
+ return 1;
+}
+
+/***************************************************************************/
+
+main(int argc, char *argv[])
+
+{
+
+if (argc!=3)
+  {
+  cout << "Usage: scanuff ufffile code" << endl;
+  cout << "Affiche les caracteres hexadecimaux" << endl;
+  exit(1);
+  }
+
+ifstream infile(argv[1]);
+if (!infile)
+  {
+  cout << "Cannot open file " << argv[1] << endl;
+  exit(1);
+  }
+
+
+int i;
+ unsigned char c; unsigned int code; int nbrmots;
+ char **Mot;
+ Mot =new char*[20];
+ for (i=0; i<20; i++) Mot[i]=new char[30];
+
+ if (FindNextUff(infile,atoi(argv[2]),Mot))
+   { cout << "Not found" << endl; return 1; }
+ GetWordsInLine(infile,nbrmots,Mot);
+ for (i=0;i<nbrmots;i++) cout << " " << Mot[i];
+ cout << endl;
+
+infile.close();
+
+return 0;
+
+}
Index: src/scanwords.cpp
===================================================================
RCS file: /var/cvs/mbdyn/EasyAnim/src/scanwords.cpp,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/scanwords.cpp	27 Jan 2006 19:53:25 -0000	1.1.1.1
+++ src/scanwords.cpp	25 Oct 2006 02:25:26 -0000	1.2
@@ -1,113 +1,113 @@
-#include<stdlib.h>
-#include<iostream>
-#include<fstream>
-
-using namespace std;
-
-/***************************************************************************/
-
-int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
-
-/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
-   ou plusieurs espaces et tabulations */
-
-  {
-  char c;
-  int lncrtword=0; // longueur du mot courant;
-  nbrmotslus=0; // nombre de mots
-  if (stream.rdstate()) return 1;
-  do
-    {
-    // Reading spaces
-    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
-    // Reading word
-    nbrmotslus++; lncrtword=0;
-    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
-           (stream.peek()!='\n') && (stream.peek()!='\r') &&
-           (stream.peek()!='\f') && (stream.peek()!=EOF))
-      {
-      Mot[nbrmotslus-1][lncrtword]=stream.get();
-      lncrtword++;
-      }
-    if (lncrtword==0) nbrmotslus--;
-    else Mot[nbrmotslus-1][lncrtword]='\0';
-    }
-  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
-         &&(stream.peek()!='\r') && !stream.rdstate()); 
-  // Reading end of line characters
-  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
-         || (stream.peek()=='\r')) c=stream.get(); 
-  // Looking for end of file before returning
-  if (stream.peek()==EOF) c=stream.get(); 
-  return 0;
-  } // fin de GetWords
-
-/***************************************************************************/
-
-int FindNextMinusOne(istream &stream, char **Mot)
-{
-int NbrWords;
-do
-  {
-  if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-  }
-  while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
-return 0;
-}
-
-/***************************************************************************/
-
-int FindNextUff(istream &stream, int type, char **Mot)
-{
-int NbrWords;
- do
-   {
-   if (FindNextMinusOne(stream,Mot)) return 1;
-   if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
-   if ((NbrWords==1) && (atoi(Mot[0])==type))
-     return 0;
-   else if (FindNextMinusOne(stream,Mot)) return 1;
-   }
-   while (!stream.rdstate());
- return 1;
-}
-
-/***************************************************************************/
-
-main(int argc, char *argv[])
-
-{
-
-if (argc!=2)
-  {
-  cout << "Usage: decode file" << endl;
-  cout << "Affiche les caracteres hexadecimaux" << endl;
-  exit(1);
-  }
-
-ifstream infile(argv[1]);
-if (!infile)
-  {
-  cout << "Cannot open file " << argv[1] << endl;
-  exit(1);
-  }
-
-
-int i;
- unsigned char c; unsigned int code; int nbrmots;
- char **Mot;
- Mot =new char*[20];
- for (i=0; i<20; i++) Mot[i]=new char[30];
-
-while (!infile.eof())
-  {
-    GetWordsInLine(infile,nbrmots,Mot);
-    for (i=0;i<nbrmots;i++) cout << " " << Mot[i];
-    cout << endl;
-  }
-
-infile.close();
-
-return 0;
-
-}
+#include<stdlib.h>
+#include<iostream>
+#include<fstream>
+
+using namespace std;
+
+/***************************************************************************/
+
+int GetWordsInLine(istream &stream, int &nbrmotslus, char **Mot)
+
+/* Fonction permettant d'extraire d'une ligne tous les mots separes par un
+   ou plusieurs espaces et tabulations */
+
+  {
+  char c;
+  int lncrtword=0; // longueur du mot courant;
+  nbrmotslus=0; // nombre de mots
+  if (stream.rdstate()) return 1;
+  do
+    {
+    // Reading spaces
+    while ((stream.peek()==' ') || (stream.peek()=='\t')) c=stream.get();
+    // Reading word
+    nbrmotslus++; lncrtword=0;
+    while ((stream.peek()!=' ') && (stream.peek()!='\t') &&
+           (stream.peek()!='\n') && (stream.peek()!='\r') &&
+           (stream.peek()!='\f') && (stream.peek()!=EOF))
+      {
+      Mot[nbrmotslus-1][lncrtword]=stream.get();
+      lncrtword++;
+      }
+    if (lncrtword==0) nbrmotslus--;
+    else Mot[nbrmotslus-1][lncrtword]='\0';
+    }
+  while ((stream.peek()!='\n') && (stream.peek()!='\f') 
+         &&(stream.peek()!='\r') && !stream.rdstate()); 
+  // Reading end of line characters
+  while ((stream.peek()=='\n') || (stream.peek()=='\f') 
+         || (stream.peek()=='\r')) c=stream.get(); 
+  // Looking for end of file before returning
+  if (stream.peek()==EOF) c=stream.get(); 
+  return 0;
+  } // fin de GetWords
+
+/***************************************************************************/
+
+int FindNextMinusOne(istream &stream, char **Mot)
+{
+int NbrWords;
+do
+  {
+  if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
+  }
+  while ((NbrWords!=1) || (strcmp(Mot[0],"-1")!=0));
+return 0;
+}
+
+/***************************************************************************/
+
+int FindNextUff(istream &stream, int type, char **Mot)
+{
+int NbrWords;
+ do
+   {
+   if (FindNextMinusOne(stream,Mot)) return 1;
+   if (GetWordsInLine(stream,NbrWords,Mot)) return 1;
+   if ((NbrWords==1) && (atoi(Mot[0])==type))
+     return 0;
+   else if (FindNextMinusOne(stream,Mot)) return 1;
+   }
+   while (!stream.rdstate());
+ return 1;
+}
+
+/***************************************************************************/
+
+main(int argc, char *argv[])
+
+{
+
+if (argc!=2)
+  {
+  cout << "Usage: decode file" << endl;
+  cout << "Affiche les caracteres hexadecimaux" << endl;
+  exit(1);
+  }
+
+ifstream infile(argv[1]);
+if (!infile)
+  {
+  cout << "Cannot open file " << argv[1] << endl;
+  exit(1);
+  }
+
+
+int i;
+ unsigned char c; unsigned int code; int nbrmots;
+ char **Mot;
+ Mot =new char*[20];
+ for (i=0; i<20; i++) Mot[i]=new char[30];
+
+while (!infile.eof())
+  {
+    GetWordsInLine(infile,nbrmots,Mot);
+    for (i=0;i<nbrmots;i++) cout << " " << Mot[i];
+    cout << endl;
+  }
+
+infile.close();
+
+return 0;
+
+}
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ TODO	2006-10-26 22:54:51.000000000 +0200
@@ -0,0 +1,15 @@
+EasyAnim 1.3 desired enhancements:
+
+- add a view toolbar/menu and
+	- allow to set the amount of rotation/translation
+	- allow to set the center of rotation
+	- allow to rotate/translate/zoom with the mouse
+- allow to print labels (need to deal with OpenGL low level stuff :()
+- allow to maximize the window (already works on CentOS 4.4!)
+- load all modes and create a menu to choose from
+
+EasyAnim 1.* desired enhancements:
+- allow to read rotation parameters (will break .vol/.van compatibility)
+- add triads (use OpenGL cone for arrow?)
+	- can switch on/off
+	- can enlarge/reduce
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ src/movie_st_stop.vbm	2006-04-13 00:40:21.000000000 +0200
@@ -0,0 +1,26 @@
+//vbm8
+#define movie_st_stop_depth 8
+#define movie_st_stop_width 16
+#define movie_st_stop_height 16
+static unsigned char movie_st_stop_bits[] = {
+2,
+0,181,0,
+255,0,0,
+160,160,160,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,0,0,2,2,2,2,2,0,0,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,0,0,2,2,2,2,2,0,0,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,0,0,0,0,0,0,0,0,0,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,2,0,2,2,2,2,2,0,2,0,2,2,
+2,2,2,0,0,0,2,2,2,2,2,0,0,0,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+};
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ src/picture.vbm	2006-05-05 23:52:49.000000000 +0200
@@ -0,0 +1,27 @@
+//vbm8
+#define picture_depth 8
+#define picture_width 16
+#define picture_height 16
+static unsigned char picture_bits[] = {
+3,
+0,181,0,
+255,0,0,
+160,160,160,
+0,0,255,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,3,3,3,3,3,3,3,3,2,2,2,2,2,
+2,2,2,3,3,3,3,3,3,3,3,2,2,2,2,2,
+2,2,2,3,3,3,3,3,3,3,1,1,1,2,2,2,
+2,2,2,3,3,3,3,3,1,1,1,1,1,1,1,2,
+2,2,2,3,3,3,3,1,1,1,1,1,1,1,1,1,
+2,2,2,3,3,3,0,1,1,1,1,1,1,1,1,1,
+2,2,2,3,3,0,0,1,1,1,1,1,1,1,1,1,
+2,2,2,3,0,0,0,1,1,1,1,1,1,1,1,1,
+2,2,2,0,0,0,2,1,1,1,1,1,1,1,1,1,
+2,2,0,0,0,2,2,2,1,1,1,1,1,1,1,2,
+2,0,0,0,0,0,0,0,0,0,1,1,1,2,2,2,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+};
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ src/rev_st_stop.vbm	2006-10-25 04:25:01.000000000 +0200
@@ -0,0 +1,26 @@
+//vbm8
+#define rev_st_stop_depth 8
+#define rev_st_stop_width 16
+#define rev_st_stop_height 16
+static unsigned char rev_st_stop_bits[] = {
+2,
+0,181,0,
+255,0,0,
+160,160,160,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,2,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,0,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,0,0,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,0,0,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,0,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,0,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,2,0,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,2,2,0,0,2,1,1,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+};
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ src/usesock.cpp	2006-11-16 23:07:21.000000000 +0100
@@ -0,0 +1,471 @@
+/* 
+ * MBDyn (C) is a multibody analysis code. 
+ * http://www.mbdyn.org
+ *
+ * Copyright (C) 1996-2006
+ *
+ * Pierangelo Masarati	<masarati@aero.polimi.it>
+ * Paolo Mantegazza	<mantegazza@aero.polimi.it>
+ *
+ * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
+ * via La Masa, 34 - 20156 Milano, Italy
+ * http://www.aero.polimi.it
+ *
+ * Changing this copyright notice is forbidden.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ * 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file is used by EasyAnim to deal with motion sent by an external
+ * program as a stream of data.  It has been incorporated into the branch
+ * of EasyAnim 1.3 developed at DIAPM by Pierangelo Masarati.
+ */
+
+#include <netdb.h>
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <iostream>
+#include <fstream>
+
+#include "usesock.h"
+
+#define DEFAULT_PORT	5500 /* FIXME: da definire meglio */
+#define DEFAULT_HOST 	"127.0.0.1"
+#define DEFAULT_PATH	"easyanim.sock"
+
+
+static int
+make_inet_socket(struct sockaddr_in *name, const char *hostname,
+		unsigned short int port, int dobind, int *perrno)
+{
+   	int			sock = -1;
+
+	socklen_t		size;
+
+	if (perrno) {
+		*perrno = 0;
+	}
+
+   	/* Create the socket. */
+   	sock = socket(PF_INET, SOCK_STREAM, 0);
+   	if (sock < 0) {
+		if (perrno) {
+			*perrno = errno;
+		}
+      		return -1;
+   	}
+
+   	/* Give the socket a name. */
+   	name->sin_family = AF_INET;
+   	name->sin_port = htons(port);
+	if (hostname) {
+		struct hostent	*hostinfo;
+
+		hostinfo = gethostbyname(hostname);
+		if (hostinfo == NULL) {
+			*perrno = h_errno;
+			return -3;
+		}
+
+		name->sin_addr = *(struct in_addr *)hostinfo->h_addr;
+	} else {
+		name->sin_addr.s_addr = htonl(INADDR_ANY);
+	}
+
+	size = sizeof(struct sockaddr_in);
+	if (dobind && bind(sock, (struct sockaddr *) name, size) < 0)
+	{
+		if (perrno) {
+			*perrno = errno;
+		}
+		return -2;
+   	}
+
+   	return sock;
+}
+
+static int
+make_named_socket(const char *path, int dobind, int *perrno)
+{
+   	int			sock = -1;
+
+   	struct sockaddr_un	name;
+	socklen_t		size;
+
+	if (perrno) {
+		*perrno = 0;
+	}
+
+   	/* Create the socket. */
+   	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+   	if (sock < 0) {
+		if (perrno) {
+			*perrno = errno;
+		}
+      		return -1;
+   	}
+
+   	/* Give the socket a name. */
+   	name.sun_family = AF_LOCAL;
+   	strncpy(name.sun_path, path, sizeof(name.sun_path));
+	size = (offsetof(struct sockaddr_un, sun_path)
+			+ strlen(name.sun_path) + 1);
+   	if (dobind && bind(sock, (struct sockaddr *) &name, size) < 0) {
+		if (perrno) {
+			*perrno = errno;
+		}
+      		return -2;
+   	}
+
+   	return sock;
+}
+
+UseSocket::UseSocket(bool c)
+: sock(-1),
+create(c),
+connected(false),
+abandoned(false),
+socklen(0)
+{
+}
+
+UseSocket::~UseSocket(void)
+{
+	if (sock != -1) {
+		shutdown(sock, SHUT_RDWR);
+		close(sock);
+	}
+}
+
+int
+UseSocket::GetSock(void) const
+{
+	return sock;
+}
+
+void
+UseSocket::SetSock(int s)
+{
+	sock = s;
+}
+
+void
+UseSocket::PostConnect(void)
+{
+	struct linger lin;
+	lin.l_onoff = 1;
+	lin.l_linger = 0;
+		
+	if (setsockopt(GetSock(), SOL_SOCKET, SO_LINGER, &lin, sizeof(lin))) {
+		int save_errno = errno;
+		char *msg = strerror(save_errno);
+
+		std::cerr << "UseSocket(): setsockopt() failed "
+				"(" << save_errno << ": " << msg << ")"
+				<< std::endl;
+      		throw Error();
+	}
+}
+
+void
+UseSocket::Connect(void)
+{
+	int	count = 1000;
+	int	timeout = 100000;
+
+	for ( ; count > 0; count--) {
+		if (connect(sock, GetSockaddr(), GetSocklen()) < 0) {
+			if (errno == ECONNREFUSED) {
+				/* Socket does not exist yet; retry */
+				usleep(timeout);
+				continue;
+			}
+
+			/* Connect failed */
+			std::cerr << "UseSocket(): connect() failed "
+					<< std::endl;
+			throw Error();
+		}
+
+		/* Success */
+		connected = true;
+		PostConnect();
+		return;
+	}
+
+	std::cerr << "UseSocket(): connection timeout reached "
+			<< std::endl;
+	throw Error();
+}
+
+void
+UseSocket::ConnectSock(int s)
+{
+	SetSock(s);
+
+	connected = true;
+
+	PostConnect();
+}
+
+bool
+UseSocket::Connected(void) const
+{
+	return connected;
+}
+
+void
+UseSocket::Abandon(void)
+{
+	abandoned = true;
+}
+
+bool
+UseSocket::Abandoned(void) const
+{
+	return abandoned;
+}
+
+socklen_t&
+UseSocket::GetSocklen(void) const
+{
+	return socklen;
+}
+
+UseInetSocket::UseInetSocket(std::string& h, unsigned short p, bool c)
+: UseSocket(c),
+host(h),
+port(p)
+{
+	socklen = sizeof(addr);
+
+
+	char buf[BUFSIZ];
+	
+	/* if 0, means INET on localhost */
+	if (host.empty()) {
+		host = DEFAULT_HOST;
+	}
+
+	snprintf(buf, sizeof(buf), "%s:%u", host.c_str(), p);
+	
+	if (create) {
+		struct sockaddr_in	addr_name;
+		int			save_errno;
+
+   		sock = make_inet_socket(&addr_name, host.c_str(), port, 1, &save_errno);
+		
+		if (sock == -1) {
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseInetSocket(" << buf << "): "
+				"socket() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+
+   		} else if (sock == -2) {
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseInetSocket(" << buf << "): "
+				"bind() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+
+   		} else if (sock == -3) {
+			std::cerr << "UseInetSocket(" << buf << "): "
+				"illegal host name \"" << host << "\" "
+				"(" << save_errno << ")"
+				<< std::endl;
+      			throw Error();
+   		}
+
+   		if (listen(sock, 1) < 0) {
+			save_errno = errno;
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseInetSocket(" << buf << "): "
+				"listen() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+   		}
+	}
+}
+
+UseInetSocket::~UseInetSocket(void)
+{
+}
+
+void
+UseInetSocket::Connect(void)
+{
+	if (connected) {
+		return;
+	}
+
+	sock = socket(PF_INET, SOCK_STREAM, 0);
+	if (sock < 0) {
+		std::cerr << "UseSocket(): socket() failed "
+				<< "\"" << host << ":" << port << "\""
+				<< std::endl;
+		throw Error();
+	}
+
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(port);
+	if (inet_aton(host.c_str(), &addr.sin_addr) == 0) {
+		std::cerr << "UseSocket(): unknown host "
+				"\"" << host << ":" << port << "\""
+				<< std::endl;
+		throw Error();
+	}
+
+	std::cout << "connecting to inet socket "
+			"\"" << inet_ntoa(addr.sin_addr) 
+			<< ":" << ntohs(addr.sin_port)
+			<< "\" ..." << std::endl;
+
+	UseSocket::Connect();
+}
+	
+void
+UseInetSocket::ConnectSock(int s)
+{
+	UseSocket::ConnectSock(s);
+	
+	std::cout << "INET connection to port=" << port << " by client "
+			<< "\"" << inet_ntoa(addr.sin_addr)
+			<< ":" << ntohs(addr.sin_port) << "\""
+			<< std::endl;
+}
+
+struct sockaddr *
+UseInetSocket::GetSockaddr(void) const
+{
+	return (struct sockaddr *)&addr;
+}
+	
+UseLocalSocket::UseLocalSocket(std::string& p, bool c)
+: UseSocket(c),
+path(p)
+{
+	socklen = sizeof(addr);
+
+	if (path.empty()) {
+		const char	*tmp = getenv("TMPDIR");
+		if (tmp == 0) {
+			tmp = "/tmp";
+		}
+
+		path = std::string(tmp) + DEFAULT_PATH;
+	}
+	
+	if (create) {
+		int		save_errno;
+
+		sock = make_named_socket(path.c_str(), 1, &save_errno);
+		
+		if (sock == -1) {
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseLocalSocket(" << path << "): "
+				"socket() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+
+   		} else if (sock == -2) {
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseLocalSocket(" << path << "): "
+				"bind() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+   		}
+   		if (listen(sock, 1) < 0) {
+			save_errno = errno;
+			const char	*err_msg = strerror(save_errno);
+
+			std::cerr << "UseLocalSocket(" << path << "): "
+				"listen() failed "
+				"(" << save_errno << ": " << err_msg << ")"
+				<< std::endl;
+      			throw Error();
+   		}
+	}
+}
+
+UseLocalSocket::~UseLocalSocket(void)
+{
+	if (!path.empty() && create) {
+		unlink(path.c_str());
+	}
+}
+
+void
+UseLocalSocket::Connect(void)
+{
+	if (connected) {
+		return;
+	}
+
+	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (sock < 0){
+		int save_errno = errno;
+		char *msg = strerror(save_errno);
+
+		std::cerr << "UseSocket(): socket() failed "
+				"(" << save_errno << ": " << msg << ")"
+				<< std::endl;
+		throw Error();
+	}
+	addr.sun_family = AF_UNIX;
+	memcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
+
+	std::cout << "connecting to local socket \""
+			<< path << "\" ..." << std::endl;
+
+	UseSocket::Connect();
+}
+
+void
+UseLocalSocket::ConnectSock(int s)
+{
+	UseSocket::ConnectSock(s);
+	
+	std::cout << "LOCAL connection to path=" << path << std::endl;
+}
+
+struct sockaddr *
+UseLocalSocket::GetSockaddr(void) const
+{
+	return (struct sockaddr *)&addr;
+}
+
--- /dev/null	2006-11-28 09:37:37.000187500 +0100
+++ src/usesock.h	2006-11-16 23:07:21.000000000 +0100
@@ -0,0 +1,103 @@
+/* 
+ * MBDyn (C) is a multibody analysis code. 
+ * http://www.mbdyn.org
+ *
+ * Copyright (C) 1996-2006
+ *
+ * Pierangelo Masarati	<masarati@aero.polimi.it>
+ * Paolo Mantegazza	<mantegazza@aero.polimi.it>
+ *
+ * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
+ * via La Masa, 34 - 20156 Milano, Italy
+ * http://www.aero.polimi.it
+ *
+ * Changing this copyright notice is forbidden.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ * 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file is used by EasyAnim to deal with motion sent by an external
+ * program as a stream of data.  It has been incorporated into the branch
+ * of EasyAnim 1.3 developed at DIAPM by Pierangelo Masarati.
+ */
+
+#ifndef USESOCK_H
+#define USESOCK_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+class UseSocket {
+protected:
+	int sock;
+	bool create;
+	bool connected;
+	bool abandoned;
+
+	mutable socklen_t socklen;
+
+	void PostConnect(void);
+
+public:
+	UseSocket(bool c);
+	virtual ~UseSocket(void);
+	
+	int GetSock(void) const;
+	void SetSock(int s);
+	virtual void Connect(void);
+	virtual void ConnectSock(int s);
+	bool Connected(void) const;
+	void Abandon(void);
+	bool Abandoned(void) const;
+
+	socklen_t& GetSocklen(void) const;
+	virtual struct sockaddr *GetSockaddr(void) const = 0;
+
+	class Error {};
+};
+
+class UseInetSocket : public UseSocket {
+protected:
+	std::string host;
+ 	unsigned short int port;
+	struct sockaddr_in addr;
+	
+public:
+	UseInetSocket(std::string &h, unsigned short p, bool c);
+	virtual ~UseInetSocket(void);
+	
+	void Connect(void);
+	void ConnectSock(int s);
+	struct sockaddr *GetSockaddr(void) const;
+};
+
+class UseLocalSocket : public UseSocket {
+protected:
+	std::string path;
+	struct sockaddr_un addr;
+	
+public:
+	UseLocalSocket(std::string& p, bool c);
+	virtual ~UseLocalSocket(void);
+	
+	void Connect(void);
+	void ConnectSock(int s);
+	struct sockaddr *GetSockaddr(void) const;
+};
+
+#endif /* USESOCK_H */
+
