1 // sous mac 
  2 // g++ -I/usr/local/include/ -lglfw -lGLEW -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs main7.cpp -framework OpenGL -omain7
  3 // ./main7
  4 
  5 // sous linux   
  6 // g++ -I/usr/local/include/ -I/public/ig/glm/ -c main7.cpp  -omain7.o
  7 // g++ -I/usr/local main7.o -lglfw  -lGLEW  -lGL -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -omain7
  8 // ./main7
  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 using namespace std;
 18 
 19 #include <stdlib.h>
 20 #include <string.h>
 21 
 22 #include <GL/glew.h>
 23 #include <GLFW/glfw3.h>
 24 
 25 #ifdef __APPLE__
 26 #include <OpenGL/gl.h>
 27 #else
 28 #include <GL/gl.h>
 29 #endif
 30 
 31 #include <opencv2/core/core.hpp>
 32 #include <opencv2/highgui/highgui.hpp>
 33 using namespace cv;
 34 
 35 #define GLM_FORCE_RADIANS
 36 #include <glm/glm.hpp>
 37 #include <glm/gtc/matrix_transform.hpp>
 38 #include <glm/gtc/type_ptr.hpp>
 39 
 40 using namespace glm;
 41 
 42 
 43 // Le nombre de donnees
 44 const int N = 12;
 45 
 46 // Maintenant on a 2 VBO avec 2 parties chacun 
 47 long vertexSize1, vertexSize2, colorSize1, texCoordSize2;
 48 
 49 // Les donnees sous forme de pointeur. Il faudra donc faire un malloc
 50 // pour allouer de l'espace avant de mettre des donnees dedans
 51 GLfloat *g_vertex_buffer_data1   = NULL;
 52 GLfloat *g_vertex_color_data1    = NULL;
 53 GLfloat *g_vertex_buffer_data2   = NULL;
 54 GLfloat *g_vertex_texcoord_data2 = NULL;
 55 
 56 // l'angle de rotation de la camera autour du modele
 57 float angleRot = 0.0f;
 58 
 59 // LA fenetre
 60 GLFWwindow* window; 
 61 
 62 // La texture d'alphabet
 63 GLuint texId;
 64 
 65 // la vitesse initiale
 66 float speed = 0.0; 
 67 
 68 // La taille de notre fenetre
 69 int winWidth  = 800;
 70 int winHeight = 400;
 71 
 72 // La taille de notre texture
 73 int texWidth  = -1;
 74 int texHeight = -1;
 75 
 76 // This will identify our vertex buffers (VBOs)
 77 GLuint vertexbuffer1;
 78 GLuint vertexbuffer2;
 79 
 80 // Identifiant de notre VAO
 81 GLuint vertexArrayID1;
 82 GLuint vertexArrayID2;
 83 
 84 // identifiant de nos programmes de shaders
 85 GLuint programID1;
 86 GLuint programID2;
 87 
 88 // stocke les variables uniformes qui seront communes a tous les vertex dessines
 89 GLint uniform_proj1, uniform_view1, uniform_model1, uniform_proj2, uniform_view2, uniform_model2, uniform_texture2;
 90 
 91 
 92 typedef struct Character {
 93   int codePoint, x, y, width, height, originX, originY;
 94 } Character;
 95 
 96 typedef struct Font {
 97   const char *name;
 98   int size, bold, italic, width, height, characterCount;
 99   Character *characters;
100 } Font;
101 
102 // On a recupere tout ca sur le meme site qui a genere la texture des symboles
103 static Character characters_Arial[] = {
104   {' ', 311, 112, 3, 3, 1, 1},
105   {'!', 145, 86, 9, 26, -1, 25},
106   {'"', 212, 112, 16, 12, 0, 25},
107   {'#', 346, 0, 21, 27, 2, 25},
108   {'$', 128, 0, 19, 32, 1, 27},
109   {'%', 173, 0, 29, 27, 0, 25},
110   {'&', 253, 0, 24, 27, 0, 25},
111   {'\'', 228, 112, 8, 12, 0, 25},
112   {'(', 99, 0, 11, 33, 0, 25},
113   {')', 87, 0, 12, 33, 1, 25},
114   {'*', 188, 112, 15, 14, 1, 25},
115   {'+', 131, 112, 19, 19, 0, 21},
116   {',', 203, 112, 9, 13, 0, 6},
117   {'-', 257, 112, 12, 8, 0, 13},
118   {'.', 302, 112, 9, 7, 0, 6},
119   {'/', 264, 33, 13, 27, 2, 25},
120   {'0', 215, 33, 18, 27, 0, 25},
121   {'1', 109, 86, 14, 26, -1, 25},
122   {'2', 0, 86, 19, 26, 1, 25},
123   {'3', 178, 33, 19, 27, 1, 25},
124   {'4', 339, 60, 20, 26, 1, 25},
125   {'5', 159, 33, 19, 27, 0, 25},
126   {'6', 121, 33, 19, 27, 0, 25},
127   {'7', 76, 86, 18, 26, 0, 25},
128   {'8', 197, 33, 18, 27, 0, 25},
129   {'9', 140, 33, 19, 27, 1, 25},
130   {':', 122, 112, 9, 20, -1, 19},
131   {';', 172, 86, 8, 26, -1, 19},
132   {'<', 298, 86, 19, 21, 0, 22},
133   {'=', 169, 112, 19, 15, 0, 19},
134   {'>', 260, 86, 19, 21, 0, 22},
135   {'?', 299, 60, 20, 26, 0, 25},
136   {'@', 0, 0, 34, 33, 1, 25},
137   {'A', 311, 33, 27, 26, 2, 25},
138   {'B', 146, 60, 23, 26, -1, 25},
139   {'C', 300, 0, 23, 27, 0, 25},
140   {'D', 123, 60, 23, 26, -1, 25},
141   {'E', 257, 60, 21, 26, -1, 25},
142   {'F', 38, 86, 19, 26, -1, 25},
143   {'G', 228, 0, 25, 27, 0, 25},
144   {'H', 235, 60, 22, 26, -1, 25},
145   {'I', 163, 86, 9, 26, 0, 25},
146   {'J', 233, 33, 18, 27, 1, 25},
147   {'K', 75, 60, 24, 26, -1, 25},
148   {'L', 319, 60, 20, 26, -1, 25},
149   {'M', 338, 33, 26, 26, 0, 25},
150   {'N', 213, 60, 22, 26, -1, 25},
151   {'O', 202, 0, 26, 27, 0, 25},
152   {'P', 278, 60, 21, 26, -1, 25},
153   {'Q', 147, 0, 26, 29, 0, 25},
154   {'R', 99, 60, 24, 26, -1, 25},
155   {'S', 277, 0, 23, 27, 1, 25},
156   {'T', 191, 60, 22, 26, 1, 25},
157   {'U', 323, 0, 23, 27, 0, 25},
158   {'V', 50, 60, 25, 26, 2, 25},
159   {'W', 277, 33, 34, 26, 2, 25},
160   {'X', 25, 60, 25, 26, 2, 25},
161   {'Y', 0, 60, 25, 26, 2, 25},
162   {'Z', 169, 60, 22, 26, 1, 25},
163   {'[', 63, 0, 12, 33, 0, 25},
164   {'\\', 251, 33, 13, 27, 2, 25},
165   {']', 110, 0, 11, 33, 1, 25},
166   {'^', 150, 112, 19, 16, 0, 25},
167   {'_', 280, 112, 22, 7, 2, -1},
168   {'`', 269, 112, 11, 8, 1, 25},
169   {'a', 221, 86, 20, 21, 1, 19},
170   {'b', 21, 33, 20, 27, 0, 25},
171   {'c', 241, 86, 19, 21, 0, 19},
172   {'d', 81, 33, 20, 27, 0, 25},
173   {'e', 201, 86, 20, 21, 1, 19},
174   {'f', 94, 86, 15, 26, 1, 25},
175   {'g', 61, 33, 20, 27, 0, 19},
176   {'h', 57, 86, 19, 26, 0, 25},
177   {'i', 154, 86, 9, 26, 0, 25},
178   {'j', 75, 0, 12, 33, 3, 25},
179   {'k', 19, 86, 19, 26, 0, 25},
180   {'l', 136, 86, 9, 26, 0, 25},
181   {'m', 0, 112, 28, 20, 0, 19},
182   {'n', 70, 112, 19, 20, 0, 19},
183   {'o', 180, 86, 21, 21, 1, 19},
184   {'p', 41, 33, 20, 27, 0, 19},
185   {'q', 101, 33, 20, 27, 0, 19},
186   {'r', 107, 112, 15, 20, 0, 19},
187   {'s', 317, 86, 19, 21, 1, 19},
188   {'t', 123, 86, 13, 26, 1, 24},
189   {'u', 279, 86, 19, 21, 0, 19},
190   {'v', 28, 112, 21, 20, 2, 19},
191   {'w', 336, 86, 29, 20, 2, 19},
192   {'x', 49, 112, 21, 20, 2, 19},
193   {'y', 0, 33, 21, 27, 2, 19},
194   {'z', 89, 112, 18, 20, 1, 19},
195   {'{', 34, 0, 15, 33, 1, 25},
196   {'|', 121, 0, 7, 33, -1, 25},
197   {'}', 49, 0, 14, 33, 1, 25},
198   {'~', 236, 112, 21, 9, 1, 16},
199 };
200 
201 char characters_ArialIndexes[256];
202 
203 static Font font_Arial = {"Arial", 32, 1, 0, 367, 132, 95, characters_Arial};
204 
205 
206 
207 // Charge une texture et retourne l'identifiant openGL
208 GLuint LoadTexture(string fileName){
209   GLuint tId = -1;
210   // On utilise OpenCV pour charger l'image
211   Mat image = imread(fileName, CV_LOAD_IMAGE_UNCHANGED);
212 
213   // On va utiliser des TEXTURE_RECTANGLE au lieu de classiques TEXTURE_2D
214   // car avec ca les coordonnees de texture s'exprime en pixels  et non en coordoonnes homogenes (0.0...1.0)
215   // En effet la texture est composee de lettres et symbole que nous voudrons extraire... or la position et
216   // taille de ces symboles dans la texture sont connuees en "pixels". Ca sera donc plus facile 
217   glEnable(GL_TEXTURE_RECTANGLE);
218   //comme d'hab on fait generer un numero unique(ID) par OpenGL
219   glGenTextures(1, &tId);
220 
221   texWidth  = image.cols;
222   texHeight = image.rows;
223 
224   glBindTexture(GL_TEXTURE_RECTANGLE, tId);
225     // on envoie les pixels a la carte graphique
226     glTexImage2D(GL_TEXTURE_RECTANGLE, 
227                  0,           // mipmap level => Attention pas de mipmap dans les textures rectangle
228                  GL_RGBA,     // internal color format
229                  image.cols, 
230                  image.rows, 
231                  0,           // border width in pixels
232                  GL_BGRA,     // input file format. Arg le png code les canaux dans l'autre sens
233                  GL_UNSIGNED_BYTE, // image data type
234                  image.ptr());
235     // On peut donner des indication a opengl sur comment la texture sera utilisee 
236     glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
237     glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
238     glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
239     glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
240 
241   // INTERDIT sur les textures rectangle!
242   //glGenerateMipmap(GL_TEXTURE_2D);
243   glBindTexture(GL_TEXTURE_RECTANGLE, 0);
244 
245   return tId;
246 }
247 
248 
249 // Charge un programme de shaders, le compile et recupere dedans des pointeurs vers
250 // les variables homogenes que nous voudront mettre a jour plus tard, a chaque dessin 
251 GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
252 
253   // Create the shaders
254   GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
255   GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
256 
257   // Read the Vertex Shader code from the file
258   string VertexShaderCode;
259   ifstream VertexShaderStream(vertex_file_path, ios::in);
260   if(VertexShaderStream.is_open()){
261     string Line = "";
262     while(getline(VertexShaderStream, Line))
263       VertexShaderCode += "\n" + Line;
264     VertexShaderStream.close();
265   }else{
266     printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
267     getchar();
268     return 0;
269   }
270 
271   // Read the Fragment Shader code from the file
272   string FragmentShaderCode;
273   ifstream FragmentShaderStream(fragment_file_path, ios::in);
274   if(FragmentShaderStream.is_open()){
275     string Line = "";
276     while(getline(FragmentShaderStream, Line))
277       FragmentShaderCode += "\n" + Line;
278     FragmentShaderStream.close();
279   }
280 
281   GLint Result = GL_FALSE;
282   int InfoLogLength;
283 
284 
285   // Compile Vertex Shader
286   printf("Compiling shader : %s\n", vertex_file_path);
287   char const * VertexSourcePointer = VertexShaderCode.c_str();
288   glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
289   glCompileShader(VertexShaderID);
290 
291   // Check Vertex Shader
292   glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
293   glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
294   if ( InfoLogLength > 0 ){
295     vector<char> VertexShaderErrorMessage(InfoLogLength+1);
296     glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
297     printf("%s\n", &VertexShaderErrorMessage[0]);
298   }
299 
300 
301 
302   // Compile Fragment Shader
303   printf("Compiling shader : %s\n", fragment_file_path);
304   char const * FragmentSourcePointer = FragmentShaderCode.c_str();
305   glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
306   glCompileShader(FragmentShaderID);
307 
308   // Check Fragment Shader
309   glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
310   glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
311   if ( InfoLogLength > 0 ){
312     vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
313     glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
314     printf("%s\n", &FragmentShaderErrorMessage[0]);
315   }
316 
317 
318 
319   // Link the program
320   printf("Linking program\n");
321   GLuint progID = glCreateProgram();
322   glAttachShader(progID, VertexShaderID);
323   glAttachShader(progID, FragmentShaderID);
324   glLinkProgram(progID);
325 
326 
327   // Check the program
328   glGetProgramiv(progID, GL_LINK_STATUS, &Result);
329   glGetProgramiv(progID, GL_INFO_LOG_LENGTH, &InfoLogLength);
330   if ( InfoLogLength > 0 ){
331     vector<char> ProgramErrorMessage(InfoLogLength+1);
332     glGetProgramInfoLog(progID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
333     printf("%s\n", &ProgramErrorMessage[0]);
334   }
335 
336   
337   glDetachShader(progID, VertexShaderID);
338   glDetachShader(progID, FragmentShaderID);
339   
340   glDeleteShader(VertexShaderID);
341   glDeleteShader(FragmentShaderID);
342 
343   return progID;
344 }
345 
346 
347 void generateData(){
348   vertexSize1   = 3*3*5*N*sizeof(GLfloat);
349   colorSize1    = 3*3*5*N*sizeof(GLfloat);
350 
351   vertexSize2   = 3*3*4*N*sizeof(GLfloat);
352   texCoordSize2 = 3*2*4*N*sizeof(GLfloat);
353 
354   if (g_vertex_buffer_data1 != NULL)
355     free(g_vertex_buffer_data1);
356 
357   if (g_vertex_color_data1!= NULL)
358     free(g_vertex_color_data1);
359   
360   if (g_vertex_buffer_data2 != NULL)
361     free(g_vertex_buffer_data2);
362 
363   if (g_vertex_texcoord_data2!= NULL)
364     free(g_vertex_texcoord_data2);
365 
366   g_vertex_buffer_data1   = (GLfloat*)malloc(vertexSize1);
367   g_vertex_color_data1    = (GLfloat*)malloc(colorSize1);
368 
369   g_vertex_buffer_data2   = (GLfloat*)malloc(vertexSize2);
370   g_vertex_texcoord_data2 = (GLfloat*)malloc(texCoordSize2);
371 
372   for (int i=0; i<N; i++){
373     int val = rand()%100;
374     char *str = (char *)malloc(4); 
375     sprintf(str, "%02i", val);
376     cout << val<< " ="<< str <<endl;
377     float r = (100+val)/199.0; 
378     g_vertex_buffer_data1[ 0+i*9*5] = 0.0;
379     g_vertex_buffer_data1[ 1+i*9*5] = 0.0;
380     g_vertex_buffer_data1[ 2+i*9*5] = 0.0;
381 
382     g_vertex_buffer_data1[ 3+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
383     g_vertex_buffer_data1[ 4+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
384     g_vertex_buffer_data1[ 5+i*9*5] = r/5.0;
385 
386     g_vertex_buffer_data1[ 6+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
387     g_vertex_buffer_data1[ 7+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
388     g_vertex_buffer_data1[ 8+i*9*5] = r/5.0;
389 
390 
391     g_vertex_buffer_data1[ 9+i*9*5] = 0.0;
392     g_vertex_buffer_data1[10+i*9*5] = 0.0;
393     g_vertex_buffer_data1[11+i*9*5] = 0.0;
394 
395     g_vertex_buffer_data1[12+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
396     g_vertex_buffer_data1[13+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
397     g_vertex_buffer_data1[14+i*9*5] = r/5.0;
398 
399     g_vertex_buffer_data1[15+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
400     g_vertex_buffer_data1[16+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
401     g_vertex_buffer_data1[17+i*9*5] = 0.0;
402 
403 
404     g_vertex_buffer_data1[18+i*9*5] = 0.0;
405     g_vertex_buffer_data1[19+i*9*5] = 0.0;
406     g_vertex_buffer_data1[20+i*9*5] = 0.0;
407 
408     g_vertex_buffer_data1[21+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
409     g_vertex_buffer_data1[22+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
410     g_vertex_buffer_data1[23+i*9*5] = r/5.0;
411 
412     g_vertex_buffer_data1[24+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
413     g_vertex_buffer_data1[25+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
414     g_vertex_buffer_data1[26+i*9*5] = 0.0;    
415 
416 
417     g_vertex_buffer_data1[27+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
418     g_vertex_buffer_data1[28+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
419     g_vertex_buffer_data1[29+i*9*5] = r/5.0;
420 
421     g_vertex_buffer_data1[30+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
422     g_vertex_buffer_data1[31+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
423     g_vertex_buffer_data1[32+i*9*5] = r/5.0;
424 
425     g_vertex_buffer_data1[33+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
426     g_vertex_buffer_data1[34+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
427     g_vertex_buffer_data1[35+i*9*5] = 0.0;    
428 
429     g_vertex_buffer_data1[36+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
430     g_vertex_buffer_data1[37+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
431     g_vertex_buffer_data1[38+i*9*5] = r/5.0;
432 
433     g_vertex_buffer_data1[39+i*9*5] = 0.0+r*cos((2*i+0)*M_PI/(N));
434     g_vertex_buffer_data1[40+i*9*5] = 0.0+r*sin((2*i+0)*M_PI/(N));
435     g_vertex_buffer_data1[41+i*9*5] = 0.0;
436 
437     g_vertex_buffer_data1[42+i*9*5] = 0.0+r*cos((2*i+1.9)*M_PI/(N));
438     g_vertex_buffer_data1[43+i*9*5] = 0.0+r*sin((2*i+1.9)*M_PI/(N));
439     g_vertex_buffer_data1[44+i*9*5] = 0.0;    
440 
441 
442     g_vertex_color_data1[ 0+i*9*5] = 0.0;
443     g_vertex_color_data1[ 1+i*9*5] = 0.0;
444     g_vertex_color_data1[ 2+i*9*5] = 1.0;
445 
446     g_vertex_color_data1[ 3+i*9*5] = 0.5;
447     g_vertex_color_data1[ 4+i*9*5] = 0.0;
448     g_vertex_color_data1[ 5+i*9*5] = 0.0;
449 
450     g_vertex_color_data1[ 6+i*9*5] = 1.0;
451     g_vertex_color_data1[ 7+i*9*5] = 0.0;
452     g_vertex_color_data1[ 8+i*9*5] = 0.0;
453 
454     g_vertex_color_data1[ 9+i*9*5] = 0.5;
455     g_vertex_color_data1[10+i*9*5] = 0.0;
456     g_vertex_color_data1[11+i*9*5] = 1.0;
457 
458     g_vertex_color_data1[12+i*9*5] = 0.5;
459     g_vertex_color_data1[13+i*9*5] = 0.0;
460     g_vertex_color_data1[14+i*9*5] = 0.0;
461 
462     g_vertex_color_data1[15+i*9*5] = 0.5;
463     g_vertex_color_data1[16+i*9*5] = 0.0;
464     g_vertex_color_data1[17+i*9*5] = 0.0;    
465 
466     g_vertex_color_data1[18+i*9*5] = 1.0;
467     g_vertex_color_data1[19+i*9*5] = 0.0;
468     g_vertex_color_data1[20+i*9*5] = 1.0;
469 
470     g_vertex_color_data1[21+i*9*5] = 1.0;
471     g_vertex_color_data1[22+i*9*5] = 0.0;
472     g_vertex_color_data1[23+i*9*5] = 0.0;
473 
474     g_vertex_color_data1[24+i*9*5] = 1.0;
475     g_vertex_color_data1[25+i*9*5] = 0.0;
476     g_vertex_color_data1[26+i*9*5] = 0.0;    
477 
478     g_vertex_color_data1[27+i*9*5] = 1.0;
479     g_vertex_color_data1[28+i*9*5] = 0.0;
480     g_vertex_color_data1[29+i*9*5] = 0.0;    
481 
482     g_vertex_color_data1[30+i*9*5] = 0.5;
483     g_vertex_color_data1[31+i*9*5] = 0.0;
484     g_vertex_color_data1[32+i*9*5] = 0.0;
485 
486     g_vertex_color_data1[33+i*9*5] = 1.0;
487     g_vertex_color_data1[34+i*9*5] = 0.0;
488     g_vertex_color_data1[35+i*9*5] = 0.0;  
489 
490     g_vertex_color_data1[36+i*9*5] = 0.5;
491     g_vertex_color_data1[37+i*9*5] = 0.0;
492     g_vertex_color_data1[38+i*9*5] = 0.0;    
493 
494     g_vertex_color_data1[39+i*9*5] = 0.5;
495     g_vertex_color_data1[40+i*9*5] = 0.0;
496     g_vertex_color_data1[41+i*9*5] = 0.0;
497 
498     g_vertex_color_data1[42+i*9*5] = 1.0;
499     g_vertex_color_data1[43+i*9*5] = 0.0;
500     g_vertex_color_data1[44+i*9*5] = 0.0;  
501 
502     g_vertex_buffer_data2[0+i*9*4] = 0.0+r*cos((2*i+1.45)*M_PI/(N));
503     g_vertex_buffer_data2[1+i*9*4] = 0.0+r*sin((2*i+1.45)*M_PI/(N));
504     g_vertex_buffer_data2[2+i*9*4] = 3*r/20.0;
505 
506     g_vertex_buffer_data2[3+i*9*4] = 0.0+r*cos((2*i+1.0)*M_PI/(N));
507     g_vertex_buffer_data2[4+i*9*4] = 0.0+r*sin((2*i+1.0)*M_PI/(N));
508     g_vertex_buffer_data2[5+i*9*4] = 3*r/20.0;
509 
510     g_vertex_buffer_data2[6+i*9*4] = 0.0+r*cos((2*i+1.45)*M_PI/(N));
511     g_vertex_buffer_data2[7+i*9*4] = 0.0+r*sin((2*i+1.45)*M_PI/(N));
512     g_vertex_buffer_data2[8+i*9*4] = 1*r/20.0;    
513 
514     g_vertex_buffer_data2[9+i*9*4] = 0.0+r*cos((2*i+1.0)*M_PI/(N));
515     g_vertex_buffer_data2[10+i*9*4] = 0.0+r*sin((2*i+1.0)*M_PI/(N));
516     g_vertex_buffer_data2[11+i*9*4] = 3*r/20.0;
517 
518     g_vertex_buffer_data2[12+i*9*4] = 0.0+r*cos((2*i+1.0)*M_PI/(N));
519     g_vertex_buffer_data2[13+i*9*4] = 0.0+r*sin((2*i+1.0)*M_PI/(N));
520     g_vertex_buffer_data2[14+i*9*4] = 1*r/20.0;  ;
521 
522     g_vertex_buffer_data2[15+i*9*4] = 0.0+r*cos((2*i+1.45)*M_PI/(N));
523     g_vertex_buffer_data2[16+i*9*4] = 0.0+r*sin((2*i+1.45)*M_PI/(N));
524     g_vertex_buffer_data2[17+i*9*4] = 1*r/20.0;  ;
525 
526 
527     g_vertex_buffer_data2[18+i*9*4] = 0.0+r*cos((2*i+1.00)*M_PI/(N));
528     g_vertex_buffer_data2[19+i*9*4] = 0.0+r*sin((2*i+1.00)*M_PI/(N));
529     g_vertex_buffer_data2[20+i*9*4] = 3*r/20.0;
530 
531     g_vertex_buffer_data2[21+i*9*4] = 0.0+r*cos((2*i+0.5)*M_PI/(N));
532     g_vertex_buffer_data2[22+i*9*4] = 0.0+r*sin((2*i+0.5)*M_PI/(N));
533     g_vertex_buffer_data2[23+i*9*4] = 3*r/20.0;
534 
535     g_vertex_buffer_data2[24+i*9*4] = 0.0+r*cos((2*i+1.00)*M_PI/(N));
536     g_vertex_buffer_data2[25+i*9*4] = 0.0+r*sin((2*i+1.00)*M_PI/(N));
537     g_vertex_buffer_data2[26+i*9*4] = 1*r/20.0;    
538 
539     g_vertex_buffer_data2[27+i*9*4] = 0.0+r*cos((2*i+0.5)*M_PI/(N));
540     g_vertex_buffer_data2[28+i*9*4] = 0.0+r*sin((2*i+0.5)*M_PI/(N));
541     g_vertex_buffer_data2[29+i*9*4] = 3*r/20.0;
542 
543     g_vertex_buffer_data2[30+i*9*4] = 0.0+r*cos((2*i+0.5)*M_PI/(N));
544     g_vertex_buffer_data2[31+i*9*4] = 0.0+r*sin((2*i+0.5)*M_PI/(N));
545     g_vertex_buffer_data2[32+i*9*4] = 1*r/20.0;  ;
546 
547     g_vertex_buffer_data2[33+i*9*4] = 0.0+r*cos((2*i+1.00)*M_PI/(N));
548     g_vertex_buffer_data2[34+i*9*4] = 0.0+r*sin((2*i+1.00)*M_PI/(N));
549     g_vertex_buffer_data2[35+i*9*4] = 1*r/20.0;
550 
551 
552     
553 
554     // on doit maintenant generer des coordonnees de texture pour chaque vertex. 
555     // plutot que d'afficher toute la texture on affiche que la sous partie qui correspond au 2ieme symbole
556     char symbol = str[0];
557     char index  = characters_ArialIndexes[symbol]; 
558 
559     g_vertex_texcoord_data2[0+i*6*4] = characters_Arial[index].x+1;
560     g_vertex_texcoord_data2[1+i*6*4] = characters_Arial[index].y+1;
561 
562     g_vertex_texcoord_data2[2+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
563     g_vertex_texcoord_data2[3+i*6*4] = characters_Arial[index].y+1;
564 
565     g_vertex_texcoord_data2[4+i*6*4] = characters_Arial[index].x+1;
566     g_vertex_texcoord_data2[5+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
567 
568     g_vertex_texcoord_data2[6+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
569     g_vertex_texcoord_data2[7+i*6*4] = characters_Arial[index].y+1;
570 
571     g_vertex_texcoord_data2[8+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
572     g_vertex_texcoord_data2[9+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
573 
574     g_vertex_texcoord_data2[10+i*6*4] = characters_Arial[index].x+1;
575     g_vertex_texcoord_data2[11+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
576 
577 
578     symbol = str[1];
579     index  = characters_ArialIndexes[symbol]; 
580 
581     g_vertex_texcoord_data2[12+i*6*4] = characters_Arial[index].x+1;
582     g_vertex_texcoord_data2[13+i*6*4] = characters_Arial[index].y+1;
583 
584     g_vertex_texcoord_data2[14+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
585     g_vertex_texcoord_data2[15+i*6*4] = characters_Arial[index].y+1;
586 
587     g_vertex_texcoord_data2[16+i*6*4] = characters_Arial[index].x+1;
588     g_vertex_texcoord_data2[17+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
589 
590     g_vertex_texcoord_data2[18+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
591     g_vertex_texcoord_data2[19+i*6*4] = characters_Arial[index].y+1;
592 
593     g_vertex_texcoord_data2[20+i*6*4] = characters_Arial[index].x+1+characters_Arial[20].width-2;
594     g_vertex_texcoord_data2[21+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
595 
596     g_vertex_texcoord_data2[22+i*6*4] = characters_Arial[index].x+1;
597     g_vertex_texcoord_data2[23+i*6*4] = characters_Arial[index].y+1+characters_Arial[20].height-2;
598   }
599 }
600 
601 
602 void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
603 {
604     // on teste si la touche E est pressee et si c'est le cas on re-genere des donnees
605     if (key== GLFW_KEY_E && action == GLFW_PRESS){
606       
607       generateData();
608       // ici on n'envoie que les sommets car on souhaite garder les memes couleurs ... et le nombre
609       // n'a pas change !
610       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer1);
611       glBufferSubData(GL_ARRAY_BUFFER, 0,                            vertexSize1, g_vertex_buffer_data1);
612       glBindBuffer(GL_ARRAY_BUFFER, 0);
613       glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
614       glBufferSubData(GL_ARRAY_BUFFER, 0,                            vertexSize2, g_vertex_buffer_data2);
615       glBindBuffer(GL_ARRAY_BUFFER, 0);
616     } else if (key== GLFW_KEY_LEFT && action == GLFW_PRESS ){
617       speed = speed - 1.0/256.0;
618     } else if (key== GLFW_KEY_RIGHT && action == GLFW_PRESS){
619       speed = speed + 1.0/256.0;
620     } else if ((key== GLFW_KEY_UP || key== GLFW_KEY_DOWN) && action == GLFW_PRESS){
621       speed = 0.0;
622     } 
623 
624 }
625 
626 
627 void initOpenGL(){
628   // Enable depth test
629   glEnable(GL_DEPTH_TEST);
630   // Accept fragment if it closer to the camera than the former one
631   glDepthFunc(GL_LESS);
632   glDepthRange(-1, 1);
633 
634   // car maintenant on va appliquer une texture transparente par dessus un quad colore
635   // (avant on pouvait faire le melange nous meme dans le fragment shader car tout etait
636   // faitdans un meme shader)
637   glEnable(GL_BLEND);
638   glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
639   glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
640 
641   // creation du glVertexAttribPointer
642   glGenVertexArrays(1, &vertexArrayID1);
643   glGenVertexArrays(2, &vertexArrayID2);
644 
645   // Generate 2 buffers, put the resulting identifier in vertexbuffer
646   glGenBuffers(1, &vertexbuffer1);
647   glGenBuffers(1, &vertexbuffer2);
648 
649   glBindVertexArray(vertexArrayID1);
650 
651   // The following commands will talk about our 'vertexbuffer' buffer
652   glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer1);
653     // Only allocqte memory. Do not send yet our vertices to OpenGL.
654     glBufferData(GL_ARRAY_BUFFER, vertexSize1+colorSize1, 0, GL_STATIC_DRAW);
655 
656     // send vertices in the first part of the buffer
657     glBufferSubData(GL_ARRAY_BUFFER, 0,                            vertexSize1, g_vertex_buffer_data1);
658 
659     // send colors in the second part of the buffer
660     glBufferSubData(GL_ARRAY_BUFFER, vertexSize1, colorSize1, g_vertex_color_data1);
661   
662     // ici les commandes stockees "une fois pour toute" dans le VAO 
663     // avant on faisait ca a chaque dessin
664     glVertexAttribPointer(
665        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
666        3,                  // size
667        GL_FLOAT,           // type
668        GL_FALSE,           // normalized?
669        0,                  // stride
670        (void*)0            // array buffer offset
671     );
672     glEnableVertexAttribArray(0);
673 
674     glVertexAttribPointer( // same thing for the colors
675       1, 
676       3, 
677       GL_FLOAT, 
678       GL_FALSE, 
679       0, 
680       (void*)vertexSize1);
681     glEnableVertexAttribArray(1);
682 
683   glBindVertexArray(vertexArrayID2);
684   glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
685 
686     // Only allocqte memory. Do not send yet our vertices to OpenGL.
687     glBufferData(GL_ARRAY_BUFFER, vertexSize2+texCoordSize2, 0, GL_STATIC_DRAW);
688 
689       // send vertices in the first part of the buffer
690     glBufferSubData(GL_ARRAY_BUFFER, 0,                            vertexSize2, g_vertex_buffer_data2);
691 
692     // send tex coords in the second part of the buffer
693     glBufferSubData(GL_ARRAY_BUFFER, vertexSize2, texCoordSize2, g_vertex_texcoord_data2);
694   
695     // ici les commandes stockees "une fois pour toute" dans le VAO 
696     // avant on faisait ca a chaque dessin
697     glVertexAttribPointer(
698        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
699        3,                  // size
700        GL_FLOAT,           // type
701        GL_FALSE,           // normalized?
702        0,                  // stride
703        (void*)0            // array buffer offset
704     );
705     glEnableVertexAttribArray(0);
706 
707     glVertexAttribPointer(
708       1, 
709       2, 
710       GL_FLOAT, 
711       GL_FALSE, 
712       0, 
713       (void*)(vertexSize2));
714     glEnableVertexAttribArray(1);
715 
716   glBindBuffer(GL_ARRAY_BUFFER, 0);
717 
718   // on desactive le VAO a la fin de l'initialisation
719   glBindVertexArray (0);
720 }
721 
722 
723 GLFWwindow *initMainwindow(){
724   // Nous allons apprendre a lire une texture de "symboles" generee a partir d'un outil comme :
725   // https://evanw.github.io/font-texture-generator/
726 
727   glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
728   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // On veut OpenGL 3.3
729   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
730   glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Pour rendre MacOS heureux ; ne devrait pas être nécessaire
731   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // On ne veut pas l'ancien OpenGL
732   glfwWindowHint(GLFW_DEPTH_BITS, 24);
733 
734   // Ouvre une fenêtre et crée son contexte OpenGl
735   GLFWwindow *win = glfwCreateWindow( winWidth, winHeight, "Main 07", NULL, NULL);
736   if( win == NULL ){
737       fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are maybe not 3.3 compatible. \n" );
738       glfwTerminate();
739   }
740 
741   // 
742   glfwMakeContextCurrent(win); 
743   
744   // Assure que l'on peut capturer la touche d'échappement 
745   glfwSetInputMode(win, GLFW_STICKY_KEYS, GL_TRUE);
746 
747   // active une callback = une fonction appellee automatiquement quand un evenement arrive 
748   glfwSetKeyCallback(win, key_callback);
749 
750   return win;
751 }
752 
753 
754 void draw(){
755   angleRot = (angleRot+M_PI*speed);
756 
757   // clear before every draw 
758   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
759 
760   //  matrice de projection proportionelle a la taille de la fenetre
761   mat4 projectionMatrix = ortho( -1.0f, 1.0f, -1.0f*winHeight/winWidth, 1.0f*winHeight/winWidth, -3.f, 3.f );
762   mat4 viewMatrix       = lookAt(
763                                 vec3(1.5*cos(angleRot), 1.5*sin(angleRot), -0.35), // where is the camara
764                                 vec3(0, 0, 0.1), //where it looks
765                                 vec3(0, 0, 1.0) // head is up
766                               );
767   mat4 modelMatrix      = mat4(1.0);
768   
769   // Use our shader
770   glUseProgram(programID1); 
771 
772     glUniformMatrix4fv(uniform_proj1,  1, GL_FALSE, value_ptr(projectionMatrix));
773     glUniformMatrix4fv(uniform_view1,  1, GL_FALSE, value_ptr(viewMatrix));
774     glUniformMatrix4fv(uniform_model1, 1, GL_FALSE, value_ptr(modelMatrix));
775 
776     // on re-active le VAO avant d'envoyer les buffers
777     glBindVertexArray(vertexArrayID1);
778 
779     // Draw the triangle(s) !
780     glDrawArrays(GL_TRIANGLES, 0, vertexSize1/(3*sizeof(float))); 
781     
782     // on desactive le VAO a la fin du dessin
783     glBindVertexArray (0);
784 
785   // Use our second shader
786   glUseProgram(programID2); 
787 
788     glUniformMatrix4fv(uniform_proj2,  1, GL_FALSE, value_ptr(projectionMatrix));
789     glUniformMatrix4fv(uniform_view2,  1, GL_FALSE, value_ptr(viewMatrix));
790     glUniformMatrix4fv(uniform_model2, 1, GL_FALSE, value_ptr(modelMatrix));
791 
792     // La texture aussi est donnee en variable uniforme. On lui donne le No 0
793     glUniform1i(uniform_texture2, 0);
794 
795     // on re-active le VAO avant d'envoyer les buffers
796     glBindVertexArray(vertexArrayID2);
797 
798     // On active la texture 0
799     glActiveTexture(GL_TEXTURE0);
800 
801     // Verrouillage de la texture
802     glBindTexture(GL_TEXTURE_RECTANGLE, texId);
803 
804     // Draw the triangle(s) !
805     glDrawArrays(GL_TRIANGLES, 0, vertexSize2/(3*sizeof(float))); 
806     
807     // Déverrouillage de la texture
808     glBindTexture(GL_TEXTURE_RECTANGLE, 0);
809 
810     // on desactive le VAO a la fin du dessin
811     glBindVertexArray (0);
812 
813   // on desactive les shaders
814   glUseProgram(0);
815 
816   // Swap buffers
817   glfwSwapBuffers(window);
818   glfwPollEvents();
819 }
820 
821 
822 int main(){
823   // Probleme, le tableau des symboles (avec leurs positions et tailles dans la texture) ne permet pas de
824   // facilement trouver les infos correspondantes a un symbole donne (par exemple ou est le symbole 4 dans la texture)
825   // Pour eviter de faire une boucle et cherche les symboles un par un on stocke dans un grand tableau (<256 :-)
826   // ou se trouve les infos de chaque symbole de la table ASCII (256 symboles max !)
827   for (int i=0 ; i< sizeof(characters_Arial)/sizeof(characters_Arial[0]); i++){
828     Character c0 = characters_Arial[i];
829     char index = c0.codePoint;
830     characters_ArialIndexes[index] = i;
831   }
832   cout << "indice du caractere '4' dans le tableau des "<< (sizeof(characters_Arial)/sizeof(characters_Arial[0])) <<"symboles : " << (int)characters_ArialIndexes['4']<<endl;
833 
834   // Initialise GLFW
835   if( !glfwInit() ) {
836       fprintf( stderr, "Failed to initialize GLFW\n" );
837       return -1;
838   }
839 
840   window = initMainwindow();
841   
842   // Initialise GLEW
843   glewExperimental=true; // Nécessaire dans le profil de base
844   if (glewInit() != GLEW_OK) {
845       fprintf(stderr, "Failed to initialize GLEW\n");
846       return -1;
847   }
848   
849   generateData();
850 
851   initOpenGL();
852 
853   texId = LoadTexture("font.png");
854 
855 
856   programID1 = LoadShaders( "SimpleVertexShader71.vertexshader", "SimpleFragmentShader71.fragmentshader" );
857   uniform_proj1    = glGetUniformLocation(programID1, "projectionMatrix");
858   uniform_view1    = glGetUniformLocation(programID1, "viewMatrix");
859   uniform_model1   = glGetUniformLocation(programID1, "modelMatrix");
860   programID2 = LoadShaders( "SimpleVertexShader72.vertexshader", "SimpleFragmentShader72.fragmentshader" );
861   uniform_proj2    = glGetUniformLocation(programID2, "projectionMatrix");
862   uniform_view2    = glGetUniformLocation(programID2, "viewMatrix");
863   uniform_model2   = glGetUniformLocation(programID2, "modelMatrix");
864   uniform_texture2 = glGetUniformLocation(programID2, "loctexture");
865   cout <<uniform_texture2<<endl;
866 
867   double before = glfwGetTime();
868   int cpt = 0;
869   do{
870     draw();
871     cpt++;
872 
873     // On a fait 100 dessins, il est temps de voir combien de temps cela a pris
874     // et quel est le taux de raffraichissement 
875     if (cpt==100) {
876       double after = glfwGetTime();
877       cout << 100.0/(after-before) << "Hz"<<endl;
878       before = after;
879       cpt=0;
880     }
881   } // Vérifie si on a appuyé sur la touche échap (ESC) ou si la fenêtre a été fermée
882   while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 );
883 }