1 /*
2
3 viewmodel.cpp
4
5 GLUI User Interface Toolkit
6 Copyright (c) 1998 Paul Rademacher
7
8 WWW: http://sourceforge.net/projects/glui/
9 Forums: http://sourceforge.net/forum/?group_id=92496
10
11 This software is provided 'as-is', without any express or implied
12 warranty. In no event will the authors be held liable for any damages
13 arising from the use of this software.
14
15 Permission is granted to anyone to use this software for any purpose,
16 including commercial applications, and to alter it and redistribute it
17 freely, subject to the following restrictions:
18
19 1. The origin of this software must not be misrepresented; you must not
20 claim that you wrote the original software. If you use this software
21 in a product, an acknowledgment in the product documentation would be
22 appreciated but is not required.
23 2. Altered source versions must be plainly marked as such, and must not be
24 misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source distribution.
26
27 */
28
29 /***********************************************************************
30
31 1996, Paul Rademacher (rademach@cs.unc.edu)
32 Oct 2003, Nigel Stewart - GLUI Code Cleaning
33
34 ************************************************************************/
35
36 #include "viewmodel.h"
37
38 #include "GL/glui.h"
39
40 #include <cstdio>
41 #include <cstdlib>
42
43 void
set_distance(const float new_distance)44 ViewModel::set_distance(const float new_distance)
45 {
46 if ( new_distance <= 0.0 ) /* Distance has to be positive */
47 return;
48
49 /* We find the current forward vector */
50 forward = lookat - eye;
51 forward.normalize();
52
53 /* Set distance */
54 distance = new_distance;
55
56 /* Find new eye point */
57 eye = lookat - forward * distance;
58 }
59
60 void
set_up(const vec3 & new_up)61 ViewModel::set_up(const vec3 &new_up)
62 {
63 up = new_up;
64 update();
65 }
66
67 void
set_up(const float x,const float y,const float z)68 ViewModel::set_up(const float x, const float y, const float z)
69 {
70 set_up(vec3(x,y,z));
71 }
72
73 void
set_eye(const vec3 & new_eye)74 ViewModel::set_eye(const vec3 &new_eye)
75 {
76 eye = new_eye;
77 update();
78 }
79
80 void
set_eye(const float x,const float y,const float z)81 ViewModel::set_eye(const float x, const float y, const float z)
82 {
83 set_eye(vec3(x,y,z));
84 }
85
86 void
set_lookat(const vec3 & new_lookat)87 ViewModel::set_lookat(const vec3 &new_lookat)
88 {
89 lookat = new_lookat;
90 update();
91 }
92
93 void
set_lookat(const float x,const float y,const float z)94 ViewModel::set_lookat(const float x, const float y, const float z)
95 {
96 set_lookat(vec3(x,y,z));
97 }
98
99
100 void
roll(const float angle)101 ViewModel::roll(const float angle)
102 {
103 mat4 rot = rotation3D( forward, angle );
104 up = rot * up;
105 update();
106 }
107
108 void
eye_yaw(const float angle)109 ViewModel::eye_yaw(const float angle)
110 {
111 vec3 eye_pt = eye - lookat; /* eye w/lookat at center */
112 mat4 rot = rotation3D( up, angle );
113
114 eye_pt = rot * eye_pt;
115 eye = lookat + eye_pt;
116
117 update();
118 }
119
120 void
eye_yaw_abs(const float angle,const vec3 & axis)121 ViewModel::eye_yaw_abs(const float angle, const vec3 &axis)
122 {
123 vec3 eye_pt = eye - lookat; /* eye w/lookat at center */
124 mat4 rot = rotation3D( axis, angle );
125
126 eye_pt = rot * eye_pt;
127 eye = lookat + eye_pt;
128
129 up = rot * up;
130
131 update();
132 }
133
134
135 void
eye_pitch(const float angle)136 ViewModel::eye_pitch(const float angle)
137 {
138 vec3 eye_pt = eye - lookat; /* eye w/lookat at center */
139 mat4 rot = rotation3D( side, angle );
140
141 eye_pt = rot * eye_pt;
142 eye = lookat + eye_pt;
143
144 up = rot * up;
145
146 update();
147 }
148
149 void
lookat_yaw(const float angle)150 ViewModel::lookat_yaw(const float angle)
151 {
152 vec3 lookat_pt = lookat - eye; /* lookat w/eye at center */
153 mat4 rot = rotation3D( up, -angle );
154
155 lookat_pt = rot * lookat_pt;
156 lookat = eye + lookat_pt;
157
158 update();
159 }
160
161 void
lookat_pitch(const float angle)162 ViewModel::lookat_pitch(const float angle)
163 {
164 vec3 lookat_pt = lookat - eye; /* lookat w/eye at center */
165 mat4 rot = rotation3D( side, -angle );
166
167 lookat_pt = rot * lookat_pt;
168 lookat = eye + lookat_pt;
169
170 up = rot * up;
171
172 update();
173 }
174
175 void
reset_up(const int axis_num)176 ViewModel::reset_up(const int axis_num)
177 {
178 float eye_distance = (lookat - eye).length();
179 eye[axis_num] = lookat[axis_num];
180 /* Bring eye to same level as lookat */
181
182 vec3 vector = eye - lookat;
183 vector.normalize();
184 vector *= eye_distance;
185
186 eye = lookat + vector;
187 up.set( 0.0, 0.0, 0.0 );
188 up[axis_num] = 1.0;
189
190 update();
191 }
192
193 void
reset_up()194 ViewModel::reset_up()
195 {
196 reset_up( VY ); /* Resets to the Y axis */
197 }
198
199 void
move(const float side_move,const float up_move,const float forw_move)200 ViewModel::move(const float side_move, const float up_move, const float forw_move)
201 {
202 eye += forward * forw_move;
203 eye += side * side_move;
204 eye += up * up_move;
205 lookat += forward * forw_move;
206 lookat += side * side_move;
207 lookat += up * up_move;
208 update();
209 }
210
211 void
move(const vec3 & v)212 ViewModel::move(const vec3 &v) /* A vector version of the above command */
213 {
214 move( v[VX], v[VY], v[VZ] );
215 }
216
217 void
move_by_eye(const vec3 & new_eye)218 ViewModel::move_by_eye(const vec3 &new_eye)
219 {
220 vec3 diff = new_eye - eye;
221
222 eye += diff;
223 lookat += diff;
224
225 update();
226 }
227
228 void
move_by_lookat(const vec3 & new_lookat)229 ViewModel::move_by_lookat(const vec3 &new_lookat)
230 {
231 vec3 diff = new_lookat - lookat;
232
233 lookat += diff;
234 eye += diff;
235
236 update();
237 }
238
239 void
move_abs(const vec3 & v)240 ViewModel::move_abs(const vec3 &v)
241 {
242 eye += v;
243 lookat += v;
244
245 update();
246 }
247
248 void
rot_about_eye(const mat4 & rot)249 ViewModel::rot_about_eye(const mat4 &rot)
250 {
251 vec3 view = lookat - eye;
252
253 view = rot * view;
254 up = rot * up;
255
256 lookat = eye + view;
257
258 update();
259 }
260
261 void
rot_about_lookat(const mat4 & rot)262 ViewModel::rot_about_lookat(const mat4 &rot)
263 {
264 // NOT QUITE RIGHT YET
265
266 vec3 view = eye - lookat;
267
268 view = rot * view;
269 up = rot * up;
270
271 eye = lookat + view;
272
273 update();
274 }
275
276 void
make_mtx()277 ViewModel::make_mtx()
278 {
279 update();
280
281 mtx[0][0]=side[VX]; mtx[0][1]=up[VX]; mtx[0][2]=forward[VX]; mtx[0][3]=0.0;
282 mtx[1][0]=side[VY]; mtx[1][1]=up[VY]; mtx[1][2]=forward[VY]; mtx[1][3]=0.0;
283 mtx[2][0]=side[VZ]; mtx[2][1]=up[VZ]; mtx[2][2]=forward[VZ]; mtx[2][3]=0.0;
284 mtx[3][0]=0.0; mtx[3][1]=0.0; mtx[3][2]= 0.0; mtx[3][3]=1.0;
285 }
286
287 void
load_to_openGL()288 ViewModel::load_to_openGL()
289 {
290 mat4 m;
291
292 make_mtx();
293
294 glMatrixMode( GL_MODELVIEW );
295 glLoadIdentity();
296 glMultMatrixf( (float*) &mtx[0][0]);
297 glTranslatef( -eye[VX], -eye[VY], -eye[VZ] );
298 }
299
300 void
load_to_openGL_noident()301 ViewModel::load_to_openGL_noident()
302 {
303 mat4 m;
304
305 make_mtx();
306
307 glMatrixMode( GL_MODELVIEW );
308 glMultMatrixf( (float*) &mtx[0][0]);
309 glTranslatef( -eye[VX], -eye[VY], -eye[VZ] );
310 }
311
312 void
reset()313 ViewModel::reset()
314 {
315 up.set( 0.0, 1.0, 0.0 );
316
317 eye.set(0.0,0.0,10.0);
318 lookat.set(0.0,0.0,0.0);
319
320 mtx = identity3D();
321
322 update();
323 }
324
ViewModel()325 ViewModel::ViewModel()
326 {
327 reset();
328 }
329
330 void
update()331 ViewModel::update()
332 {
333 /* get proper side and forward vectors, and distance */
334 forward = -(lookat - eye);
335 distance = forward.length();
336 forward /= distance;
337
338 side = up ^ forward;
339 up = forward ^ side;
340
341 forward.normalize();
342 up.normalize();
343 side.normalize();
344 }
345
346
347 void
dump(FILE * output) const348 ViewModel::dump(FILE *output) const
349 {
350 fprintf( output, "Viewmodel: \n" );
351 eye.print( output, " eye" );
352 lookat.print( output, " lookat" );
353 up.print( output, " up" );
354 side.print( output, " side" );
355 forward.print(output, " forward");
356 mtx.print( output, " mtx" );
357 }
358