1 // sous mac 
  2 // g++  -I/usr/local/include/ -lglfw -lGLEW -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs main54.cpp -framework OpenGL  -omain54
  3 // ./main54
  4 
  5 // sous linux   
  6 // g++ -I/usr/local/include/ -I/public/ig/glm/ -c main54.cpp  -omain54.o
  7 // g++ -I/usr/local main54.o -lglfw  -lGLEW  -lGL  -omain54
  8 // ./main54
  9 
 10 // Inclut les en-têtes standards
 11 #include <stdio.h>
 12 #include <string>
 13 #include <vector>
 14 #include <iostream>
 15 #include <fstream>
 16 #include <algorithm>
 17 #include <map>
 18 using namespace std;
 19 
 20 #include <stdlib.h>
 21 #include <string.h>
 22 
 23 #include <GL/glew.h>
 24 #include <GLFW/glfw3.h>
 25 
 26 // following the tutorial found here:
 27 // https://www.learnopencv.com/delaunay-triangulation-and-voronoi-diagram-using-opencv-c-python/
 28 // http://www.faadoosupport.com/learning-opencv-3-delaunay-triangulation-and-voronoi-diagram-explanation/
 29 #include <opencv2/imgproc/imgproc.hpp>
 30 #include <opencv2/highgui/highgui.hpp>
 31 
 32 #ifdef __APPLE__
 33 #include <OpenGL/gl.h>
 34 #else
 35 #include <GL/gl.h>
 36 #endif
 37 
 38 #define GLM_FORCE_RADIANS
 39 #include <glm/glm.hpp>
 40 #include <glm/gtc/matrix_transform.hpp>
 41 #include <glm/gtc/type_ptr.hpp>
 42 
 43 
 44 using namespace glm;
 45 using namespace cv;
 46 
 47 double dangle = M_PI/1024;
 48 
 49 const int N = 10000000;
 50 
 51 std::map<Point2f,float> altitudes;
 52 std::map<Point2f,float> infos2;
 53 long sss=0;
 54 GLfloat *g_vertex_buffer_data;
 55 GLfloat *g_vertex_color_data;
 56 GLfloat *g_vertex_normal_data;
 57 vector<vector<Point2f> > facets;
 58 vector<Point2f> centers;
 59 
 60 // stocke les variables uniformes qui seront communes a tous les vertex dessines dans une variable globale 
 61 GLint uniform_proj, uniform_view, uniform_model;
 62 float w = 1000.0;
 63 
 64 // france in geojson from :
 65 //https://github.com/mledoze/countries/blob/bb61a1cddfefd09ad5c92ad0a1effbfceba39930/data/fra.geo.json
 66 
 67 bool sitesOrdered(const Point2f& s1, const Point2f& s2) {
 68   if (s1.y < s2.y)
 69     return true;
 70   if (s1.y == s2.y && s1.x < s2.x)
 71     return true;
 72 
 73   return false;
 74 }
 75 
 76 
 77 
 78 namespace cv {
 79   bool operator<(Point2f const& lhs, Point2f const& rhs) {
 80       return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;
 81   }
 82 }
 83 
 84 
 85 
 86 void readData(){
 87   std::cout << "readData " <<endl;
 88   unsigned int nPoints;
 89   float dimension = 1.0;
 90   Rect *rect = new Rect(0, 0, w, w);
 91 
 92 
 93   
 94  
 95   // Create an instance of Subdiv2D
 96   Subdiv2D *subdiv = new Subdiv2D(*rect);
 97 
 98   ifstream file ( "villes.csv" ); // declare file stream: http://www.cplusplus.com/reference/iostream/ifstream/
 99   string value;
100   getline ( file, value, '\n' );
101 
102   
103   float minlon = 10;
104   float maxlon = 0;
105   float minlat = 10;
106   float maxlat = 0;
107   int count    = 0;
108 
109   vector<Point2f> tmpSites;
110   vector<Point2f> sites;
111   Point2f s;
112 
113 
114   while ( file.good() ) {
115      getline ( file, value, ';' ); // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
116      string sinsee = string( value, 0, value.length() );
117      getline ( file, value, ';' );
118      string sname = string( value, 0, value.length() );
119      getline ( file, value, ';' );
120      string saltitude = string( value, 0, value.length() );
121      float alt = stof(saltitude, NULL);
122      getline ( file, value, ';' );
123      string scp = string( value, 0, value.length() );
124      getline ( file, value, ';' );
125      string slon = string( value, 0, value.length() );
126      float lon = stof(slon, NULL);
127      getline ( file, value, ';' );
128      string slat = string( value, 0, value.length() );
129      float lat = stof(slat, NULL);
130      getline ( file, value, ';' );
131      string spop = string( value, 0, value.length() );
132      int pop = stoi(spop, NULL);
133      getline ( file, value, '\n' );
134      string ssur = string( value, 0, value.length() );
135      float sur = stof(ssur, NULL);
136      
137      count++;
138      if (count<N){
139         minlon = glm::min(lon, minlon);
140        maxlon = glm::max(lon, maxlon);
141        minlat = glm::min(lat, minlat);
142        maxlat = glm::max(lat, maxlat);
143        s.x    = lon;
144        s.y    = lat;
145        altitudes[s] = alt/20000.0;
146        infos2[s]    = pop/sur/200.0;
147 
148        tmpSites.push_back(s); 
149      }  
150        
151   }
152 
153   cout << "City File read !" << tmpSites.size() << " / " << N << endl;
154   cout <<"  lons:"<<minlon<<"..."<<maxlon<<endl;
155   cout <<"  lats:"<<minlat<<"..."<<maxlat<<endl;
156 
157   ifstream file2 ( "fra.geo.json" ); // declare file stream: http://www.cplusplus.com/reference/iostream/ifstream/
158   getline ( file2, value, '[' );
159   getline ( file2, value, '[' );
160   getline ( file2, value, '[' );
161   getline ( file2, value, '[' );
162   getline ( file2, value, '[' );
163   count    = 0;
164   while ( file2.good() ) {
165     getline ( file2, value, ',' );
166     int i=0;
167     while(value.at(i)=='[') i++;
168     string sx = string( value, i, value.length());
169 
170     getline ( file2, value, ']' );
171     string sy = string( value, 0, value.length());
172     getline ( file2, value, '[' );
173     
174     float lon = M_PI/180.0*stof(sx, NULL);
175     float lat = M_PI/180.0*stof(sy, NULL);
176     minlon=glm::min(lon, minlon);
177     maxlon=glm::max(lon, maxlon);
178     minlat=glm::min(lat, minlat);
179     maxlat=glm::max(lat, maxlat);
180     s.x = lon;
181     s.y = lat;
182     //  cout << s.x << ", " << s.y << " " << endl;
183     tmpSites.push_back(s);
184     altitudes[s] = -0.25;
185     count++;
186   }
187   cout << "Border File read !" << count << endl;
188   cout <<"  lons:"<<minlon<<"..."<<maxlon<<" among "<<tmpSites.size()<<" / "<<N<<endl;
189   cout <<"  lats:"<<minlat<<"..."<<maxlat<<" among "<<tmpSites.size()<<" / "<<N<<endl;
190 
191   //enleve les doublons et normalise
192   Point2f s2;
193   std::sort(tmpSites.begin(), tmpSites.end(), sitesOrdered);
194   s2.x = (0.1+(tmpSites[0].x-minlon)/(maxlon-minlon))*0.8*w;
195   s2.y = (0.1+(tmpSites[0].y-minlat)/(maxlat-minlat))*0.8*w;
196 
197   sites.push_back(s2);
198   for (vector<Point2f>::iterator it = tmpSites.begin(); it != tmpSites.end(); it++) {
199     Point2f& s =*it;
200     s2.x = (0.1+(s.x-minlon)/(maxlon-minlon)*0.8)*w;
201     s2.y = (0.1+(s.y-minlat)/(maxlat-minlat)*0.8)*w;
202 
203     if (s != sites.back()) {
204       sites.push_back(s2);
205       altitudes[s2] = altitudes[s];
206       infos2[s2]    = infos2[s];
207     } else{
208       cout <<"WARNING: "<<s2.x<<","<<s2.y<<" is identical to "<<sites.back().x<<","<<sites.back().y<<endl;
209     }
210 
211   }
212   cout << "  point normalization and duplicate removal done. " <<endl;
213 
214   for( vector<Point2f>::iterator it = sites.begin(); it != sites.end(); it++){
215     subdiv->insert(*it);
216   }
217 
218   // Voila c'est ici qu'on lance l'algo de Voronoi
219    subdiv->getVoronoiFacetList(vector<int>(), facets, centers);
220   
221   cout << "  facets&centers list: " << facets.size() << " % "  << centers.size()<<endl;
222   
223   // une premiere passe sur les cellule de voronoi pour ajouter a cahque point du bord 
224   // l'altitude du centre de la cellule de vononoi  (chaque point devrait se voir ajouter 3 altitudes !)
225   for( size_t i = 0; i < facets.size(); i++ ){
226     for( size_t j = 0; j < facets[i].size(); j++ ){
227       altitudes[facets[i][j]] =  altitudes[facets[i][j]] + altitudes[centers[i]];
228       sss++; // on en profite pour compter combien de triangles nous aurons besoin
229     }
230   }
231   
232   // sss est ici le nombre de triangles necessaires .. mais on voudrait plutot la taille memoire cencessaire
233   sss = (4+sss)*sizeof(GLfloat)*9;
234   
235   cout << "allocate arrays  => " << sss << endl;
236   
237   // Malheureusement on ne peut plus faire de l'allocation statique de memoire
238   g_vertex_buffer_data = (GLfloat *)malloc(sss);
239   g_vertex_color_data  = (GLfloat *)malloc(sss);
240   g_vertex_normal_data = (GLfloat *)malloc(sss);
241   //GLfloat g_vertex_buffer_data[sss];
242   //GLfloat g_vertex_color_data[sss];
243 }
244 
245 
246 void updateRepr(float gain1, float gain2){
247   long ii=0;
248   glm::vec3 normal;
249 
250   for( size_t i = 0; i < facets.size(); i++ ){
251       Point2f p0 = centers[i];
252       srand(i); // chaque facette aura une couleur differente
253       float r = (rand()%256)/256.0;
254       float g = (rand()%256)/256.0;
255       float b = 0.0;
256       for( size_t j = 0; j < facets[i].size(); j++ ){
257         Point2f p1 = facets[i][j];
258         // ah ah ah qui comprend la formule avec un modulo ?
259         Point2f p2 = facets[i][(j+facets[i].size()-1)%facets[i].size()];
260 
261         g_vertex_buffer_data[ 0+ii*9] = p0.x/w;
262         g_vertex_buffer_data[ 1+ii*9] = p0.y/w;
263         g_vertex_buffer_data[ 2+ii*9] = gain1*altitudes[p0];
264 
265         g_vertex_buffer_data[ 3+ii*9] = p1.x/w;
266         g_vertex_buffer_data[ 4+ii*9] = p1.y/w;
267         g_vertex_buffer_data[ 5+ii*9] = gain1*altitudes[p1]/3.0;
268 
269         g_vertex_buffer_data[ 6+ii*9] = p2.x/w;
270         g_vertex_buffer_data[ 7+ii*9] = p2.y/w;
271         g_vertex_buffer_data[ 8+ii*9] = gain1*altitudes[p2]/3.0;
272 
273         // le centre de la cellule de voronoi a une couleur dependant de info2
274         g_vertex_color_data[ 0+ii*9] = gain2*infos2[p0];
275         g_vertex_color_data[ 1+ii*9] = gain2*infos2[p0];
276         g_vertex_color_data[ 2+ii*9] = gain2*infos2[p0];
277 
278         //les bords de la cellule de voronoi ont une couleur aleatoire dependante de la cellule
279         g_vertex_color_data[ 3+ii*9] = 0.5+r/2.0;
280         g_vertex_color_data[ 4+ii*9] = 0.5+g/2.0;
281         g_vertex_color_data[ 5+ii*9] = 0.5+b/2.0;
282 
283         g_vertex_color_data[ 6+ii*9] = 0.5+r/2.0;
284         g_vertex_color_data[ 7+ii*9] = 0.5+g/2.0;
285         g_vertex_color_data[ 8+ii*9] = 0.5+b/2.0;
286 
287         // calcul de la normale
288         normal = -glm::normalize(glm::cross(glm::vec3(p1.x/w, p1.y/w, gain1*altitudes[p1]/3.0)-
289                                             glm::vec3(p0.x/w, p0.y/w, gain1*altitudes[p0]), 
290                                             glm::vec3(p2.x/w, p2.y/w, gain1*altitudes[p2]/3.0)-
291                                             glm::vec3(p0.x/w, p0.y/w, gain1*altitudes[p0])));
292 
293         g_vertex_normal_data[ 0+ii*9] = normal.x;
294         g_vertex_normal_data[ 1+ii*9] = normal.y;
295         g_vertex_normal_data[ 2+ii*9] = normal.z;
296 
297         g_vertex_normal_data[ 3+ii*9] = normal.x;
298         g_vertex_normal_data[ 4+ii*9] = normal.y;
299         g_vertex_normal_data[ 5+ii*9] = normal.z;
300 
301         g_vertex_normal_data[ 6+ii*9] = normal.x;
302         g_vertex_normal_data[ 7+ii*9] = normal.y;
303         g_vertex_normal_data[ 8+ii*9] = normal.z;
304 
305         ii++;
306       }
307   }
308 
309   // 4 triangles pour la mer
310   g_vertex_buffer_data[ 0+ii*9] = 0.5;
311   g_vertex_buffer_data[ 1+ii*9] = 0.5;
312   g_vertex_buffer_data[ 2+ii*9] = 0;
313 
314   g_vertex_buffer_data[ 3+ii*9] = 1.5;
315   g_vertex_buffer_data[ 4+ii*9] = -0.5;
316   g_vertex_buffer_data[ 5+ii*9] = 0;
317 
318   g_vertex_buffer_data[ 6+ii*9] = 1.5;
319   g_vertex_buffer_data[ 7+ii*9] = 1.5;
320   g_vertex_buffer_data[ 8+ii*9] = 0;
321 
322   g_vertex_color_data[ 0+ii*9] = 0;
323   g_vertex_color_data[ 1+ii*9] = 0;
324   g_vertex_color_data[ 2+ii*9] = 0.7;
325 
326   g_vertex_color_data[ 3+ii*9] = 0;
327   g_vertex_color_data[ 4+ii*9] = 0;
328   g_vertex_color_data[ 5+ii*9] = 0.1;
329 
330   g_vertex_color_data[ 6+ii*9] = 0;
331   g_vertex_color_data[ 7+ii*9] = 0;
332   g_vertex_color_data[ 8+ii*9] = 0.1;
333 
334   ii++;
335 
336   g_vertex_buffer_data[ 0+ii*9] = 0.5;
337   g_vertex_buffer_data[ 1+ii*9] = 0.5;
338   g_vertex_buffer_data[ 2+ii*9] = 0;
339 
340   g_vertex_buffer_data[ 3+ii*9] = -0.5;
341   g_vertex_buffer_data[ 4+ii*9] = 1.5;
342   g_vertex_buffer_data[ 5+ii*9] = 0;
343 
344   g_vertex_buffer_data[ 6+ii*9] = -0.5;
345   g_vertex_buffer_data[ 7+ii*9] = -0.5;
346   g_vertex_buffer_data[ 8+ii*9] = 0;
347 
348   g_vertex_color_data[ 0+ii*9] = 0;
349   g_vertex_color_data[ 1+ii*9] = 0;
350   g_vertex_color_data[ 2+ii*9] = 0.7;
351 
352   g_vertex_color_data[ 3+ii*9] = 0;
353   g_vertex_color_data[ 4+ii*9] = 0;
354   g_vertex_color_data[ 5+ii*9] = 0.1;
355 
356   g_vertex_color_data[ 6+ii*9] = 0;
357   g_vertex_color_data[ 7+ii*9] = 0;
358   g_vertex_color_data[ 8+ii*9] = 0.1;
359 
360   ii++;
361 
362   g_vertex_buffer_data[ 0+ii*9] = 0.5;
363   g_vertex_buffer_data[ 1+ii*9] = 0.5;
364   g_vertex_buffer_data[ 2+ii*9] = 0;
365 
366   g_vertex_buffer_data[ 3+ii*9] = 1.5;
367   g_vertex_buffer_data[ 4+ii*9] = -0.5;
368   g_vertex_buffer_data[ 5+ii*9] = 0;
369 
370   g_vertex_buffer_data[ 6+ii*9] = -0.5;
371   g_vertex_buffer_data[ 7+ii*9] = -0.5;
372   g_vertex_buffer_data[ 8+ii*9] = 0;
373 
374   g_vertex_color_data[ 0+ii*9] = 0;
375   g_vertex_color_data[ 1+ii*9] = 0;
376   g_vertex_color_data[ 2+ii*9] = 0.7;
377 
378   g_vertex_color_data[ 3+ii*9] = 0;
379   g_vertex_color_data[ 4+ii*9] = 0;
380   g_vertex_color_data[ 5+ii*9] = 0.1;
381 
382   g_vertex_color_data[ 6+ii*9] = 0;
383   g_vertex_color_data[ 7+ii*9] = 0;
384   g_vertex_color_data[ 8+ii*9] = 0.1;
385 
386   ii++;
387 
388   g_vertex_buffer_data[ 0+ii*9] = 0.5;
389   g_vertex_buffer_data[ 1+ii*9] = 0.5;
390   g_vertex_buffer_data[ 2+ii*9] = 0;
391 
392   g_vertex_buffer_data[ 3+ii*9] = -0.5;
393   g_vertex_buffer_data[ 4+ii*9] = 1.5;
394   g_vertex_buffer_data[ 5+ii*9] = 0;
395 
396   g_vertex_buffer_data[ 6+ii*9] = 1.5;
397   g_vertex_buffer_data[ 7+ii*9] = 1.5;
398   g_vertex_buffer_data[ 8+ii*9] = 0;
399 
400   g_vertex_color_data[ 0+ii*9] = 0;
401   g_vertex_color_data[ 1+ii*9] = 0;
402   g_vertex_color_data[ 2+ii*9] = 0.7;
403 
404   g_vertex_color_data[ 3+ii*9] = 0;
405   g_vertex_color_data[ 4+ii*9] = 0;
406   g_vertex_color_data[ 5+ii*9] = 0.1;
407 
408   g_vertex_color_data[ 6+ii*9] = 0;
409   g_vertex_color_data[ 7+ii*9] = 0;
410   g_vertex_color_data[ 8+ii*9] = 0.1;
411 }
412 
413 
414 
415 GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
416 
417   // Create the shaders
418   GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
419   GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
420 
421   // Read the Vertex Shader code from the file
422   std::string VertexShaderCode;
423   std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
424   if (VertexShaderStream.is_open()){
425     std::string Line = "";
426     while(getline(VertexShaderStream, Line))
427       VertexShaderCode += "\n" + Line;
428     VertexShaderStream.close();
429   } else {
430     printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
431     getchar();
432     return 0;
433   }
434 
435   // Read the Fragment Shader code from the file
436   std::string FragmentShaderCode;
437   std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
438   if(FragmentShaderStream.is_open()){
439     std::string Line = "";
440     while(getline(FragmentShaderStream, Line))
441       FragmentShaderCode += "\n" + Line;
442     FragmentShaderStream.close();
443   }
444 
445   GLint Result = GL_FALSE;
446   int InfoLogLength;
447 
448 
449   // Compile Vertex Shader
450   printf("Compiling shader : %s\n", vertex_file_path);
451   char const * VertexSourcePointer = VertexShaderCode.c_str();
452   glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
453   glCompileShader(VertexShaderID);
454 
455   // Check Vertex Shader
456   glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
457   glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
458   if ( InfoLogLength > 0 ){
459     std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
460     glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
461     printf("%s\n", &VertexShaderErrorMessage[0]);
462   }
463 
464 
465   // Compile Fragment Shader
466   printf("Compiling shader : %s\n", fragment_file_path);
467   char const * FragmentSourcePointer = FragmentShaderCode.c_str();
468   glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
469   glCompileShader(FragmentShaderID);
470 
471   // Check Fragment Shader
472   glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
473   glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
474   if ( InfoLogLength > 0 ){
475     std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
476     glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
477     printf("%s\n", &FragmentShaderErrorMessage[0]);
478   }
479 
480   // Link the program
481   printf("Linking program\n");
482   GLuint ProgramID = glCreateProgram();
483   glAttachShader(ProgramID, VertexShaderID);
484   glAttachShader(ProgramID, FragmentShaderID);
485   glLinkProgram(ProgramID);
486 
487   // Check the program
488   glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
489   glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
490   if ( InfoLogLength > 0 ){
491     std::vector<char> ProgramErrorMessage(InfoLogLength+1);
492     glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
493     printf("%s\n", &ProgramErrorMessage[0]);
494   }
495   
496   glDetachShader(ProgramID, VertexShaderID);
497   glDetachShader(ProgramID, FragmentShaderID);
498   
499   glDeleteShader(VertexShaderID);
500   glDeleteShader(FragmentShaderID);
501 
502   return ProgramID;
503 }
504 
505 
506 int main(){
507     // Initialise GLFW
508   if( !glfwInit() ) {
509       fprintf( stderr, "Failed to initialize GLFW\n" );
510       return -1;
511   }
512 
513 
514  
515   // 3eme partie du pipeline ... en openGL ...
516   glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
517   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // On veut OpenGL 3.3
518   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
519   glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Pour rendre MacOS heureux ; ne devrait pas être nécessaire
520   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // On ne veut pas l'ancien OpenGL
521   glfwWindowHint(GLFW_DEPTH_BITS, 24);
522 
523   // Ouvre une fenêtre et crée son contexte OpenGl
524   GLFWwindow* window; // (Dans le code source qui accompagne, cette variable est globale)
525   window = glfwCreateWindow( 2560, 1600, "Main 54", NULL, NULL);
526   if( window == NULL ){
527       fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
528       glfwTerminate();
529       return -1;
530   }
531 
532   glfwMakeContextCurrent(window); // Initialise GLEW
533   glewExperimental=true; // Nécessaire dans le profil de base
534   if (glewInit() != GLEW_OK) {
535       fprintf(stderr, "Failed to initialize GLEW\n");
536       return -1;
537   }
538   cout << "OpenGL and window initialized "<<endl;
539 
540   // Enable depth test
541   glEnable(GL_DEPTH_TEST);
542 
543   // Accept fragment if it closer to the camera than the former one
544   glDepthFunc(GL_LESS);
545   glDepthRange(0, 10);
546 
547   // Bon maintenant on cree le VAO et cette fois on va s'en servir !
548   GLuint VertexArrayID;
549   glGenVertexArrays(1, &VertexArrayID);
550   glBindVertexArray(VertexArrayID);
551 
552   float gainAlt = 1.0;
553   float gainCol = 1.0;
554 
555 
556  // 1ere partie du pipeline
557   readData();
558 
559   // 2eme partie du pipeline
560   updateRepr(gainAlt, gainCol);  
561 
562   // This will identify our vertex buffer
563   GLuint vertexbuffer;
564   // Generate 1 buffer, put the resulting identifier in vertexbuffer
565   glGenBuffers(1, &vertexbuffer);
566 
567   // The following commands will talk about our 'vertexbuffer' buffer
568   glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
569     // Only allocqte memory. Do not send yet our vertices to OpenGL.
570     glBufferData(GL_ARRAY_BUFFER, sss+sss+sss, 0, GL_STATIC_DRAW);
571 
572       // send vertices in the first part of the buffer
573     glBufferSubData(GL_ARRAY_BUFFER, 0,       sss, g_vertex_buffer_data);
574 
575     // send colors in the second part of the buffer
576     glBufferSubData(GL_ARRAY_BUFFER, sss,     sss, g_vertex_color_data);
577   
578     // send normals in the third part of the buffer
579     glBufferSubData(GL_ARRAY_BUFFER, sss+sss, sss, g_vertex_normal_data);
580 
581     // ici les commandes stockees "une fois pour toute" dans le VAO 
582     glVertexAttribPointer(
583        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
584        3,                  // size
585        GL_FLOAT,           // type
586        GL_FALSE,           // normalized?
587        0,                  // stride
588        (void*)0            // array buffer offset
589     );
590     glEnableVertexAttribArray(0);
591 
592     glVertexAttribPointer( // same thing for the colors
593       1, 
594       3, 
595       GL_FLOAT, 
596       GL_FALSE, 
597       0, 
598       (void*)sss);
599     glEnableVertexAttribArray(1);
600 
601     glVertexAttribPointer( // same thing for the normals
602       2, 
603       3, 
604       GL_FLOAT, 
605       GL_FALSE, 
606       0, 
607       (void*)(sss+sss));
608     glEnableVertexAttribArray(2);
609 
610 
611   glBindBuffer(GL_ARRAY_BUFFER, 0);
612 
613   // on desactive le VAO a la fin de l'initialisation
614   glBindVertexArray (0);
615 
616 
617   // Assure que l'on peut capturer la touche d'échappement enfoncée ci-dessous
618   glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
619 
620   GLuint programID = LoadShaders( "SimpleVertexShader54.vertexshader", "SimpleFragmentShader54.fragmentshader" );
621   uniform_proj     = glGetUniformLocation(programID, "projectionMatrix");
622   uniform_view     = glGetUniformLocation(programID, "viewMatrix");
623   uniform_model    = glGetUniformLocation(programID, "modelMatrix");
624 
625   float angle = -M_PI/2;
626   float elev  = M_PI/6;
627 
628 
629   do{
630     //angle += dangle;
631     elev = M_PI/6 + 0.5*sin(angle)*sin(angle);
632 
633     // recupere la taille effective de la fenetre
634     int width, height;
635     glfwGetWindowSize (window, &width, &height);
636 
637     // re-initialise les tableaux de bits avant un nouvel affichage
638     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
639 
640     // Utilise notre unique shader
641     glUseProgram(programID); 
642 
643     // on change de matrice de projection : la projection orthogonale est plus propice a la visualization !
644     //glm::mat4 projectionMatrix = glm::ortho( -1.0f, 1.0f, -1.0f*height/width, 1.0f*height/width, 0.0f, 2.f );
645     glm::mat4 projectionMatrix = glm::perspective(glm::radians(66.0f), ((float) width) / ((float) height), 0.1f, 4.0f);
646     
647     vec3 vc = vec3(cos(angle)*cos(elev),  sin(angle)*cos(elev), sin(elev));
648     vec3 vt = vec3(-sin(angle)*cos(elev), cos(angle)*cos(elev), 0);
649 
650     glm::mat4 viewMatrix     = glm::lookAt(
651                                 vc, // where is the camara
652                                 //vec3(0.0, 0.0, 2.0),
653                                 vec3(0.0, -0.1, 0.0), //where it looks
654                                 2.0f*normalize(glm::cross(vc, vt)) // head is up
655                               );
656 
657     mat4 modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.9f,  1.9f,  1.9f));
658     modelMatrix      = glm::translate(modelMatrix, glm::vec3(-0.5f, -0.5f, 0.0));
659 
660     glUniformMatrix4fv(uniform_proj,  1, GL_FALSE, glm::value_ptr(projectionMatrix));
661     glUniformMatrix4fv(uniform_view,  1, GL_FALSE, glm::value_ptr(viewMatrix));
662     glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(modelMatrix));
663 
664     // on re-active le VAO avant d'envoyer les buffers
665     glBindVertexArray(VertexArrayID);
666 
667     // dessine les triangle(s) !
668     glDrawArrays(GL_TRIANGLES, 0, sss/(3*sizeof(GLfloat))); // Starting from vertex 0.. all the vertices; 
669 
670     // on desactive le VAO a la fin du dessin
671     glBindVertexArray (0);
672 
673     // on desactive les shaders
674     glUseProgram(0);
675 
676     // echange le buffer visible et invisible
677     glfwSwapBuffers(window);
678     glfwPollEvents();
679 
680     if (glfwGetKey(window, GLFW_KEY_UP ) == GLFW_PRESS){
681       gainAlt = gainAlt*1.5;
682       updateRepr(gainAlt, gainCol);  
683       glBindVertexArray(VertexArrayID);
684       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
685 
686       glBufferSubData(GL_ARRAY_BUFFER, 0,       sss, g_vertex_buffer_data);
687       glBufferSubData(GL_ARRAY_BUFFER, sss,     sss, g_vertex_color_data);
688       glBufferSubData(GL_ARRAY_BUFFER, sss+sss, sss, g_vertex_normal_data);
689 
690       glBindBuffer(GL_ARRAY_BUFFER, 0);
691       glBindVertexArray (0);
692     } else if (glfwGetKey(window, GLFW_KEY_DOWN ) == GLFW_PRESS){
693       gainAlt = gainAlt*0.75;
694       updateRepr(gainAlt, gainCol);  
695       glBindVertexArray(VertexArrayID);
696       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
697 
698       glBufferSubData(GL_ARRAY_BUFFER, 0,       sss, g_vertex_buffer_data);
699       glBufferSubData(GL_ARRAY_BUFFER, sss,     sss, g_vertex_color_data);
700       glBufferSubData(GL_ARRAY_BUFFER, sss+sss, sss, g_vertex_normal_data);
701 
702       glBindBuffer(GL_ARRAY_BUFFER, 0);
703       glBindVertexArray (0);
704     } else if (glfwGetKey(window, GLFW_KEY_LEFT ) == GLFW_PRESS){
705       gainCol = gainCol*0.75;
706       updateRepr(gainAlt, gainCol);  
707       glBindVertexArray(VertexArrayID);
708       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
709 
710       glBufferSubData(GL_ARRAY_BUFFER, 0,       sss, g_vertex_buffer_data);
711       glBufferSubData(GL_ARRAY_BUFFER, sss,     sss, g_vertex_color_data);
712       glBufferSubData(GL_ARRAY_BUFFER, sss+sss, sss, g_vertex_normal_data);
713 
714       glBindBuffer(GL_ARRAY_BUFFER, 0);
715       glBindVertexArray (0);
716     } else if (glfwGetKey(window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
717       gainCol = gainCol*1.5;
718       updateRepr(gainAlt, gainCol);  
719       glBindVertexArray(VertexArrayID);
720       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
721 
722       glBufferSubData(GL_ARRAY_BUFFER, 0,       sss, g_vertex_buffer_data);
723       glBufferSubData(GL_ARRAY_BUFFER, sss,     sss, g_vertex_color_data);
724       glBufferSubData(GL_ARRAY_BUFFER, sss+sss, sss, g_vertex_normal_data);
725       glBindBuffer(GL_ARRAY_BUFFER, 0);
726       glBindVertexArray (0);
727     }
728   } // Vérifie si on a appuyé sur la touche échap (ESC) ou si la fenêtre a été fermée
729   while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
730   glfwWindowShouldClose(window) == 0 );
731 }