ripple/ripple.cpp

982 lines
36 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdlib.h>
#include <iostream>
#include "inf2705.h"
#include "constants.h"
#include "FBO.h"
#include "Packets.h"
#define SOL 1
// variables pour l'utilisation des nuanceurs
GLuint prog; // votre programme de nuanceurs
GLint locVertex = -1;
GLint locNormal = -1;
GLint locTexCoord = -1;
GLint locmatrModel = -1;
GLint locmatrVisu = -1;
GLint locmatrProj = -1;
GLint locmatrNormale = -1;
GLint loclaTexture = -1;
GLuint indLightSource;
GLuint indFrontMaterial;
GLuint indLightModel;
GLuint indvarsUnif;
GLuint progBase; // le programme de nuanceurs de base
GLint locVertexBase = -1;
GLint locColorBase = -1;
GLint locmatrModelBase = -1;
GLint locmatrVisuBase = -1;
GLint locmatrProjBase = -1;
GLuint vao[2];
GLuint vbo[5];
GLuint ubo[4];
// matrices de du pipeline graphique
MatricePipeline matrModel;
MatricePipeline matrVisu;
MatricePipeline matrProj;
// les formes
FormeSphere *sphere = NULL, *sphereLumi = NULL;
FormeTheiere *theiere = NULL;
FormeTore *tore = NULL;
FormeCylindre *cylindre = NULL;
FormeCylindre *cone = NULL;
// variables pour définir le point de vue
double thetaCam = 0.0; // angle de rotation de la caméra (coord. sphériques)
double phiCam = 0.0; // angle de rotation de la caméra (coord. sphériques)
double distCam = 0.0; // distance (coord. sphériques)
// variables d'état
bool enPerspective = false; // indique si on est en mode Perspective (true) ou Ortho (false)
bool enmouvement = false; // le modèle est en mouvement/rotation automatique ou non
bool afficheAxes = true; // indique si on affiche les axes
GLenum modePolygone = GL_FILL; // comment afficher les polygones
// FBOs
FBO *posFBO;
FBO *heightFBO;
FBO *aaFBO;
// Wave Packets
Packets *packets;
////////////////////////////////////////
// déclaration des variables globales //
////////////////////////////////////////
// partie 1: illumination
int modele = 1; // le modèle à afficher
// partie 3: texture
GLuint textureDE = 0;
GLuint textureECHIQUIER = 0;
// définition des lumières
struct LightSourceParameters
{
glm::vec4 ambient;
glm::vec4 diffuse;
glm::vec4 specular;
glm::vec4 position;
glm::vec3 spotDirection;
float spotExposant;
float spotAngle; // ([0.0,90.0] ou 180.0)
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
} LightSource[1] = { { glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
glm::vec4( 4, 1, 15, 1.0 ),
glm::vec3( -5.0, -2.0, -10.0 ),
1.0, // l'exposant du cône
15.0, // l'angle du cône du spot
1., 0., 0. } };
// définition du matériau
struct MaterialParameters
{
glm::vec4 emission;
glm::vec4 ambient;
glm::vec4 diffuse;
glm::vec4 specular;
float shininess;
} FrontMaterial = { glm::vec4( 0.0, 0.0, 0.0, 1.0 ),
glm::vec4( 0.1, 0.1, 0.1, 1.0 ),
glm::vec4( 1.0, 0.1, 1.0, 1.0 ),
glm::vec4( 1.0, 1.0, 1.0, 1.0 ),
100.0 };
struct LightModelParameters
{
glm::vec4 ambient; // couleur ambiante
int localViewer; // doit-on prendre en compte la position de l'observateur? (local ou à l'infini)
int twoSide; // éclairage sur les deux côtés ou un seul?
} LightModel = { glm::vec4(0,0,0,1), false, false };
struct
{
// partie 1: illumination
int typeIllumination; // 0:Lambert, 1:Gouraud, 2:Phong
int utiliseBlinn; // indique si on veut utiliser modèle spéculaire de Blinn ou Phong
int utiliseDirect; // indique si on utilise un spot style Direct3D ou OpenGL
int afficheNormales; // indique si on utilise les normales comme couleurs (utile pour le débogage)
// partie 3: texture
int texnumero; // numéro de la texture appliquée
int utiliseCouleur; // doit-on utiliser la couleur de base de l'objet en plus de celle de la texture?
int afficheTexelNoir; // un texel noir doit-il être affiché 0:noir, 1:mi-coloré, 2:transparent?
} varsUnif = { 2, false, false, false,
0, true, 0 };
// ( En glsl, les types 'bool' et 'int' sont de la même taille, ce qui n'est pas le cas en C++.
// Ci-dessus, on triche donc un peu en déclarant les 'bool' comme des 'int', mais ça facilite la
// copie directe vers le nuanceur où les variables seront bien de type 'bool'. )
void verifierAngles()
{
if ( thetaCam > 360.0 )
thetaCam -= 360.0;
else if ( thetaCam < 0.0 )
thetaCam += 360.0;
const GLdouble MINPHI = -90.0, MAXPHI = 90.0;
if ( phiCam > MAXPHI )
phiCam = MAXPHI;
else if ( phiCam < MINPHI )
phiCam = MINPHI;
}
void calculerPhysique( )
{
if ( enmouvement )
{
static int sensTheta = 1;
static int sensPhi = 1;
thetaCam += 0.3 * sensTheta;
phiCam += 0.5 * sensPhi;
//if ( thetaCam <= 0. || thetaCam >= 360.0 ) sensTheta = -sensTheta;
if ( phiCam < -90.0 || phiCam > 90.0 ) sensPhi = -sensPhi;
static int sensAngle = 1;
LightSource[0].spotAngle += sensAngle * 0.3;
if ( LightSource[0].spotAngle < 5.0 ) sensAngle = -sensAngle;
if ( LightSource[0].spotAngle > 60.0 ) sensAngle = -sensAngle;
#if 0
static int sensExposant = 1;
LightSource[0].spotExposant += sensExposant * 0.3;
if ( LightSource[0].spotExposant < 1.0 ) sensExposant = -sensExposant;
if ( LightSource[0].spotExposant > 10.0 ) sensExposant = -sensExposant;
#endif
// De temps à autre, alterner entre le modèle d'illumination: Lambert, Gouraud, Phong
static float type = 0;
type += 0.005;
varsUnif.typeIllumination = fmod(type,3);
}
verifierAngles();
}
void chargerTextures()
{
unsigned char *pixels;
GLsizei largeur, hauteur;
if ( ( pixels = ChargerImage( "textures/de.bmp", largeur, hauteur ) ) != NULL )
{
glGenTextures( 1, &textureDE );
glBindTexture( GL_TEXTURE_2D, textureDE );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, largeur, hauteur, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, 0 );
delete[] pixels;
}
if ( ( pixels = ChargerImage( "textures/echiquier.bmp", largeur, hauteur ) ) != NULL )
{
glGenTextures( 1, &textureECHIQUIER );
glBindTexture( GL_TEXTURE_2D, textureECHIQUIER );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, largeur, hauteur, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glBindTexture( GL_TEXTURE_2D, 0 );
delete[] pixels;
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
}
void chargerNuanceurs()
{
// charger le nuanceur de base
{
// créer le programme
progBase = glCreateProgram();
// attacher le nuanceur de sommets
{
GLuint nuanceurObj = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( nuanceurObj, 1, &ProgNuanceur::chainesSommetsMinimal, NULL );
glCompileShader( nuanceurObj );
glAttachShader( progBase, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
}
// attacher le nuanceur de fragments
{
GLuint nuanceurObj = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( nuanceurObj, 1, &ProgNuanceur::chainesFragmentsMinimal, NULL );
glCompileShader( nuanceurObj );
glAttachShader( progBase, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
}
// faire l'édition des liens du programme
glLinkProgram( progBase );
ProgNuanceur::afficherLogLink( progBase );
// demander la "Location" des variables
if ( ( locVertexBase = glGetAttribLocation( progBase, "Vertex" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Vertex" << std::endl;
if ( ( locColorBase = glGetAttribLocation( progBase, "Color" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Color" << std::endl;
if ( ( locmatrModelBase = glGetUniformLocation( progBase, "matrModel" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrModel" << std::endl;
if ( ( locmatrVisuBase = glGetUniformLocation( progBase, "matrVisu" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrVisu" << std::endl;
if ( ( locmatrProjBase = glGetUniformLocation( progBase, "matrProj" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrProj" << std::endl;
}
// charger le nuanceur de ce TP
{
// créer le programme
prog = glCreateProgram();
// attacher le nuanceur de sommets
#if !defined(SOL)
const GLchar *chainesSommets = ProgNuanceur::lireNuanceur( "nuanceurSommets.glsl" );
#else
const GLchar *chainesSommets = ProgNuanceur::lireNuanceur( "nuanceurSommetsSolution.glsl" );
#endif
if ( chainesSommets != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( nuanceurObj, 1, &chainesSommets, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesSommets;
}
#if !defined(SOL)
const GLchar *chainesGeometrie = ProgNuanceur::lireNuanceur( "nuanceurGeometrie.glsl" );
#else
const GLchar *chainesGeometrie = ProgNuanceur::lireNuanceur( "nuanceurGeometrieSolution.glsl" );
#endif
if ( chainesGeometrie != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_GEOMETRY_SHADER );
glShaderSource( nuanceurObj, 1, &chainesGeometrie, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesGeometrie;
}
// attacher le nuanceur de fragments
#if !defined(SOL)
const GLchar *chainesFragments = ProgNuanceur::lireNuanceur( "nuanceurFragments.glsl" );
#else
const GLchar *chainesFragments = ProgNuanceur::lireNuanceur( "nuanceurFragmentsSolution.glsl" );
#endif
if ( chainesFragments != NULL )
{
GLuint nuanceurObj = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( nuanceurObj, 1, &chainesFragments, NULL );
glCompileShader( nuanceurObj );
glAttachShader( prog, nuanceurObj );
ProgNuanceur::afficherLogCompile( nuanceurObj );
delete [] chainesFragments;
}
// faire l'édition des liens du programme
glLinkProgram( prog );
ProgNuanceur::afficherLogLink( prog );
// demander la "Location" des variables
if ( ( locVertex = glGetAttribLocation( prog, "Vertex" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Vertex" << std::endl;
if ( ( locNormal = glGetAttribLocation( prog, "Normal" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de Normal (partie 1)" << std::endl;
if ( ( locTexCoord = glGetAttribLocation( prog, "TexCoord" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de TexCoord (partie 3)" << std::endl;
if ( ( locmatrModel = glGetUniformLocation( prog, "matrModel" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrModel" << std::endl;
if ( ( locmatrVisu = glGetUniformLocation( prog, "matrVisu" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrVisu" << std::endl;
if ( ( locmatrProj = glGetUniformLocation( prog, "matrProj" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrProj" << std::endl;
if ( ( locmatrNormale = glGetUniformLocation( prog, "matrNormale" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de matrNormale (partie 1)" << std::endl;
if ( ( loclaTexture = glGetUniformLocation( prog, "laTexture" ) ) == -1 ) std::cerr << "!!! pas trouvé la \"Location\" de laTexture (partie 3)" << std::endl;
if ( ( indLightSource = glGetUniformBlockIndex( prog, "LightSourceParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de LightSource" << std::endl;
if ( ( indFrontMaterial = glGetUniformBlockIndex( prog, "MaterialParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de FrontMaterial" << std::endl;
if ( ( indLightModel = glGetUniformBlockIndex( prog, "LightModelParameters" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de LightModel" << std::endl;
if ( ( indvarsUnif = glGetUniformBlockIndex( prog, "varsUnif" ) ) == GL_INVALID_INDEX ) std::cerr << "!!! pas trouvé l'\"index\" de varsUnif" << std::endl;
// charger les ubo
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[0] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(LightSource), &LightSource, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 0;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[0] );
glUniformBlockBinding( prog, indLightSource, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[1] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(FrontMaterial), &FrontMaterial, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 1;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[1] );
glUniformBlockBinding( prog, indFrontMaterial, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[2] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(LightModel), &LightModel, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 2;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[2] );
glUniformBlockBinding( prog, indLightModel, bindingIndex );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[3] );
glBufferData( GL_UNIFORM_BUFFER, sizeof(varsUnif), &varsUnif, GL_DYNAMIC_COPY );
glBindBuffer( GL_UNIFORM_BUFFER, 0 );
const GLuint bindingIndex = 3;
glBindBufferBase( GL_UNIFORM_BUFFER, bindingIndex, ubo[3] );
glUniformBlockBinding( prog, indvarsUnif, bindingIndex );
}
}
}
// initialisation d'openGL
void initialiser()
{
// donner l'orientation du modèle
thetaCam = 0.0;
phiCam = 0.0;
distCam = 30.0;
// Create FBOs
posFBO = new FBO();
heightFBO = new FBO();
aaFBO = new FBO();
// couleur de l'arrière-plan
glClearColor( 0.4, 0.2, 0.0, 1.0 );
// activer les etats openGL
glEnable( GL_DEPTH_TEST );
// charger les textures
chargerTextures();
// allouer les UBO pour les variables uniformes
glGenBuffers( 4, ubo );
// charger les nuanceurs
chargerNuanceurs();
glUseProgram( prog );
// (partie 1) créer le cube
/* +Y */
/* 3+-----------+2 */
/* |\ |\ */
/* | \ | \ */
/* | \ | \ */
/* | 7+-----------+6 */
/* | | | | */
/* | | | | */
/* 0+---|-------+1 | */
/* \ | \ | +X */
/* \ | \ | */
/* \| \| */
/* 4+-----------+5 */
/* +Z */
GLfloat sommets[3*4*6] =
{
-1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, // P3,P2,P0,P1
1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // P5,P4,P1,P0
1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // P6,P5,P2,P1
-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, // P7,P6,P3,P2
-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, // P4,P7,P0,P3
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0 // P4,P5,P7,P6
};
GLfloat normales[3*4*6] =
{
0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0,
0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
};
GLfloat texcoordsDe[2*4*6] =
{
1.000000,0.000000, 0.666666,0.000000, 1.000000,0.333333, 0.666666,0.333333,
0.000000,0.666666, 0.333333,0.666666, 0.000000,0.333333, 0.333333,0.333333,
0.666666,1.000000, 0.666666,0.666666, 0.333333,1.000000, 0.333333,0.666666,
1.000000,0.333333, 0.666666,0.333333, 1.000000,0.666666, 0.666666,0.666666,
0.333333,0.000000, 0.333333,0.333333, 0.666666,0.000000, 0.666666,0.333333,
0.666666,0.333333, 0.333333,0.333333, 0.666666,0.666666, 0.333333,0.666666
};
GLfloat texcoordsEchiquier[2*4*6] =
{
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0,
2.0, -1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0,
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0,
-1.0, 2.0, 2.0, 2.0, -1.0, -1.0, 2.0, -1.0,
2.0, 2.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0,
-1.0, -1.0, -1.0, 2.0, 2.0, -1.0, 2.0, 2.0
};
// allouer les objets OpenGL
glGenVertexArrays( 2, vao );
glGenBuffers( 5, vbo );
// initialiser le VAO
glBindVertexArray( vao[0] );
// charger le VBO pour les sommets
glBindBuffer( GL_ARRAY_BUFFER, vbo[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof(sommets), sommets, GL_STATIC_DRAW );
glVertexAttribPointer( locVertex, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locVertex);
// (partie 1) charger le VBO pour les normales
glBindBuffer( GL_ARRAY_BUFFER, vbo[1] );
glBufferData( GL_ARRAY_BUFFER, sizeof(normales), normales, GL_STATIC_DRAW );
glVertexAttribPointer( locNormal, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locNormal);
// (partie 3) charger le VBO pour les coordonnées de texture du dé
glBindBuffer( GL_ARRAY_BUFFER, vbo[2] );
glBufferData( GL_ARRAY_BUFFER, sizeof(texcoordsDe), texcoordsDe, GL_STATIC_DRAW );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locTexCoord);
// (partie 3) charger le VBO pour les coordonnées de texture de l'échiquier
glBindBuffer( GL_ARRAY_BUFFER, vbo[3] );
glBufferData( GL_ARRAY_BUFFER, sizeof(texcoordsEchiquier), texcoordsEchiquier, GL_STATIC_DRAW );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locTexCoord);
glBindVertexArray(0);
// initialiser le VAO pour une ligne (montrant la direction du spot)
glBindVertexArray( vao[1] );
GLfloat coords[] = { 0., 0., 0., 0., 0., 1. };
glBindBuffer( GL_ARRAY_BUFFER, vbo[4] );
glBufferData( GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW );
glVertexAttribPointer( locVertexBase, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray(locVertexBase);
glBindVertexArray(0);
// créer quelques autres formes
sphere = new FormeSphere( 1.0, 32, 32 );
sphereLumi = new FormeSphere( 0.5, 10, 10 );
theiere = new FormeTheiere( );
tore = new FormeTore( 0.4, 0.8, 32, 32 );
cylindre = new FormeCylindre( 0.3, 0.3, 3.0, 32, 32 );
cone = new FormeCylindre( 0.0, 0.5, 3.0, 32, 32 );
// Update display mesh and FBOs
// redimensionner();
}
void conclure()
{
glUseProgram( 0 );
glDeleteVertexArrays( 2, vao );
glDeleteBuffers( 4, vbo );
glDeleteBuffers( 4, ubo );
delete sphere;
delete sphereLumi;
delete theiere;
delete tore;
delete cylindre;
delete cone;
delete posFBO;
delete heightFBO;
delete aaFBO;
}
void afficherModele()
{
// partie 3: paramètres de texture
switch ( varsUnif.texnumero )
{
default:
//std::cout << "Sans texture" << std::endl;
glBindTexture( GL_TEXTURE_2D, 0 );
break;
case 1:
//std::cout << "Texture DE" << std::endl;
glBindTexture( GL_TEXTURE_2D, textureDE );
break;
case 2:
//std::cout << "Texture ECHIQUIER" << std::endl;
glBindTexture( GL_TEXTURE_2D, textureECHIQUIER );
break;
}
// Dessiner le modèle
matrModel.PushMatrix(); {
// appliquer les rotations
matrModel.Rotate( phiCam, -1.0, 0.0, 0.0 );
matrModel.Rotate( thetaCam, 0.0, -1.0, 0.0 );
// mise à l'échelle
matrModel.Scale( 5.0, 5.0, 5.0 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
// (partie 1: ne pas oublier de calculer et donner une matrice pour les transformations des normales)
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
switch ( modele )
{
default:
case 1:
// afficher le cube
glBindVertexArray( vao[0] );
glBindBuffer( GL_ARRAY_BUFFER, varsUnif.texnumero == 1 ? vbo[2] : vbo[3] );
glVertexAttribPointer( locTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 4, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 8, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 12, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 16, 4 );
glDrawArrays( GL_TRIANGLE_STRIP, 20, 4 );
glBindVertexArray( 0 );
break;
case 2:
tore->afficher();
break;
case 3:
sphere->afficher();
break;
case 4:
matrModel.Rotate( -90.0, 1.0, 0.0, 0.0 );
matrModel.Translate( 0.0, 0.0, -0.5 );
matrModel.Scale( 0.5, 0.5, 0.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
theiere->afficher( );
break;
case 5:
matrModel.PushMatrix(); {
matrModel.Translate( 0.0, 0.0, -1.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
cylindre->afficher();
} matrModel.PopMatrix();
break;
case 6:
matrModel.PushMatrix(); {
matrModel.Translate( 0.0, 0.0, -1.5 );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
glUniformMatrix3fv( locmatrNormale, 1, GL_TRUE, glm::value_ptr( glm::inverse( glm::mat3( matrVisu.getMatr() * matrModel.getMatr() ) ) ) );
cone->afficher();
} matrModel.PopMatrix();
break;
}
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
}
void afficherLumiere()
{
// Dessiner la lumiere
// tracer une ligne vers la source lumineuse
const GLfloat fact = 5.;
GLfloat coords[] =
{
LightSource[0].position.x , LightSource[0].position.y , LightSource[0].position.z,
LightSource[0].position.x+LightSource[0].spotDirection.x/fact, LightSource[0].position.y+LightSource[0].spotDirection.y/fact, LightSource[0].position.z+LightSource[0].spotDirection.z/fact
};
glLineWidth( 3.0 );
glVertexAttrib3f( locColorBase, 1.0, 1.0, 0.5 ); // jaune
glBindVertexArray( vao[1] );
matrModel.PushMatrix(); {
glBindBuffer( GL_ARRAY_BUFFER, vbo[4] );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(coords), coords );
glDrawArrays( GL_LINES, 0, 2 );
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
glBindVertexArray( 0 );
glLineWidth( 1.0 );
// tracer la source lumineuse
matrModel.PushMatrix(); {
matrModel.Translate( LightSource[0].position.x, LightSource[0].position.y, LightSource[0].position.z );
glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
sphereLumi->afficher();
} matrModel.PopMatrix(); glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
}
// fonction d'affichage
void FenetreTP::afficherScene()
{
// effacer l'ecran et le tampon de profondeur
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( progBase );
// définir le pipeline graphique
if ( enPerspective )
{
matrProj.Perspective( 35.0, (GLdouble)largeur_ / (GLdouble)hauteur_,
0.1, 60.0 );
}
else
{
const GLfloat d = 8.0;
if ( largeur_ <= hauteur_ )
{
matrProj.Ortho( -d, d,
-d*(GLdouble)hauteur_ / (GLdouble)largeur_,
d*(GLdouble)hauteur_ / (GLdouble)largeur_,
0.1, 60.0 );
}
else
{
matrProj.Ortho( -d*(GLdouble)largeur_ / (GLdouble)hauteur_,
d*(GLdouble)largeur_ / (GLdouble)hauteur_,
-d, d,
0.1, 60.0 );
}
}
glUniformMatrix4fv( locmatrProjBase, 1, GL_FALSE, matrProj );
matrVisu.LookAt( 0.0, 0.0, distCam, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
glUniformMatrix4fv( locmatrVisuBase, 1, GL_FALSE, matrVisu );
matrModel.LoadIdentity();
glUniformMatrix4fv( locmatrModelBase, 1, GL_FALSE, matrModel );
// afficher les axes
if ( afficheAxes ) FenetreTP::afficherAxes( 8.0 );
// dessiner la scène
afficherLumiere();
glUseProgram( prog );
// mettre à jour les blocs de variables uniformes
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[0] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &LightSource, sizeof(LightSource) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[1] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &FrontMaterial, sizeof(FrontMaterial) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[2] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &LightModel, sizeof(LightModel) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
{
glBindBuffer( GL_UNIFORM_BUFFER, ubo[3] );
GLvoid *p = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY );
memcpy( p, &varsUnif, sizeof(varsUnif) );
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
// mettre à jour les matrices et autres uniformes
glUniformMatrix4fv( locmatrProj, 1, GL_FALSE, matrProj );
glUniformMatrix4fv( locmatrVisu, 1, GL_FALSE, matrVisu );
glUniformMatrix4fv( locmatrModel, 1, GL_FALSE, matrModel );
//glActiveTexture( GL_TEXTURE0 ); // activer la texture '0' (valeur de défaut)
glUniform1i( loclaTexture, 0 ); // '0' => utilisation de GL_TEXTURE0
afficherModele();
}
// fonction de redimensionnement de la fenêtre graphique
void FenetreTP::redimensionner( GLsizei w, GLsizei h )
{
std::cout << "Resizing to " << w << "×" << h << std::endl;
/* FIXME Is this function called on program start ? */
glViewport( 0, 0, w, h );
/* TODO Create/resize display mesh */
posFBO->Liberer();
posFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h);
heightFBO->Liberer();
heightFBO->Init(WAVETEX_WIDTH_FACTOR * w, WAVETEX_HEIGHT_FACTOR * h);
aaFBO->Liberer();
aaFBO->Init(AA_OVERSAMPLE_FACTOR * w, AA_OVERSAMPLE_FACTOR * h);
}
static void echoEtats( )
{
static std::string illuminationStr[] = { "0:Lambert", "1:Gouraud", "2:Phong" };
static std::string reflexionStr[] = { "0:Phong", "1:Blinn" };
static std::string spotStr[] = { "0:OpenGL", "1:Direct3D" };
std::cout << " modèle d'illumination= " << illuminationStr[varsUnif.typeIllumination]
<< ", refléxion spéculaire= " << reflexionStr[varsUnif.utiliseBlinn]
<< ", spot= " << spotStr[varsUnif.utiliseDirect]
<< std::endl;
}
// fonction de gestion du clavier
void FenetreTP::clavier( TP_touche touche )
{
// traitement des touches q et echap
switch ( touche )
{
case TP_ECHAP:
case TP_q: // Quitter l'application
quit();
break;
case TP_x: // Activer/désactiver l'affichage des axes
afficheAxes = !afficheAxes;
std::cout << "// Affichage des axes ? " << ( afficheAxes ? "OUI" : "NON" ) << std::endl;
break;
case TP_v: // Recharger les fichiers des nuanceurs et recréer le programme
chargerNuanceurs();
std::cout << "// Recharger nuanceurs" << std::endl;
break;
case TP_p: // Permuter la projection: perspective ou orthogonale
enPerspective = !enPerspective;
break;
case TP_i: // Alterner entre le modèle d'illumination: Lambert, Gouraud, Phong
if ( ++varsUnif.typeIllumination > 2 ) varsUnif.typeIllumination = 0;
echoEtats( );
break;
case TP_r: // Alterner entre le modèle de réflexion spéculaire: Phong, Blinn
varsUnif.utiliseBlinn = !varsUnif.utiliseBlinn;
echoEtats( );
break;
case TP_s: // Alterner entre le modèle de spot: OpenGL, Direct3D
varsUnif.utiliseDirect = !varsUnif.utiliseDirect;
echoEtats( );
break;
//case TP_l: // Alterner entre une caméra locale à la scène ou distante (localViewer)
// LightModel.localViewer = !LightModel.localViewer;
// std::cout << " localViewer=" << LightModel.localViewer << std::endl;
// break;
case TP_a: // Incrémenter l'angle du cône du spot
case TP_EGAL:
case TP_PLUS:
LightSource[0].spotAngle += 2.0;
if ( LightSource[0].spotAngle > 90.0 ) LightSource[0].spotAngle = 90.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
break;
case TP_z: // Décrémenter l'angle du cône du spot
case TP_MOINS:
case TP_SOULIGNE:
LightSource[0].spotAngle -= 2.0;
if ( LightSource[0].spotAngle < 0.0 ) LightSource[0].spotAngle = 0.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
break;
case TP_d: // Incrémenter l'exposant du spot
case TP_BARREOBLIQUE:
LightSource[0].spotExposant += 0.3;
if ( LightSource[0].spotExposant > 89.0 ) LightSource[0].spotExposant = 89.0;
std::cout << " spotExposant=" << LightSource[0].spotExposant << std::endl;
break;
case TP_e: // Décrémenter l'exposant du spot
case TP_POINT:
LightSource[0].spotExposant -= 0.3;
if ( LightSource[0].spotExposant < 0.0 ) LightSource[0].spotExposant = 0.0;
std::cout << " spotExposant=" << LightSource[0].spotExposant << std::endl;
break;
case TP_j: // Incrémenter le coefficient de brillance
case TP_CROCHETDROIT:
FrontMaterial.shininess *= 1.1;
std::cout << " FrontMaterial.shininess=" << FrontMaterial.shininess << std::endl;
break;
case TP_u: // Décrémenter le coefficient de brillance
case TP_CROCHETGAUCHE:
FrontMaterial.shininess /= 1.1; if ( FrontMaterial.shininess < 0.0 ) FrontMaterial.shininess = 0.0;
std::cout << " FrontMaterial.shininess=" << FrontMaterial.shininess << std::endl;
break;
case TP_DROITE:
LightSource[0].position.x += 0.3;
break;
case TP_GAUCHE:
LightSource[0].position.x -= 0.3;
break;
case TP_BAS:
LightSource[0].position.y += 0.3;
break;
case TP_HAUT:
LightSource[0].position.y -= 0.3;
break;
case TP_FIN:
LightSource[0].spotDirection.x += 0.6;
break;
case TP_DEBUT:
LightSource[0].spotDirection.x -= 0.6;
break;
case TP_PAGEPREC:
LightSource[0].spotDirection.y += 0.6;
break;
case TP_PAGESUIV:
LightSource[0].spotDirection.y -= 0.6;
break;
case TP_m: // Choisir le modèle affiché: cube, tore, sphère, théière, cylindre, cône
if ( ++modele > 6 ) modele = 1;
std::cout << " modele=" << modele << std::endl;
break;
case TP_0:
thetaCam = 0.0; phiCam = 0.0; distCam = 30.0; // placer les choses afin d'avoir une belle vue
break;
case TP_t: // Choisir la texture utilisée: aucune, dé, échiquier
varsUnif.texnumero++;
if ( varsUnif.texnumero > 2 ) varsUnif.texnumero = 0;
std::cout << " varsUnif.texnumero=" << varsUnif.texnumero << std::endl;
break;
// case TP_c: // Changer l'affichage de l'objet texturé avec couleurs ou sans couleur
// varsUnif.utiliseCouleur = !varsUnif.utiliseCouleur;
// std::cout << " utiliseCouleur=" << varsUnif.utiliseCouleur << std::endl;
// break;
case TP_o: // Changer l'affichage des texels noirs (noir, mi-coloré, transparent)
varsUnif.afficheTexelNoir++;
if ( varsUnif.afficheTexelNoir > 2 ) varsUnif.afficheTexelNoir = 0;
std::cout << " afficheTexelNoir=" << varsUnif.afficheTexelNoir << std::endl;
break;
case TP_g: // Permuter l'affichage en fil de fer ou plein
modePolygone = ( modePolygone == GL_FILL ) ? GL_LINE : GL_FILL;
glPolygonMode( GL_FRONT_AND_BACK, modePolygone );
break;
case TP_n: // Utiliser ou non les normales calculées comme couleur (pour le débogage)
varsUnif.afficheNormales = !varsUnif.afficheNormales;
break;
case TP_ESPACE: // Permuter la rotation automatique du modèle
enmouvement = !enmouvement;
break;
default:
std::cout << " touche inconnue : " << (char) touche << std::endl;
imprimerTouches();
break;
}
}
// fonction callback pour un clic de souris
int dernierX = 0; // la dernière valeur en X de position de la souris
int dernierY = 0; // la derniere valeur en Y de position de la souris
static enum { deplaceCam, deplaceSpotDirection, deplaceSpotPosition } deplace = deplaceCam;
static bool pressed = false;
void FenetreTP::sourisClic( int button, int state, int x, int y )
{
pressed = ( state == TP_PRESSE );
if ( pressed )
{
// on vient de presser la souris
dernierX = x;
dernierY = y;
switch ( button )
{
case TP_BOUTON_GAUCHE: // Tourner l'objet
deplace = deplaceCam;
break;
case TP_BOUTON_MILIEU: // Modifier l'orientation du spot
deplace = deplaceSpotDirection;
break;
case TP_BOUTON_DROIT: // Déplacer la lumière
deplace = deplaceSpotPosition;
break;
}
}
else
{
// on vient de relâcher la souris
}
}
void FenetreTP::sourisWheel( int x, int y ) // Changer la taille du spot
{
const int sens = +1;
LightSource[0].spotAngle += sens*y;
if ( LightSource[0].spotAngle > 90.0 ) LightSource[0].spotAngle = 90.0;
if ( LightSource[0].spotAngle < 0.0 ) LightSource[0].spotAngle = 0.0;
std::cout << " spotAngle=" << LightSource[0].spotAngle << std::endl;
}
// fonction de mouvement de la souris
void FenetreTP::sourisMouvement( int x, int y )
{
if ( pressed )
{
int dx = x - dernierX;
int dy = y - dernierY;
switch ( deplace )
{
case deplaceCam:
thetaCam -= dx / 3.0;
phiCam -= dy / 3.0;
break;
case deplaceSpotDirection:
LightSource[0].spotDirection.x += 0.06 * dx;
LightSource[0].spotDirection.y -= 0.06 * dy;
// std::cout << " LightSource[0].spotDirection=" << glm::to_string(LightSource[0].spotDirection) << std::endl;
break;
case deplaceSpotPosition:
LightSource[0].position.x += 0.03 * dx;
LightSource[0].position.y -= 0.03 * dy;
// std::cout << " LightSource[0].position=" << glm::to_string(LightSource[0].position) << std::endl;
//glm::vec3 ecranPos( x, hauteur_-y, ecranLumi[2] );
//LightSource[0].position = glm::vec4(glm::unProject( ecranPos, VM, P, cloture ), 1.0);
break;
}
dernierX = x;
dernierY = y;
verifierAngles();
}
}
int main( int argc, char *argv[] )
{
// créer une fenêtre
FenetreTP fenetre( "INF2705 TP" );
// allouer des ressources et définir le contexte OpenGL
initialiser();
bool boucler = true;
while ( boucler )
{
// mettre à jour la physique
calculerPhysique( );
// affichage
fenetre.afficherScene();
fenetre.swap();
// récupérer les événements et appeler la fonction de rappel
boucler = fenetre.gererEvenement();
}
// détruire les ressources OpenGL allouées
conclure();
return 0;
}