Moka controlers
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros
operations-eye-positioning.cc
Go to the documentation of this file.
1 /*
2  * lib-controler : Un contrôleur générique de scène 3D.
3  * Copyright (C) 2004, Moka Team, Université de Poitiers, Laboratoire SIC
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * Copyright (C) 2009, Guillaume Damiand, CNRS, LIRIS,
6  * guillaume.damiand@liris.cnrs.fr, http://liris.cnrs.fr/
7  *
8  * This file is part of lib-controler
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 //******************************************************************************
25 #include "g-map-vertex.hh"
26 #include "controler.hh"
27 #include "view-precompile.hh"
28 #include <cassert>
29 
30 using namespace GMap3d;
31 
32 
33 //******************************************************************************
34 
35 // Fonction modulo avec des nombres flottants.
36 // Le resultat est toujours positif.
37 
38 static float fpmod(float div,float mod)
39 {
40  float res = fmod(div,mod);
41  return (res < 0 ? res + mod : res);
42 }
43 
44 
45 //******************************************************************************
46 
47 //effectue un produit matriciel
48 
49 static CVertex multMatrixVector(const float mat[3][3], float x, float y, float z)
50 {
51  return CVertex(
52  mat[0][0] * x + mat[0][1] * y + mat[0][2] * z,
53  mat[1][0] * x + mat[1][1] * y + mat[1][2] * z,
54  mat[2][0] * x + mat[2][1] * y + mat[2][2] * z);
55 }
56 
57 //******************************************************************************
58 
59 //calcule la matrice de rotation autour de l'axe axe avec un angle 'angle'
60 
61 static void createRotationMatrix(float mat[3][3], float angle, const CVertex & axe)
62 {
63  float cos_a = cosf(angle);
64  float sin_a = sinf(angle);
65  float inv_cos = 1. - cos_a;
66 
67 
68  mat[0][0] = cos_a + (inv_cos * axe.getX() * axe.getX());
69  mat[0][1] = (inv_cos * axe.getX() * axe.getY()) - (sin_a * axe.getZ());
70  mat[0][2] = (inv_cos * axe.getX() * axe.getZ()) + (sin_a * axe.getY());
71 
72  mat[1][0] = (inv_cos * axe.getX() * axe.getY()) + (sin_a * axe.getZ());
73  mat[1][1] = cos_a + (inv_cos * axe.getY() * axe.getY());
74  mat[1][2] = (inv_cos * axe.getY() * axe.getZ()) - (sin_a * axe.getX());;
75 
76  mat[2][0] = (inv_cos * axe.getX() * axe.getZ()) - (sin_a * axe.getY());
77  mat[2][1] = (inv_cos * axe.getY() * axe.getZ()) + (sin_a * axe.getX());
78  mat[2][2] = cos_a + (inv_cos * axe.getZ() * axe.getZ());
79 }
80 
81 //******************************************************************************
82 
83 // Calcule les coordonnees de l'oeil.
84 
85 void CControler::calculEyePosition(TViewId AView, CParameterEyePosition * eye_pos, CParameterAimedPosition * pt_view)
86 {
87  float alpha_rad = rad(fpmod(eye_pos -> getRotationAlpha() - 90.0, 360));
88  float beta_rad = rad(fpmod(eye_pos -> getRotationBeta() + 90.0, 360));
89  float distance = eye_pos -> getDistance();
90 
91  eye_coord.setX(pt_view -> getLookAt(0) + distance * cosf(alpha_rad) * sinf(beta_rad));
92  eye_coord.setY(pt_view -> getLookAt(1) + distance * sinf(alpha_rad) * sinf(beta_rad));
93  eye_coord.setZ(pt_view -> getLookAt(2) + distance * cosf(beta_rad));
94 }
95 
96 //******************************************************************************
97 
98 // Calcule les coordonnees de l'oeil.
99 
100 CVertex CControler::calculEyePosition(TViewId AView)
101 {
104  calculEyePosition(AView,eye_pos,pt_view);
105  return CVertex(eye_coord);
106 }
107 
108 
109 
110 //******************************************************************************
111 
112 // Retourne un accesseur sur les coordonnees de l'oeil
113 // precedement calculees avec les fonctions horizontalRotationEye(),
114 // verticalRotationEye(), moveEye() ou moveEyeLateral().
115 
116 const CVertex & CControler::getEyePosition() const
117 {
118  return eye_coord;
119 }
120 
121 
122 //******************************************************************************
123 // Operations 3D
124 //******************************************************************************
125 
126 // Effectue une rotation horizontale de la camera de 'alpha' degres.
127 
128 void CControler::horizontalRotationEye(TViewId AView,bool positive,float alpha)
129 {
132  calculEyePosition(AView,eye_pos,pt_view);
133 
134  if (alpha == 0) alpha = eye_pos -> getAngleRotation();
135  if (!positive) alpha = -alpha;
136 
137  // on ramene la camera à l'origine
138  CVertex cam_y(pt_view -> getLookAt(0) - eye_coord.getX(),
139  pt_view -> getLookAt(1) - eye_coord.getY(),
140  pt_view -> getLookAt(2) - eye_coord.getZ());
141 
142  // on tourne autour de l'axe Oz
143  float rotation_mat[3][3];
144  createRotationMatrix(rotation_mat, rad(alpha), OZ);
145  CVertex coord_pt_view = multMatrixVector(rotation_mat, cam_y.getX(),cam_y.getY(),cam_y.getZ() );
146 
147  // on remet la camera a son emplacement
148  coord_pt_view += eye_coord;
149  pt_view -> setLookAt(0,coord_pt_view.getX());
150  pt_view -> setLookAt(1,coord_pt_view.getY());
151  pt_view -> setLookAt(2,coord_pt_view.getZ());
152 
153  // on fait tourner la camera autour de la cible pour la remettre dans l'axe de visee original
154  eye_pos -> setRotationAlpha(fpmod(eye_pos -> getRotationAlpha() + alpha,360));
155 }
156 
157 
158 
159 
160 // Effectue une rotation verticale de la camera de 'beta' degres.
161 
162 void CControler::verticalRotationEye(TViewId AView,bool positive,float beta)
163 {
166  calculEyePosition(AView,eye_pos,pt_view);
167 
168  if (beta == 0) beta = eye_pos -> getAngleRotation();
169  if (!positive) beta = -beta;
170 
171  //on ramene la camera à l'origine
172  CVertex cam_y(pt_view -> getLookAt(0) - eye_coord.getX(),
173  pt_view -> getLookAt(1) - eye_coord.getY(),
174  pt_view -> getLookAt(2) - eye_coord.getZ());
175 
176  //on tourne autour de l'axe normale a la vue et a la verticale
177  CVertex axe_de_rotation = OZ * cam_y;
178  axe_de_rotation.normalize();
179 
180  float rotation_mat[3][3];
181  createRotationMatrix(rotation_mat, rad(-beta), axe_de_rotation);
182  CVertex coord_pt_view = multMatrixVector(rotation_mat, cam_y.getX(),cam_y.getY(),cam_y.getZ() );
183 
184 //on remet la camera a son emplacement
185  coord_pt_view += eye_coord;
186  pt_view -> setLookAt(0,coord_pt_view.getX());
187  pt_view -> setLookAt(1,coord_pt_view.getY());
188  pt_view -> setLookAt(2,coord_pt_view.getZ());
189 
190 //on fait tourner la camera autour de la cible pour la remttre dans l'axe de visee original
191  eye_pos -> setRotationBeta(fpmod(eye_pos -> getRotationBeta() + beta,360));
192 }
193 
194 
195 
196 
197 // Deplace la camera dans la direction de visee.
198 // 'coeff' indique la longueur du deplacement :
199 // Un nombre positif fait avancer, un nomber negatif fait reculer.
200 
201 void CControler::moveEye(TViewId AView,bool positive,float coeff)
202 {
205  calculEyePosition(AView,eye_pos,pt_view);
206 
207  if (coeff == 0) coeff = eye_pos -> getPasAvancement();
208  if (!positive) coeff = -coeff;
209 
210  CVertex direction(pt_view -> getLookAt(0) - eye_coord.getX(),
211  pt_view -> getLookAt(1) - eye_coord.getY(),
212  pt_view -> getLookAt(2) - eye_coord.getZ());
213 
214  direction.normalize();
215  direction *= coeff;
216  eye_coord += direction;
217 
218  pt_view -> setLookAt(0,pt_view -> getLookAt(0) + direction.getX());
219  pt_view -> setLookAt(1,pt_view -> getLookAt(1) + direction.getY());
220  pt_view -> setLookAt(2,pt_view -> getLookAt(2) + direction.getZ());
221 }
222 
223 //******************************************************************************
224 //Deplacement lateral de la camera :
225 // 'coeff' indique la longueur du deplacement :
226 // Un nombre positif fait avancer sur la droite, un nomber negatif sur la gauche.
227 void CControler::moveEyeLateral(TViewId AView,bool positive,float coeff)
228 {
231  calculEyePosition(AView,eye_pos,pt_view);
232 
233  if (coeff == 0) coeff = eye_pos -> getPasAvancement();
234  if (!positive) coeff = -coeff;
235 
236  CVertex avant(pt_view -> getLookAt(0) - eye_coord.getX(),
237  pt_view -> getLookAt(1) - eye_coord.getY(),
238  pt_view -> getLookAt(2) - eye_coord.getZ());
239 
240  CVertex direction=avant*OZ;
241  direction.normalize();
242  direction *= coeff;
243  eye_coord += direction;
244 
245  pt_view -> setLookAt(0,pt_view -> getLookAt(0) + direction.getX());
246  pt_view -> setLookAt(1,pt_view -> getLookAt(1) + direction.getY());
247  pt_view -> setLookAt(2,pt_view -> getLookAt(2) + direction.getZ());
248 }
249 
250 
251 //******************************************************************************
252 // Operations 2D
253 //******************************************************************************
254 
255 void CControler::moveEyeX(TViewId AView,bool positive,float coeff)
256 {
258  if (coeff == 0) coeff = getParameterEyePosition(AView) -> getPasAvancement();
259  if (!positive) coeff = -coeff;
260  pt_view -> setLookAt(0,pt_view -> getLookAt(0) + coeff);
261 }
262 
263 
264 void CControler::moveEyeY(TViewId AView,bool positive,float coeff)
265 {
267  if (coeff == 0) coeff = getParameterEyePosition(AView) -> getPasAvancement();
268  if (!positive) coeff = -coeff;
269  pt_view -> setLookAt(1,pt_view -> getLookAt(1) + coeff);
270 }
271 
272 
273 
274 void CControler::moveEyeZ(TViewId AView,bool positive,float coeff)
275 {
277  if (coeff == 0) coeff = getParameterEyePosition(AView) -> getPasAvancement();
278  if (!positive) coeff = -coeff;
279  pt_view -> setLookAt(2,pt_view -> getLookAt(2) + coeff);
280 }
281