|
@@ -0,0 +1,399 @@
|
|
|
+#include "SceneOpenGL.h"
|
|
|
+
|
|
|
+// Permet d'éviter la ré-écriture du namespace glm::
|
|
|
+using namespace glm;
|
|
|
+
|
|
|
+// Constructeur de Destucteur
|
|
|
+SceneOpenGL::SceneOpenGL(std::string titreFenetre, int largeurFenetre, int hauteurFenetre)
|
|
|
+: m_titreFenetre(titreFenetre), m_largeurFenetre(largeurFenetre),
|
|
|
+m_hauteurFenetre(hauteurFenetre), m_fenetre(0), m_contexteOpenGL(0),
|
|
|
+m_input(), m_texturLoader( "Textures/" ),
|
|
|
+m_shader( "Shaders/texture.vert", "Shaders/texture.frag" ),
|
|
|
+m_shLight( "Shaders/light.vert", "Shaders/light.frag" ),
|
|
|
+m_shGris( "Shaders/texture.vert", "Shaders/gris.frag" )
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+SceneOpenGL::~SceneOpenGL()
|
|
|
+{
|
|
|
+ SDL_GL_DeleteContext(m_contexteOpenGL);
|
|
|
+ SDL_DestroyWindow(m_fenetre);
|
|
|
+ SDL_Quit();
|
|
|
+}
|
|
|
+
|
|
|
+// Méthodes
|
|
|
+bool SceneOpenGL::initialiserFenetre()
|
|
|
+{
|
|
|
+ // Initialisation de la SDL
|
|
|
+ if(SDL_Init(SDL_INIT_VIDEO) < 0)
|
|
|
+ {
|
|
|
+ std::cout << "Erreur lors de l'initialisation de la SDL : " << SDL_GetError() << std::endl;
|
|
|
+ SDL_Quit();
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ #ifdef __APPLE__
|
|
|
+ // Version d'OpenGL
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
|
+
|
|
|
+ // Récupération du Bundle
|
|
|
+ CFURLRef URLBundle = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
|
|
+ char *cheminResources = new char[PATH_MAX];
|
|
|
+
|
|
|
+ // Changement du 'Working Directory'
|
|
|
+ if(CFURLGetFileSystemRepresentation(URLBundle, 1, (UInt8*)cheminResources, PATH_MAX))
|
|
|
+ chdir(cheminResources);
|
|
|
+
|
|
|
+ // Libération de la mémoire
|
|
|
+ delete[] cheminResources;
|
|
|
+ CFRelease(URLBundle);
|
|
|
+
|
|
|
+ #else
|
|
|
+ // Version d'OpenGL
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
|
|
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
|
+
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // Création de la fenêtre
|
|
|
+ uint32_t flag( SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL );
|
|
|
+ m_fenetre = SDL_CreateWindow(m_titreFenetre.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_largeurFenetre, m_hauteurFenetre, flag);
|
|
|
+ if(m_fenetre == 0)
|
|
|
+ {
|
|
|
+ std::cout << "Erreur lors de la creation de la fenetre : " << SDL_GetError() << std::endl;
|
|
|
+ SDL_Quit();
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Paramètres des évènements
|
|
|
+ m_input.setWindow( m_fenetre );
|
|
|
+ m_input.capturerPointeur( true );
|
|
|
+ m_input.setMoveKeys( SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_D, SDL_SCANCODE_A );
|
|
|
+
|
|
|
+ // Création du contexte OpenGL
|
|
|
+ m_contexteOpenGL = SDL_GL_CreateContext(m_fenetre);
|
|
|
+ if(m_contexteOpenGL == 0)
|
|
|
+ {
|
|
|
+ std::cout << SDL_GetError() << std::endl;
|
|
|
+ SDL_DestroyWindow(m_fenetre);
|
|
|
+ SDL_Quit();
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool SceneOpenGL::initGL()
|
|
|
+{
|
|
|
+ #ifdef WIN32
|
|
|
+ // On initialise GLEW
|
|
|
+ GLenum initialisationGLEW( glewInit() );
|
|
|
+
|
|
|
+ // Si l'initialisation a échoué :
|
|
|
+ if(initialisationGLEW != GLEW_OK)
|
|
|
+ {
|
|
|
+ // On affiche l'erreur grâce à la fonction : glewGetErrorString(GLenum code)
|
|
|
+ std::cout << "Erreur d'initialisation de GLEW : " << glewGetErrorString(initialisationGLEW) << std::endl;
|
|
|
+
|
|
|
+ // On quitte la SDL
|
|
|
+ SDL_GL_DeleteContext(m_contexteOpenGL);
|
|
|
+ SDL_DestroyWindow(m_fenetre);
|
|
|
+ SDL_Quit();
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
+
|
|
|
+ // Paramètres OpenGL avancés
|
|
|
+ glEnable(GL_DEPTH_TEST);
|
|
|
+ glEnable(GL_CULL_FACE);
|
|
|
+
|
|
|
+ // Tout s'est bien passé, on retourne true
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void SceneOpenGL::bouclePrincipale()
|
|
|
+{
|
|
|
+ // Variables temps
|
|
|
+ unsigned int frameRate (1000 / 50);
|
|
|
+ Uint32 debutBoucle(0), finBoucle(0), tempsEcoule(0);
|
|
|
+
|
|
|
+ // Frame Buffer
|
|
|
+ FrameBuffer frameBuffer(512, 512);
|
|
|
+ frameBuffer.charger();
|
|
|
+ m_texturLoader.addTextur("FBO_Tele", frameBuffer.getColorBuffer(0));
|
|
|
+
|
|
|
+ // Shaders
|
|
|
+ m_shader.charger();
|
|
|
+ m_shLight.charger();
|
|
|
+ m_shGris.charger();
|
|
|
+ Shader* shTarget(0x0);
|
|
|
+
|
|
|
+ // Matrices (première passe)
|
|
|
+ mat4 projectionFBO;
|
|
|
+
|
|
|
+ projectionFBO = perspective(70.0, (double)frameBuffer.getLargeur() / frameBuffer.getHauteur(), 1.0, 100.0);
|
|
|
+
|
|
|
+ // Matrices (seconde passe)
|
|
|
+ mat4 projection, projection30, projection70, plat;
|
|
|
+ mat4 view, unicite(1.0);
|
|
|
+
|
|
|
+ const float format( (float) m_largeurFenetre / m_hauteurFenetre );
|
|
|
+ projection70 = perspective(70.0, (double)format, 0.1, 100.0);
|
|
|
+ projection30 = perspective(30.0, (double)format, 0.1, 100.0);
|
|
|
+ const float plat_extY( 30.0 );
|
|
|
+ const float plat_extX( plat_extY * format );
|
|
|
+ plat = ortho(-plat_extX, plat_extX, -plat_extY, plat_extY, 0.1f, 100.0f);
|
|
|
+
|
|
|
+ // Vecteurs
|
|
|
+ uint16_t nbLight(3);
|
|
|
+ vec3 posLight[nbLight];
|
|
|
+ posLight[0] = vec3( 10.0, 3.0, 0.0 );
|
|
|
+ posLight[2] = vec3( 30.0, 3.5, 0.0 );
|
|
|
+ float posLightV[nbLight*3];
|
|
|
+
|
|
|
+ // Caméra mobile
|
|
|
+ Camera camera(vec3(0, 1.78, 0), vec3(0, 1.78, -1), vec3(0, 1, 0), 0.5, 0.5);
|
|
|
+ vec3 eyePos;
|
|
|
+ m_input.afficherPointeur(false);
|
|
|
+ m_input.capturerPointeur(true);
|
|
|
+
|
|
|
+ // Objet Caisse
|
|
|
+ OBJ metal;
|
|
|
+ metal.charger("3DModels/kube.obj", m_texturLoader.take("caisse_basic"));
|
|
|
+ mat4 model_metal(1.0);
|
|
|
+
|
|
|
+ OBJ plan;
|
|
|
+ plan.charger( "3DModels/plan.obj", m_texturLoader.take("pierres"), 50.0, 20.0);
|
|
|
+ mat4 model_plan(1.0);
|
|
|
+ model_plan = translate(model_plan, vec3(2.5,0.0,0.0));
|
|
|
+
|
|
|
+ OBJ tele;
|
|
|
+ tele.charger( "3DModels/plan.obj", m_texturLoader.take("FBO_Tele"), 2.5 );
|
|
|
+ mat4 model_tele(1.0);
|
|
|
+ model_tele = translate( model_tele, vec3(16.56,3.2,-0.5) );
|
|
|
+ model_tele = rotate(model_tele, 90.0f, vec3(0, 0, 1));
|
|
|
+
|
|
|
+ OBJ caisse;
|
|
|
+ caisse.charger("3DModels/kube.obj", m_texturLoader.take("chantier"));
|
|
|
+ mat4 model_caisseA(1.0),model_caisseB(1.0),model_caisseC(1.0);
|
|
|
+ model_caisseA = translate( model_caisseA, vec3(-6.56,1.0,-0.5) );
|
|
|
+ model_caisseB = translate( model_caisseB, vec3(6.56,1.0,4.5) );
|
|
|
+ model_caisseC = translate( model_caisseC, vec3(3.5,1.0,3.5) );
|
|
|
+
|
|
|
+ OBJ weapon;
|
|
|
+ weapon.charger( "3DModels/MPX.obj", m_texturLoader.take("chantier"), 0.2 );
|
|
|
+ mat4 model_weapon(1.0);
|
|
|
+
|
|
|
+ Mosaic sword;
|
|
|
+ sword.charger( "2DModels/sword_iron.bmp" );
|
|
|
+ mat4 model_sword(1.0);
|
|
|
+
|
|
|
+ float angle = 0.0;
|
|
|
+ float theta, theta_old = 0.0;
|
|
|
+ float phi, phi_old = 0.0;
|
|
|
+
|
|
|
+ bool rangee(true), rangement(false), veutRanger(false);
|
|
|
+ bool veutViser(false);
|
|
|
+ bool veutTemporiser(false);
|
|
|
+ bool veutLight(false), lightDone(false), lightState(false);
|
|
|
+ bool veutOverLight(false), overLightDone(false); GLint overLightState(false);
|
|
|
+
|
|
|
+ // Boucle principale
|
|
|
+ while(!m_input.terminer())
|
|
|
+ {
|
|
|
+ // On définit le temps de début de boucle
|
|
|
+ debutBoucle = SDL_GetTicks();
|
|
|
+
|
|
|
+ // Gestion des évènements
|
|
|
+ m_input.updateEvenements();
|
|
|
+
|
|
|
+ camera.setVol( m_input.getTouche( SDL_SCANCODE_LSHIFT ) );
|
|
|
+
|
|
|
+ if (m_input.getTouche(SDL_SCANCODE_ESCAPE))
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (m_input.getTouche(SDL_SCANCODE_KP_3)) nbLight = 3;
|
|
|
+ if (m_input.getTouche(SDL_SCANCODE_KP_2)) nbLight = 2;
|
|
|
+ if (m_input.getTouche(SDL_SCANCODE_KP_1)) nbLight = 1;
|
|
|
+ if (m_input.getTouche(SDL_SCANCODE_KP_0)) nbLight = 0;
|
|
|
+
|
|
|
+ camera.deplacer(m_input);
|
|
|
+
|
|
|
+ veutRanger = m_input.getTouche(SDL_SCANCODE_E) || m_input.getBoutonPad(1);
|
|
|
+ if ( !rangement && veutRanger ) {
|
|
|
+ rangement = true;
|
|
|
+ rangee = !rangee;
|
|
|
+ if ( rangee ) camera.setVitesse(0.5f);
|
|
|
+ else camera.setVitesse(0.2f);
|
|
|
+ }
|
|
|
+ else if ( !veutRanger ) rangement = false;
|
|
|
+
|
|
|
+ veutTemporiser = m_input.getTouche( SDL_SCANCODE_SPACE ) || m_input.getBoutonPad(2);
|
|
|
+
|
|
|
+ veutViser = m_input.getBoutonSouris(3) || m_input.getBoutonPad(4);
|
|
|
+
|
|
|
+ veutLight = m_input.getTouche( SDL_SCANCODE_LCTRL ) || m_input.getBoutonPad(3);
|
|
|
+ if ( !lightDone && veutLight ) {
|
|
|
+ lightDone = true;
|
|
|
+ lightState = !lightState;
|
|
|
+ }
|
|
|
+ else if ( !veutLight ) lightDone = false;
|
|
|
+
|
|
|
+ veutOverLight = m_input.getTouche( SDL_SCANCODE_Q ) || m_input.getBoutonPad(0);
|
|
|
+ if ( !overLightDone && veutOverLight ) {
|
|
|
+ overLightDone = true;
|
|
|
+ overLightState = !overLightState;
|
|
|
+ }
|
|
|
+ else if ( !veutOverLight ) overLightDone = false;
|
|
|
+
|
|
|
+
|
|
|
+ /* ***** Première Passe ***** */
|
|
|
+
|
|
|
+ // Verrouillage du Frame Buffer
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.getID());
|
|
|
+
|
|
|
+ // Nettoyage de l'écran
|
|
|
+ glClearColor(0.2, 0.2, 0.25, 1.0);
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
+
|
|
|
+ // Redimensionnement de la zone d'affichage
|
|
|
+ glViewport(0, 0, frameBuffer.getLargeur(), frameBuffer.getHauteur());
|
|
|
+
|
|
|
+ // Placement de la caméra
|
|
|
+ view = lookAt(vec3(0, 0, 3), vec3(0, 0, 0), vec3(0, 1, 0));
|
|
|
+
|
|
|
+ // Gestion de la rotation de la caisse
|
|
|
+ if ( veutTemporiser )
|
|
|
+ angle = 0.05f;
|
|
|
+ else
|
|
|
+ angle = 2.0f;
|
|
|
+
|
|
|
+ // Activation du shader
|
|
|
+ glUseProgram( m_shGris.getProgramID() );
|
|
|
+
|
|
|
+ // Affichage de la caisse
|
|
|
+ model_metal = rotate(model_metal, angle, vec3(0, 1, 0));
|
|
|
+ metal.afficher(projectionFBO*view*model_metal, model_metal, &m_shGris);
|
|
|
+
|
|
|
+ // Désactivation du shader
|
|
|
+ glUseProgram( 0 );
|
|
|
+
|
|
|
+ // Déverrouillage du Frame Buffer
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
+
|
|
|
+
|
|
|
+ /* ***** Seconde Passe ***** */
|
|
|
+
|
|
|
+ // Nettoyage de l'écran
|
|
|
+ glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
+
|
|
|
+ // Redimensionnement de la zone d'affichage
|
|
|
+ glViewport(0, 0, m_largeurFenetre, m_hauteurFenetre);
|
|
|
+
|
|
|
+ // Gestion de la caméra
|
|
|
+ camera.lookAt(view);
|
|
|
+ if ( veutViser ) projection = projection30;
|
|
|
+ else if ( m_input.getTouche( SDL_SCANCODE_X ) ) projection = plat;
|
|
|
+ else projection = projection70;
|
|
|
+
|
|
|
+ // Gestion de la lumière
|
|
|
+ posLight[1] = camera.getPos() + vec3(0.0, 1.2, 0.0);
|
|
|
+ posLight[2] = rotateY( posLight[2], angle );
|
|
|
+
|
|
|
+ uint16_t j;
|
|
|
+ for ( uint16_t i(0); i<nbLight; i++ )
|
|
|
+ {
|
|
|
+ j = i * 3;
|
|
|
+ posLightV[j] = posLight[i].x;
|
|
|
+ posLightV[j+1] = posLight[i].y;
|
|
|
+ posLightV[j+2] = posLight[i].z;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Activation du shader
|
|
|
+ if ( lightState )
|
|
|
+ {
|
|
|
+ eyePos = camera.getPos();
|
|
|
+ shTarget = &m_shLight;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ shTarget = &m_shader;
|
|
|
+
|
|
|
+ glUseProgram( shTarget->getProgramID() );
|
|
|
+
|
|
|
+ if ( lightState )
|
|
|
+ {
|
|
|
+ glUniform3f(glGetUniformLocation(m_shLight.getProgramID(), "eyePos"), eyePos.x, eyePos.y, eyePos.z);
|
|
|
+ glUniform3fv(glGetUniformLocation(m_shLight.getProgramID(), "posLight"), nbLight, posLightV);
|
|
|
+ glUniform1i(glGetUniformLocation(m_shLight.getProgramID(), "overLight"), overLightState);
|
|
|
+ glUniform1i(glGetUniformLocation(m_shLight.getProgramID(), "nbLight"), (int)nbLight);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Afficher le plan
|
|
|
+ plan.afficher(projection * view * model_plan, model_plan, shTarget);
|
|
|
+
|
|
|
+ // Afficher la télé
|
|
|
+ tele.afficher(projection * view * model_tele, model_tele, shTarget);
|
|
|
+
|
|
|
+ // Affichage de la caisse
|
|
|
+ model_caisseA = rotate(model_caisseA, angle, vec3(0, 1, 0));
|
|
|
+ weapon.afficher(projection * view * model_caisseA, model_caisseA, shTarget);
|
|
|
+ caisse.afficher(projection * view * model_caisseB, model_caisseB, shTarget);
|
|
|
+ caisse.afficher(projection * view * model_caisseC, model_caisseC, shTarget);
|
|
|
+
|
|
|
+ // Affichage de l'arme
|
|
|
+ if ( rangee ) {
|
|
|
+ theta = camera.getTheta() + 180;
|
|
|
+ phi = 90;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ theta = camera.getTheta();
|
|
|
+ phi = camera.getPhi();
|
|
|
+ }
|
|
|
+
|
|
|
+ theta_old = theta_old*3 + theta;
|
|
|
+ theta_old /= 4;
|
|
|
+ phi_old = phi_old*3 - phi;
|
|
|
+ phi_old /= 4;
|
|
|
+
|
|
|
+ model_weapon = translate( unicite, camera.getPos() );
|
|
|
+ model_weapon = rotate(model_weapon, theta_old, vec3(0, 1, 0));
|
|
|
+ model_weapon = rotate(model_weapon, phi_old, vec3(1, 0, 0) );
|
|
|
+
|
|
|
+ if ( veutViser ) model_weapon = translate( model_weapon, vec3(0,-0.5,1.0) );
|
|
|
+ else model_weapon = translate( model_weapon, vec3(-0.5,-0.7,1.0) );
|
|
|
+
|
|
|
+ glClear(GL_DEPTH_BUFFER_BIT); // L'arme s'affiche au premier plan quoi qu'il arrive
|
|
|
+
|
|
|
+ weapon.afficher(projection * view * model_weapon, model_weapon, shTarget);
|
|
|
+
|
|
|
+ // Affichage de l'épée
|
|
|
+ sword.afficher(projection * view * model_sword, model_sword, shTarget);
|
|
|
+
|
|
|
+ // Désactivation du shader
|
|
|
+ shTarget = 0x0;
|
|
|
+ glUseProgram( 0 );
|
|
|
+
|
|
|
+ // Actualisation de la fenêtre
|
|
|
+ SDL_GL_SwapWindow(m_fenetre);
|
|
|
+
|
|
|
+ // Calcul du temps écoulé
|
|
|
+ finBoucle = SDL_GetTicks();
|
|
|
+ tempsEcoule = finBoucle - debutBoucle;
|
|
|
+
|
|
|
+ // Si nécessaire, on met en pause le programme
|
|
|
+ if(tempsEcoule < frameRate)
|
|
|
+ SDL_Delay(frameRate - tempsEcoule);
|
|
|
+ }
|
|
|
+}
|