gKit2 light
tuto_transform.cpp
Go to the documentation of this file.
1 
3 
4 #include "mat.h"
5 #include "wavefront.h"
6 
7 #include "orbiter.h"
8 #include "draw.h"
9 #include "app.h"
10 
11 
12 // renvoie vrai si la boite englobante est au moins partiellement visible
13 bool visible( const Transform& mvp, const Point& pmin, const Point& pmax )
14 {
15  int planes[6] = { };
16 
17  // enumere les 8 sommets de la boite englobante
18  for(unsigned int i= 0; i < 8; i++)
19  {
20  Point p= pmin;
21  if(i & 1) p.x= pmax.x;
22  if(i & 2) p.y= pmax.y;
23  if(i & 4) p.z= pmax.z;
24 
25  // transformation du point homogene (x, y, z, w= 1)
26  vec4 h= mvp(vec4(p));
27 
28  // teste la position du point homogene par rapport aux 6 faces de la region visible
29  if(h.x < -h.w) planes[0]++; // trop a gauche
30  if(h.x > h.w) planes[1]++; // trop a droite
31 
32  if(h.y < -h.w) planes[2]++; // trop bas
33  if(h.y > h.w) planes[3]++; // trop haut
34 
35  if(h.z < -h.w) planes[4]++; // trop pres
36  if(h.z > h.w) planes[5]++; // trop loin
37  }
38 
39  // verifie si tous les sommets sont du "mauvais cote" d'une seule face, planes[i] == 8
40  for(unsigned int i= 0; i < 6; i++)
41  if(planes[i] == 8)
42  return false; // la boite englobante n'est pas visible
43 
44  // l'objet doit etre visible, ou pas, il faut aussi le test dans l'autre sens...
45  return true;
46 }
47 
48 
49 class TP : public App
50 {
51 public:
52  // constructeur : donner les dimensions de l'image, et eventuellement la version d'openGL.
53  TP( ) : App(1024, 640) {}
54 
55  int init( )
56  {
57  // volume visible par une camera, un cube -1 1
58  m_frustum= read_mesh("data/frustum.obj");
59 
60  // grille / plan de reference
61  m_grid.create(GL_LINES);
62  for(int x= 0; x < 10; x++)
63  {
64  float px= (float) x - 5.f + 0.5f;
65  m_grid.vertex(px, 0, -4.5f);
66  m_grid.vertex(px, 0, 4.5f);
67  }
68 
69  for(int z= 0; z < 10; z++)
70  {
71  float pz= (float) z - 5.f + 0.5f;
72  m_grid.vertex(-4.5f, 0, pz);
73  m_grid.vertex(4.5f, 0, pz);
74  }
75 
76  // charge un objet a afficher
77  m_objet= read_mesh("data/bigguy.obj");
78 
79  // conserve (les extremites de) sa boite englobante
80  m_objet.bounds(m_pmin, m_pmax);
81  m_camera.lookat(m_pmin, m_pmax);
82  //~ m_camera.lookat(Point(), 10);
83 
84  m_objet.default_color(Green());
85 
86  // etat openGL par defaut
87  glClearColor(0.2f, 0.2f, 0.2f, 1.f); // couleur par defaut de la fenetre
88 
89  glClearDepth(1.f); // profondeur par defaut
90  glDepthFunc(GL_LESS); // ztest, conserver l'intersection la plus proche de la camera
91  glEnable(GL_DEPTH_TEST); // activer le ztest
92 
93  return 0; // ras, pas d'erreur
94  }
95 
96  // destruction des objets de l'application
97  int quit( )
98  {
99  m_frustum.release();
100  m_grid.release();
101  m_objet.release();
102  glDeleteTextures(1, &m_texture);
103 
104  return 0;
105  }
106 
107  int update( const float time, const float delta )
108  {
109  // modifier l'orientation du cube a chaque image.
110  // time est le temps ecoule depuis le demarrage de l'application, en millisecondes,
111  // delta est le temps ecoule depuis l'affichage de la derniere image / le dernier appel a draw(), en millisecondes.
112 
113  m_model= RotationY(time / 20);
114  return 0;
115  }
116 
117  // dessiner une nouvelle image
118  int render( )
119  {
120  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
121 
122  // deplace la camera
123  int mx, my;
124  unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
125 
126  if(key_state(' '))
127  {
128  // deplace la camera "normale"
129  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
130  m_camera.rotation((float) mx, (float) my);
131  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
132  m_camera.move((float) mx);
133  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
134  m_camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
135  }
136  else
137  {
138  // deplace l'observateur
139  if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
140  m_observer.rotation((float) mx / 10, (float) my / 10);
141  else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
142  m_observer.move((float) mx / 10);
143  else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
144  m_observer.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
145  }
146 
147  // affiche l'objet en rouge, si sa boite englobante n'est pas visible pour la camera.
148  if(visible(m_camera.projection((float) window_width(), (float)window_height(), 45) * m_camera.view() * m_model, m_pmin, m_pmax))
149  m_objet.default_color(Green());
150  else
151  m_objet.default_color(Red());
152 
153 
154  Transform view= m_observer.view();
155  Transform projection= Perspective(45, (float) window_width() / (float) window_height(), .1f, 1000.f);
156 
157  static bool wireframe= false;
158  if(key_state(' '))
159  {
160  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
161 
162  // afficher le point de vue "normal"
163  draw(m_grid, m_camera);
164  draw(m_objet, m_model, m_camera);
165  }
166  else
167  {
168  if(key_state('w'))
169  {
170  clear_key_state('w');
171  wireframe= !wireframe;
172  }
173 
174  if(!wireframe)
175  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
176  else
177  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
178 
179  #if 1
180  // afficher le volume visible de la camera dans le repere monde
181  draw(m_grid, Identity(), view, projection);
182  draw(m_frustum, Inverse(m_camera.projection((float) window_width(), (float) window_height(), 45) * m_camera.view()), view, projection);
183  draw(m_objet, m_model, view, projection);
184 
185  #else
186  // afficher dans le repere image
187  draw(m_grid, m_camera.projection(window_width(), window_height(), 45) * m_camera.view(), view, projection);
188  draw(m_frustum, m_camera.projection(window_width(), window_height(), 45) * m_camera.view() * Inverse(m_camera.projection(window_width(), window_height(), 45) * m_camera.view()), view, projection);
189  // remarque : ca se simplifie non ??
190  draw(m_objet, m_camera.projection(window_width(), window_height(), 45) * m_camera.view() * m_model, view, projection);
191  #endif
192  }
193 
194  return 1;
195  }
196 
197 protected:
198  Transform m_model;
199  Mesh m_frustum;
200  Mesh m_objet;
201  Mesh m_grid;
202  GLuint m_texture;
203  Orbiter m_camera;
204  Orbiter m_observer;
205 
206  Point m_pmin, m_pmax;
207 };
208 
209 
210 int main( int argc, char **argv )
211 {
212  TP tp;
213  tp.run();
214 
215  return 0;
216 }
classe application.
Definition: app.h:20
int run()
execution de l'application.
Definition: app.cpp:36
representation d'un objet / maillage.
Definition: mesh.h:112
unsigned int vertex(const vec3 &p)
insere un sommet de position p, et ses attributs (s'ils sont definis par color(), texcoord(),...
Definition: mesh.cpp:109
void bounds(Point &pmin, Point &pmax) const
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:501
Color default_color() const
renvoie la couleur par defaut du mesh, utilisee si les sommets n'ont pas de couleur associee.
Definition: mesh.h:284
int create(const GLenum primitives)
construit les objets openGL.
Definition: mesh.cpp:16
void release()
detruit les objets openGL.
Definition: mesh.cpp:62
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet.
Definition: orbiter.h:17
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
Transform projection(const int width, const int height, const float fov)
fixe la projection reglee pour une image d'aspect width / height, et une demi ouverture de fov degres...
Definition: orbiter.cpp:47
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
Definition: alpha.cpp:59
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int update(const float time, const float delta)
a deriver et redefinir pour animer les objets en fonction du temps.
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:29
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition: window.cpp:48
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition: window.cpp:42
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:25
Color Red()
utilitaire. renvoie une couleur rouge.
Definition: color.cpp:41
Color Green()
utilitaire. renvoie une couleur verte.
Definition: color.cpp:46
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:197
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:242
Transform Perspective(const float fov, const float aspect, const float znear, const float zfar)
renvoie la matrice representant une transformation projection perspective.
Definition: mat.cpp:329
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes....
Definition: wavefront.cpp:14
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168