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