1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgKeyFlier.h 1924 2004-04-06 13:32:26Z sjbaker $
22 */
23 
24 
25 #ifndef _SSG_KEYFLIER_H_
26 #define _SSG_KEYFLIER_H_
27 
28 /***********************************************\
29 *                                               *
30 * SSG_KEYFLIER.H                                *
31 *                                               *
32 *  This file contains inline functions that     *
33 *  provide an ESIG-like keyboard-driven         *
34 *  flying carpet flight mode.                   *
35 *                                               *
36 *  Simply declare an instance of this class     *
37 *  somewhere in your program - and call the     *
38 *  'incoming_keystroke' routine every time a    *
39 *  relevent character is typed - call the       *
40 *  'update' function once per frame and the     *
41 *  'get_coord' function whenever you need new   *
42 *  coordinates. Other handy functions are also  *
43 *  available.                                   *
44 *                                               *
45 *  It's handy to use the 'Keyboard' class in    *
46 *  'tty_port.h' to provide the incoming keys.   *
47 *                                               *
48 \***********************************************/
49 
50 typedef void (*queryFunc)(float,float,float,float,float,float) ;
51 typedef void (*exitFunc)(int) ;
52 
53 class ssgKeyFlier
54 {
55 protected:
56   float    tscale ;
57   float    rscale ;
58   sgCoord  curr_pos  ;
59   sgCoord  reset_pos ;
60   sgCoord  last_pos  ;
61   sgCoord  curr_vel  ;
62   sgCoord  velocity  ;
63 
64   queryFunc query_action ;
65   exitFunc  exit_action  ;
66 
67 public:
ssgKeyFlier()68   ssgKeyFlier ()
69   {
70     query_action = NULL ;
71     exit_action  = NULL ;
72 
73     tscale = 1.0 ;
74     rscale = 1.0 ;
75     sgZeroVec3 ( reset_pos.xyz ) ; sgZeroVec3 ( reset_pos.hpr ) ;
76     sgZeroVec3 (  last_pos.xyz ) ; sgZeroVec3 (  last_pos.hpr ) ;
77     sgZeroVec3 (  velocity.xyz ) ; sgZeroVec3 (  velocity.hpr ) ;
78     update   () ;
79   }
80 
set_query_action(queryFunc f)81   void set_query_action ( queryFunc f ) { query_action = f ; }
set_exit_action(exitFunc f)82   void set_exit_action  ( exitFunc  f ) { exit_action  = f ; }
83 
stop_some()84   void stop_some ()
85   {
86     velocity.xyz[0]=velocity.xyz[2]=0.0 ;
87     sgZeroVec3 ( velocity.hpr ) ;
88     update   () ;
89   }
90 
stop_all()91   void stop_all ()
92   {
93     sgZeroVec3 (  velocity.xyz ) ; sgZeroVec3 (  velocity.hpr ) ;
94     update   () ;
95   }
96 
reset()97   void reset ()
98   {
99     stop_all () ;
100     sgCopyVec3 (  last_pos.xyz, reset_pos.xyz ) ;
101     sgCopyVec3 (  last_pos.hpr, reset_pos.hpr ) ;
102     update   () ;
103   }
104 
get_scale_factors(float * translation_scale_factor,float * rotation_scale_factor)105   void get_scale_factors ( float *translation_scale_factor, float *rotation_scale_factor )
106   {
107     if ( rotation_scale_factor != NULL )
108       *rotation_scale_factor = rscale ;
109 
110     if ( translation_scale_factor != NULL )
111       *translation_scale_factor = tscale ;
112   }
113 
114   /* Scale factors are in meters-per-update and degrees-per-update */
115 
set_scale_factors(float translation_scale_factor,float rotation_scale_factor)116   void set_scale_factors ( float translation_scale_factor, float rotation_scale_factor )
117   {
118     rscale =    rotation_scale_factor ;
119     tscale = translation_scale_factor ;
120   }
121 
122 
set_xyz_scale(float translation_scale_factor)123   void set_xyz_scale ( float translation_scale_factor )
124   {
125     tscale = translation_scale_factor ;
126   }
127 
128 
set_hpr_scale(float rotation_scale_factor)129   void set_hpr_scale ( float rotation_scale_factor )
130   {
131     rscale =    rotation_scale_factor ;
132   }
133 
134 
set_reset(sgCoord * pos)135   void set_reset ( sgCoord *pos )
136   {
137     sgCopyCoord ( & reset_pos, pos ) ;
138   }
139 
get_velocity()140   sgCoord *get_velocity ()
141   {
142     sgCopyCoord ( & curr_vel, & velocity ) ;
143     return & curr_vel ;
144   }
145 
set_velocity(sgCoord * vel)146   void set_velocity ( sgCoord *vel )
147   {
148     stop_all () ;
149     sgCopyCoord ( & velocity, vel ) ;
150     update   () ;
151   }
152 
get_coord()153   sgCoord *get_coord ()
154   {
155     sgCopyCoord ( & curr_pos, & last_pos ) ;
156     return & curr_pos ;
157   }
158 
159   void set_coord ( sgCoord *pos, int noStop = 0 )
160   {
161     if ( ! noStop ) stop_all () ;
162     sgCopyCoord ( & last_pos, pos ) ;
163     update   () ;
164   }
165 
166   void show_help ( FILE *fd = stderr )
167   {
168     fprintf ( fd, "ssgKeyFlier HELP.\n" ) ;
169     fprintf ( fd, "=================\n\n" ) ;
170     fprintf ( fd, "f  : Faster - Make translational controls more sensitive.\n" ) ;
171     fprintf ( fd, "F  : Faster - Make rotational    controls more sensitive.\n" ) ;
172     fprintf ( fd, "s  : Slower - Make translational controls less sensitive.\n" ) ;
173     fprintf ( fd, "S  : Slower - Make rotational    controls less sensitive.\n" ) ;
174     fprintf ( fd, "*,/: Same as 'f' and 's'.\n" ) ;
175     fprintf ( fd, "r/R: Reset  - Reset eyepoint to pre-defined position.\n" ) ;
176     fprintf ( fd, "h/H: Help   - Display this help message.\n" ) ;
177     fprintf ( fd, "^C :        - Exit.\n" ) ;
178     fprintf ( fd, "?  :        - Where am I?\n" ) ;
179     fprintf ( fd, "5  : Stop rotation & slew     0 : Stop all movement.\n");
180     fprintf ( fd, "2  : Pitch Up                 8 : Pitch Down    \n");
181     fprintf ( fd, "4  : Yaw Left                 6 : Yaw Right\n");
182     fprintf ( fd, "7  : Roll Left                9 : Roll Right    \n");
183     fprintf ( fd, "1  : Translate Left.          3 : Translate Right\n");
184     fprintf ( fd, "+/,: Translate Down           - : Translate Up\n");
185     fprintf ( fd, " . : Translate Backwards  ENTER : Translate Forwards\n");
186     fprintf ( fd, "[Note: Some of these controls may be overridden by the\n");
187     fprintf ( fd, "       application program.].\n");
188   }
189 
incoming_keystroke(char k)190   void incoming_keystroke ( char k )
191   {
192     switch ( k )
193     {
194       case  'h' :
195       case  'H' : show_help  () ; break ;
196       case  '/' :
197       case  'f' : tscale *= 2.0 ; break ;
198       case  'F' : rscale *= 2.0 ; break ;
199       case  '*' :
200       case  's' : tscale /= 2.0 ; break ;
201       case  'S' : rscale /= 2.0 ; break ;
202 
203       case  0x03: if ( exit_action ) exit_action( 0 ) ; exit ( 1 ) ;
204 
205       case  '?' : if ( query_action )
206                     query_action ( last_pos.xyz[0], last_pos.xyz[1], last_pos.xyz[2],
207                                    last_pos.hpr[0], last_pos.hpr[1], last_pos.hpr[2] ) ;
208                   else
209                     ulSetError ( UL_DEBUG, "ssgKeyFlier: XYZ=(%g,%g,%g), HPR=(%g,%g,%g)",
210                                  last_pos.xyz[0], last_pos.xyz[1], last_pos.xyz[2],
211                                  last_pos.hpr[0], last_pos.hpr[1], last_pos.hpr[2] ) ;
212 
213                   break ;
214       case  'r' :
215       case  'R' : reset     () ; break ;
216       case  '5' : stop_some () ; break ;
217       case  '0' : stop_all  () ; break ;
218 
219       case  '1' : velocity.xyz[0] -= tscale ; break ;
220       case  '3' : velocity.xyz[0] += tscale ; break ;
221       case  '.' : velocity.xyz[1] -= tscale ; break ;
222       case '\n' :
223       case '\r' : velocity.xyz[1] += tscale ; break ;
224       case  '+' : velocity.xyz[2] -= tscale ; break ;
225       case  '-' : velocity.xyz[2] += tscale ; break ;
226 
227       case  '6' : velocity.hpr[0] -= rscale ; break ;
228       case  '4' : velocity.hpr[0] += rscale ; break ;
229 /* Kludge to try to prevent *exact* +/-90 degree pitch terms */
230       case  '8' : velocity.hpr[1] -= rscale+0.00001f ; break ;
231       case  '2' : velocity.hpr[1] += rscale+0.00001f ; break ;
232 
233       case  '7' : velocity.hpr[2] -= rscale ; break ;
234       case  '9' : velocity.hpr[2] += rscale ; break ;
235     }
236   }
237 
isStationary()238   int isStationary ()
239   {
240     return ( velocity.hpr[0] == 0.0 &&
241              velocity.hpr[1] == 0.0 &&
242              velocity.hpr[2] == 0.0 &&
243              velocity.xyz[0] == 0.0 &&
244              velocity.xyz[1] == 0.0 &&
245              velocity.xyz[2] == 0.0 ) ;
246   }
247 
update()248   virtual void update ()
249   {
250     sgMat4 mat    ;
251     sgMat4 result ;
252     sgMat4 delta  ;
253 
254     /* Form new matrix */
255 
256     sgMakeCoordMat4 ( delta, & velocity  ) ;
257     sgMakeCoordMat4 ( mat  , & last_pos  ) ;
258     sgMultMat4      ( result, mat, delta ) ;
259     sgSetCoord      ( &last_pos, result ) ;
260   }
261 } ;
262 
263 
264 #endif
265 
266