SceneOpenGL.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #include "SceneOpenGL.h"
  2. // Permet d'éviter la ré-écriture du namespace glm::
  3. using namespace glm;
  4. // Constructeur de Destucteur
  5. SceneOpenGL::SceneOpenGL(std::string titreFenetre, int largeurFenetre, int hauteurFenetre)
  6. : m_titreFenetre(titreFenetre), m_largeurFenetre(largeurFenetre),
  7. m_hauteurFenetre(hauteurFenetre), m_fenetre(0), m_contexteOpenGL(0),
  8. m_input(), m_texturLoader( "Textures/" ),
  9. m_shader( "Shaders/texture.vert", "Shaders/texture.frag" ),
  10. m_shLight( "Shaders/light.vert", "Shaders/light.frag" ),
  11. m_shGris( "Shaders/texture.vert", "Shaders/gris.frag" )
  12. {
  13. }
  14. SceneOpenGL::~SceneOpenGL()
  15. {
  16. SDL_GL_DeleteContext(m_contexteOpenGL);
  17. SDL_DestroyWindow(m_fenetre);
  18. SDL_Quit();
  19. }
  20. // Méthodes
  21. bool SceneOpenGL::initialiserFenetre()
  22. {
  23. // Initialisation de la SDL
  24. if(SDL_Init(SDL_INIT_VIDEO) < 0)
  25. {
  26. std::cout << "Erreur lors de l'initialisation de la SDL : " << SDL_GetError() << std::endl;
  27. SDL_Quit();
  28. return false;
  29. }
  30. #ifdef __APPLE__
  31. // Version d'OpenGL
  32. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  33. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
  34. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  35. // Récupération du Bundle
  36. CFURLRef URLBundle = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
  37. char *cheminResources = new char[PATH_MAX];
  38. // Changement du 'Working Directory'
  39. if(CFURLGetFileSystemRepresentation(URLBundle, 1, (UInt8*)cheminResources, PATH_MAX))
  40. chdir(cheminResources);
  41. // Libération de la mémoire
  42. delete[] cheminResources;
  43. CFRelease(URLBundle);
  44. #else
  45. // Version d'OpenGL
  46. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  47. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
  48. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  49. #endif
  50. // Création de la fenêtre
  51. uint32_t flag( SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL );
  52. m_fenetre = SDL_CreateWindow(m_titreFenetre.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_largeurFenetre, m_hauteurFenetre, flag);
  53. if(m_fenetre == 0)
  54. {
  55. std::cout << "Erreur lors de la creation de la fenetre : " << SDL_GetError() << std::endl;
  56. SDL_Quit();
  57. return false;
  58. }
  59. // Paramètres des évènements
  60. m_input.setWindow( m_fenetre );
  61. m_input.capturerPointeur( true );
  62. m_input.setMoveKeys( SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_D, SDL_SCANCODE_A );
  63. // Création du contexte OpenGL
  64. m_contexteOpenGL = SDL_GL_CreateContext(m_fenetre);
  65. if(m_contexteOpenGL == 0)
  66. {
  67. std::cout << SDL_GetError() << std::endl;
  68. SDL_DestroyWindow(m_fenetre);
  69. SDL_Quit();
  70. return false;
  71. }
  72. return true;
  73. }
  74. bool SceneOpenGL::initGL()
  75. {
  76. #ifdef WIN32
  77. // On initialise GLEW
  78. GLenum initialisationGLEW( glewInit() );
  79. // Si l'initialisation a échoué :
  80. if(initialisationGLEW != GLEW_OK)
  81. {
  82. // On affiche l'erreur grâce à la fonction : glewGetErrorString(GLenum code)
  83. std::cout << "Erreur d'initialisation de GLEW : " << glewGetErrorString(initialisationGLEW) << std::endl;
  84. // On quitte la SDL
  85. SDL_GL_DeleteContext(m_contexteOpenGL);
  86. SDL_DestroyWindow(m_fenetre);
  87. SDL_Quit();
  88. return false;
  89. }
  90. #endif
  91. // Paramètres OpenGL avancés
  92. glEnable(GL_DEPTH_TEST);
  93. glEnable(GL_CULL_FACE);
  94. // Tout s'est bien passé, on retourne true
  95. return true;
  96. }
  97. void SceneOpenGL::bouclePrincipale()
  98. {
  99. // Variables temps
  100. unsigned int frameRate (1000 / 50);
  101. Uint32 debutBoucle(0), finBoucle(0), tempsEcoule(0);
  102. // Frame Buffer
  103. FrameBuffer frameBuffer(512, 512);
  104. frameBuffer.charger();
  105. m_texturLoader.addTextur("FBO_Tele", frameBuffer.getColorBuffer(0));
  106. // Shaders
  107. m_shader.charger();
  108. m_shLight.charger();
  109. m_shGris.charger();
  110. Shader* shTarget(0x0);
  111. // Matrices (première passe)
  112. mat4 projectionFBO;
  113. projectionFBO = perspective(70.0, (double)frameBuffer.getLargeur() / frameBuffer.getHauteur(), 1.0, 100.0);
  114. // Matrices (seconde passe)
  115. mat4 projection, projection30, projection70, plat;
  116. mat4 view, unicite(1.0);
  117. const float format( (float) m_largeurFenetre / m_hauteurFenetre );
  118. projection70 = perspective(70.0, (double)format, 0.1, 100.0);
  119. projection30 = perspective(30.0, (double)format, 0.1, 100.0);
  120. const float plat_extY( 30.0 );
  121. const float plat_extX( plat_extY * format );
  122. plat = ortho(-plat_extX, plat_extX, -plat_extY, plat_extY, 0.1f, 100.0f);
  123. // Vecteurs
  124. uint16_t nbLight(3);
  125. vec3 posLight[nbLight];
  126. posLight[0] = vec3( 10.0, 3.0, 0.0 );
  127. posLight[2] = vec3( 30.0, 3.5, 0.0 );
  128. float posLightV[nbLight*3];
  129. // Caméra mobile
  130. Camera camera(vec3(0, 1.78, 0), vec3(0, 1.78, -1), vec3(0, 1, 0), 0.5, 0.5);
  131. vec3 eyePos;
  132. m_input.afficherPointeur(false);
  133. m_input.capturerPointeur(true);
  134. // Objet Caisse
  135. OBJ metal;
  136. metal.charger("3DModels/kube.obj", m_texturLoader.take("caisse_basic"));
  137. mat4 model_metal(1.0);
  138. OBJ plan;
  139. plan.charger( "3DModels/plan.obj", m_texturLoader.take("pierres"), 50.0, 20.0);
  140. mat4 model_plan(1.0);
  141. model_plan = translate(model_plan, vec3(2.5,0.0,0.0));
  142. OBJ tele;
  143. tele.charger( "3DModels/plan.obj", m_texturLoader.take("FBO_Tele"), 2.5 );
  144. mat4 model_tele(1.0);
  145. model_tele = translate( model_tele, vec3(16.56,3.2,-0.5) );
  146. model_tele = rotate(model_tele, 90.0f, vec3(0, 0, 1));
  147. OBJ caisse;
  148. caisse.charger("3DModels/kube.obj", m_texturLoader.take("chantier"));
  149. mat4 model_caisseA(1.0),model_caisseB(1.0),model_caisseC(1.0);
  150. model_caisseA = translate( model_caisseA, vec3(-6.56,1.0,-0.5) );
  151. model_caisseB = translate( model_caisseB, vec3(6.56,1.0,4.5) );
  152. model_caisseC = translate( model_caisseC, vec3(3.5,1.0,3.5) );
  153. OBJ weapon;
  154. weapon.charger( "3DModels/MPX.obj", m_texturLoader.take("chantier"), 0.2 );
  155. mat4 model_weapon(1.0);
  156. Mosaic sword;
  157. sword.charger( "2DModels/sword_iron.bmp" );
  158. mat4 model_sword(1.0);
  159. float angle = 0.0;
  160. float theta, theta_old = 0.0;
  161. float phi, phi_old = 0.0;
  162. bool rangee(true), rangement(false), veutRanger(false);
  163. bool veutViser(false);
  164. bool veutTemporiser(false);
  165. bool veutLight(false), lightDone(false), lightState(false);
  166. bool veutOverLight(false), overLightDone(false); GLint overLightState(false);
  167. // Boucle principale
  168. while(!m_input.terminer())
  169. {
  170. // On définit le temps de début de boucle
  171. debutBoucle = SDL_GetTicks();
  172. // Gestion des évènements
  173. m_input.updateEvenements();
  174. camera.setVol( m_input.getTouche( SDL_SCANCODE_LSHIFT ) );
  175. if (m_input.getTouche(SDL_SCANCODE_ESCAPE))
  176. break;
  177. if (m_input.getTouche(SDL_SCANCODE_KP_3)) nbLight = 3;
  178. if (m_input.getTouche(SDL_SCANCODE_KP_2)) nbLight = 2;
  179. if (m_input.getTouche(SDL_SCANCODE_KP_1)) nbLight = 1;
  180. if (m_input.getTouche(SDL_SCANCODE_KP_0)) nbLight = 0;
  181. camera.deplacer(m_input);
  182. veutRanger = m_input.getTouche(SDL_SCANCODE_E) || m_input.getBoutonPad(1);
  183. if ( !rangement && veutRanger ) {
  184. rangement = true;
  185. rangee = !rangee;
  186. if ( rangee ) camera.setVitesse(0.5f);
  187. else camera.setVitesse(0.2f);
  188. }
  189. else if ( !veutRanger ) rangement = false;
  190. veutTemporiser = m_input.getTouche( SDL_SCANCODE_SPACE ) || m_input.getBoutonPad(2);
  191. veutViser = m_input.getBoutonSouris(3) || m_input.getBoutonPad(4);
  192. veutLight = m_input.getTouche( SDL_SCANCODE_LCTRL ) || m_input.getBoutonPad(3);
  193. if ( !lightDone && veutLight ) {
  194. lightDone = true;
  195. lightState = !lightState;
  196. }
  197. else if ( !veutLight ) lightDone = false;
  198. veutOverLight = m_input.getTouche( SDL_SCANCODE_Q ) || m_input.getBoutonPad(0);
  199. if ( !overLightDone && veutOverLight ) {
  200. overLightDone = true;
  201. overLightState = !overLightState;
  202. }
  203. else if ( !veutOverLight ) overLightDone = false;
  204. /* ***** Première Passe ***** */
  205. // Verrouillage du Frame Buffer
  206. glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.getID());
  207. // Nettoyage de l'écran
  208. glClearColor(0.2, 0.2, 0.25, 1.0);
  209. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  210. // Redimensionnement de la zone d'affichage
  211. glViewport(0, 0, frameBuffer.getLargeur(), frameBuffer.getHauteur());
  212. // Placement de la caméra
  213. view = lookAt(vec3(0, 0, 3), vec3(0, 0, 0), vec3(0, 1, 0));
  214. // Gestion de la rotation de la caisse
  215. if ( veutTemporiser )
  216. angle = 0.05f;
  217. else
  218. angle = 2.0f;
  219. // Activation du shader
  220. glUseProgram( m_shGris.getProgramID() );
  221. // Affichage de la caisse
  222. model_metal = rotate(model_metal, angle, vec3(0, 1, 0));
  223. metal.afficher(projectionFBO*view*model_metal, model_metal, &m_shGris);
  224. // Désactivation du shader
  225. glUseProgram( 0 );
  226. // Déverrouillage du Frame Buffer
  227. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  228. /* ***** Seconde Passe ***** */
  229. // Nettoyage de l'écran
  230. glClearColor(0.0, 0.0, 0.0, 1.0);
  231. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  232. // Redimensionnement de la zone d'affichage
  233. glViewport(0, 0, m_largeurFenetre, m_hauteurFenetre);
  234. // Gestion de la caméra
  235. camera.lookAt(view);
  236. if ( veutViser ) projection = projection30;
  237. else if ( m_input.getTouche( SDL_SCANCODE_X ) ) projection = plat;
  238. else projection = projection70;
  239. // Gestion de la lumière
  240. posLight[1] = camera.getPos() + vec3(0.0, 1.2, 0.0);
  241. posLight[2] = rotateY( posLight[2], angle );
  242. uint16_t j;
  243. for ( uint16_t i(0); i<nbLight; i++ )
  244. {
  245. j = i * 3;
  246. posLightV[j] = posLight[i].x;
  247. posLightV[j+1] = posLight[i].y;
  248. posLightV[j+2] = posLight[i].z;
  249. }
  250. // Activation du shader
  251. if ( lightState )
  252. {
  253. eyePos = camera.getPos();
  254. shTarget = &m_shLight;
  255. }
  256. else
  257. shTarget = &m_shader;
  258. glUseProgram( shTarget->getProgramID() );
  259. if ( lightState )
  260. {
  261. glUniform3f(glGetUniformLocation(m_shLight.getProgramID(), "eyePos"), eyePos.x, eyePos.y, eyePos.z);
  262. glUniform3fv(glGetUniformLocation(m_shLight.getProgramID(), "posLight"), nbLight, posLightV);
  263. glUniform1i(glGetUniformLocation(m_shLight.getProgramID(), "overLight"), overLightState);
  264. glUniform1i(glGetUniformLocation(m_shLight.getProgramID(), "nbLight"), (int)nbLight);
  265. }
  266. // Afficher le plan
  267. plan.afficher(projection * view * model_plan, model_plan, shTarget);
  268. // Afficher la télé
  269. tele.afficher(projection * view * model_tele, model_tele, shTarget);
  270. // Affichage de la caisse
  271. model_caisseA = rotate(model_caisseA, angle, vec3(0, 1, 0));
  272. weapon.afficher(projection * view * model_caisseA, model_caisseA, shTarget);
  273. caisse.afficher(projection * view * model_caisseB, model_caisseB, shTarget);
  274. caisse.afficher(projection * view * model_caisseC, model_caisseC, shTarget);
  275. // Affichage de l'arme
  276. if ( rangee ) {
  277. theta = camera.getTheta() + 180;
  278. phi = 90;
  279. }
  280. else {
  281. theta = camera.getTheta();
  282. phi = camera.getPhi();
  283. }
  284. theta_old = theta_old*3 + theta;
  285. theta_old /= 4;
  286. phi_old = phi_old*3 - phi;
  287. phi_old /= 4;
  288. model_weapon = translate( unicite, camera.getPos() );
  289. model_weapon = rotate(model_weapon, theta_old, vec3(0, 1, 0));
  290. model_weapon = rotate(model_weapon, phi_old, vec3(1, 0, 0) );
  291. if ( veutViser ) model_weapon = translate( model_weapon, vec3(0,-0.5,1.0) );
  292. else model_weapon = translate( model_weapon, vec3(-0.5,-0.7,1.0) );
  293. glClear(GL_DEPTH_BUFFER_BIT); // L'arme s'affiche au premier plan quoi qu'il arrive
  294. weapon.afficher(projection * view * model_weapon, model_weapon, shTarget);
  295. // Affichage de l'épée
  296. sword.afficher(projection * view * model_sword, model_sword, shTarget);
  297. // Désactivation du shader
  298. shTarget = 0x0;
  299. glUseProgram( 0 );
  300. // Actualisation de la fenêtre
  301. SDL_GL_SwapWindow(m_fenetre);
  302. // Calcul du temps écoulé
  303. finBoucle = SDL_GetTicks();
  304. tempsEcoule = finBoucle - debutBoucle;
  305. // Si nécessaire, on met en pause le programme
  306. if(tempsEcoule < frameRate)
  307. SDL_Delay(frameRate - tempsEcoule);
  308. }
  309. }