]> icculus.org git repositories - taylor/freespace2.git/blob - src/mission/missiongrid.cpp
fix control binding
[taylor/freespace2.git] / src / mission / missiongrid.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Mission/MissionGrid.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module for grid specific functions
16  *
17  * $Log$
18  * Revision 1.4  2002/06/17 06:33:09  relnev
19  * ryan's struct patch for gcc 2.95
20  *
21  * Revision 1.3  2002/06/09 04:41:22  relnev
22  * added copyright header
23  *
24  * Revision 1.2  2002/05/07 03:16:46  theoddone33
25  * The Great Newline Fix
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:09  root
28  * Initial import.
29  *
30  * 
31  * 2     10/07/98 10:53a Dave
32  * Initial checkin.
33  * 
34  * 1     10/07/98 10:49a Dave
35  * 
36  * 7     10/03/97 8:55a John
37  * moved Fred's grid_render code out of MissionGrid and into Fred.   Added
38  * code to turn background under overlays grey.
39  * 
40  * 6     7/28/97 2:21p John
41  * changed vecmat functions to not return src.  Started putting in code
42  * for inline vector math.    Fixed some bugs with optimizer.
43  * 
44  * 5     7/14/97 12:04a Lawrance
45  * added function that navmap calls to draw elevation lines
46  * 
47  * 4     6/24/97 3:47p Hoffoss
48  * Changed the default grid elevation to 0 instead of -10.
49  * 
50  * 3     6/18/97 11:36p Lawrance
51  * move grid rendering code to MissionGrid.cpp
52  * 
53  * 2     6/12/97 11:25a Lawrance
54  * added grid_read_camera_controls()
55  * 
56  * 1     6/12/97 10:17a Lawrance
57  *
58  * $NoKeywords: $
59  */
60
61 #include "physics.h"
62 #include "key.h"
63 #include "missiongrid.h"
64 #include "fvi.h"
65 #include "float.h"
66 #include "3d.h"
67 #include "2d.h"
68
69 grid    Global_grid;
70 grid    *The_grid;
71 int     double_fine_gridlines = 0;
72
73 void grid_read_camera_controls( control_info * ci, float frametime )
74 {
75         float kh;
76
77         {
78                 float temp = ci->heading;
79                 float temp1 = ci->pitch;
80                 memset( ci, 0, sizeof(control_info) );
81                 ci->heading = temp;
82                 ci->pitch = temp1;
83         }
84
85         // From keyboard...
86         kh = key_down_timef(SDLK_KP_6) - key_down_timef(SDLK_KP_4);
87         if (kh == 0.0f)
88                 ci->heading = 0.0f;
89         else if (kh > 0.0f) {
90                 if (ci->heading < 0.0f)
91                         ci->heading = 0.0f;
92         } else // kh < 0
93                 if (ci->heading > 0.0f)
94                         ci->heading = 0.0f;
95         ci->heading += kh;
96
97         kh = key_down_timef(SDLK_KP_8) - key_down_timef(SDLK_KP_2);
98         if (kh == 0.0f)
99                 ci->pitch = 0.0f;
100         else if (kh > 0.0f) {
101                 if (ci->pitch < 0.0f)
102                         ci->pitch = 0.0f;
103         } else // kh < 0
104                 if (ci->pitch > 0.0f)
105                         ci->pitch = 0.0f;
106         ci->pitch += kh;
107
108         ci->bank = (key_down_timef(SDLK_KP_7) - key_down_timef(SDLK_KP_9));
109         ci->forward = (key_down_timef(SDLK_a) - key_down_timef(SDLK_z));
110         ci->sideways = (key_down_timef(SDLK_KP_3) - key_down_timef(SDLK_KP_1));
111         ci->vertical = (key_down_timef(SDLK_KP_MINUS) - key_down_timef(SDLK_KP_PLUS));
112 }
113
114 //      Project the viewer's position onto the grid plane.  If more than threshold distance
115 //      from grid center, move grid center.
116 void maybe_create_new_grid(grid* gridp, vector *pos, matrix *orient, int force)
117 {
118         int roundoff;
119         plane   tplane;
120         vector  gpos, tmp, c;
121         float   dist_to_plane;
122         float   square_size, ux, uy, uz;
123
124         ux = tplane.A = gridp->gmatrix.v.uvec.xyz.x;
125         uy = tplane.B = gridp->gmatrix.v.uvec.xyz.y;
126         uz = tplane.C = gridp->gmatrix.v.uvec.xyz.z;
127         tplane.D = gridp->planeD;
128
129         compute_point_on_plane(&c, &tplane, pos);
130         dist_to_plane = fl_abs(vm_dist_to_plane(pos, &gridp->gmatrix.v.uvec, &c));
131         square_size = 1.0f;
132         while (dist_to_plane >= 25.0f)
133         {
134                 square_size *= 10.0f;
135                 dist_to_plane /= 10.0f;
136         }
137         
138         if (fvi_ray_plane(&gpos, &gridp->center, &gridp->gmatrix.v.uvec, pos, &orient->v.fvec, 0.0f)<0.0f)      {
139                 vector p;
140                 vm_vec_scale_add(&p,pos,&orient->v.fvec, 100.0f );
141                 compute_point_on_plane(&gpos, &tplane, &p );
142         }
143
144         if (vm_vec_dist(&gpos, &c) > 50.0f * square_size)
145         {
146                 vm_vec_sub(&tmp, &gpos, &c);
147                 vm_vec_normalize(&tmp);
148                 vm_vec_scale_add(&gpos, &c, &tmp, 50.0f * square_size);
149         }
150
151         roundoff = (int) square_size * 10;
152         if (!ux)
153                 gpos.xyz.x = fl_roundoff(gpos.xyz.x, roundoff);
154         if (!uy)
155                 gpos.xyz.y = fl_roundoff(gpos.xyz.y, roundoff);
156         if (!uz)
157                 gpos.xyz.z = fl_roundoff(gpos.xyz.z, roundoff);
158
159         if ((square_size != gridp->square_size) ||
160                 (gpos.xyz.x != gridp->center.xyz.x) ||
161                 (gpos.xyz.y != gridp->center.xyz.y) ||
162                 (gpos.xyz.z != gridp->center.xyz.z) || force)
163         {
164                 gridp->square_size = square_size;
165                 gridp->center = gpos;
166                 modify_grid(gridp);
167         }
168 }
169
170 //      Create a grid
171 //      *forward is vector pointing forward
172 //      *right is vector pointing right
173 //      *center is center point of grid
174 //      length is length of grid
175 //      width is width of grid
176 //      square_size is size of a grid square
177 //      For example:
178 //              *forward = (0.0, 0.0, 1.0)
179 //              *right   = (1.0, 0.0, 0.0)
180 //              *center = (0.0, 0.0, 0.0)
181 //              nrows = 10
182 //              ncols =  50.0
183 //              square_size = 10.0
184 //      will generate a grid of squares 10 long by 5 wide.
185 //      Each grid square will be 10.0 x 10.0 units.
186 //      The center of the grid will be at the global origin.
187 //      The grid will be parallel to the xz plane (because the normal is 0,1,0).
188 //      (In fact, it will be the xz plane because it is centered on the origin.)
189 //
190 //      Stuffs grid in *gridp.  If gridp == NULL, mallocs and returns a grid.
191 grid *create_grid(grid *gridp, vector *forward, vector *right, vector *center, int nrows, int ncols, float square_size)
192 {
193         int     i, ncols2, nrows2, d = 1;
194         vector  dfvec, drvec, cur, cur2, tvec, uvec, save, save2;
195
196         SDL_assert(square_size > 0.0);
197         if (double_fine_gridlines)
198                 d = 2;
199
200         if (gridp == NULL)
201                 gridp = (grid *) malloc(sizeof(grid));
202
203         SDL_assert(gridp);
204
205         gridp->center = *center;
206         gridp->square_size = square_size;
207
208         //      Create the plane equation.
209         SDL_assert(!IS_VEC_NULL(forward));
210         SDL_assert(!IS_VEC_NULL(right));
211
212         vm_vec_copy_normalize(&dfvec, forward);
213         vm_vec_copy_normalize(&drvec, right);
214
215         vm_vec_cross(&uvec, &dfvec, &drvec);
216         
217         SDL_assert(!IS_VEC_NULL(&uvec));
218
219         gridp->gmatrix.v.uvec = uvec;
220
221         gridp->planeD = -(center->xyz.x * uvec.xyz.x + center->xyz.y * uvec.xyz.y + center->xyz.z * uvec.xyz.z);
222         SDL_assert(!isnan(gridp->planeD));
223
224         gridp->gmatrix.v.fvec = dfvec;
225         gridp->gmatrix.v.rvec = drvec;
226
227         vm_vec_scale(&dfvec, square_size);
228         vm_vec_scale(&drvec, square_size);
229
230         vm_vec_scale_add(&cur, center, &dfvec, (float) -nrows * d / 2);
231         vm_vec_scale_add2(&cur, &drvec, (float) -ncols * d / 2);
232         vm_vec_scale_add(&cur2, center, &dfvec, (float) -nrows * 5 / 2);
233         vm_vec_scale_add2(&cur2, &drvec, (float) -ncols * 5 / 2);
234         save = cur;
235         save2 = cur2;
236
237         gridp->ncols = ncols;
238         gridp->nrows = nrows;
239         ncols2 = ncols / 2;
240         nrows2 = nrows / 2;
241         SDL_assert(ncols < MAX_GRIDLINE_POINTS && nrows < MAX_GRIDLINE_POINTS);
242
243         // Create the points along the edges of the grid, so we can just draw lines
244         // between them to form the grid.  
245         for (i=0; i<=ncols*d; i++) {
246                 gridp->gpoints1[i] = cur;  // small, dark gridline points
247                 vm_vec_scale_add(&tvec, &cur, &dfvec, (float) nrows * d);
248                 gridp->gpoints2[i] = tvec;
249                 vm_vec_add2(&cur, &drvec);
250         }
251
252         for (i=0; i<=ncols2; i++) {
253                 gridp->gpoints5[i] = cur2;  // large, brighter gridline points
254                 vm_vec_scale_add(&tvec, &cur2, &dfvec, (float) nrows2 * 10);
255                 gridp->gpoints6[i] = tvec; 
256                 vm_vec_scale_add2(&cur2, &drvec, 10.0f);
257         }
258
259         cur = save;
260         cur2 = save2;
261         for (i=0; i<=nrows*d; i++) {
262                 gridp->gpoints3[i] = cur;  // small, dark gridline points
263                 vm_vec_scale_add(&tvec, &cur, &drvec, (float) ncols * d);
264                 gridp->gpoints4[i] = tvec;
265                 vm_vec_add2(&cur, &dfvec);
266         }
267
268         for (i=0; i<=nrows2; i++) {
269                 gridp->gpoints7[i] = cur2;  // large, brighter gridline points
270                 vm_vec_scale_add(&tvec, &cur2, &drvec, (float) ncols2 * 10);
271                 gridp->gpoints8[i] = tvec;
272                 vm_vec_scale_add2(&cur2, &dfvec, 10.0f);
273         }
274
275         return gridp;
276 }
277
278 //      Create a nice grid -- centered at origin, 10x10, 10.0 size squares, in xz plane.
279 grid *create_default_grid(void)
280 {
281         grid    *rgrid;
282         vector  fvec, rvec, cvec;
283
284         rgrid = create_grid(&Global_grid, vm_vec_make(&fvec, 0.0f, 0.0f, 1.0f),
285                 vm_vec_make(&rvec, 1.0f, 0.0f, 0.0f),
286                 vm_vec_make(&cvec, 0.0f, 0.0f, 0.0f), 100, 100, 5.0f);
287
288         physics_init(&rgrid->physics);
289         return rgrid;
290 }
291
292 //      Rotate and project points and draw a line.
293 void rpd_line(vector *v0, vector *v1)
294 {
295         vertex  tv0, tv1;
296
297         g3_rotate_vertex(&tv0, v0);
298         g3_rotate_vertex(&tv1, v1);
299         g3_draw_line(&tv0, &tv1);
300 }
301
302
303 void modify_grid(grid *gridp)
304 {
305         create_grid(gridp, &gridp->gmatrix.v.fvec, &gridp->gmatrix.v.rvec, &gridp->center,
306                 gridp->nrows, gridp->ncols, gridp->square_size);
307 }
308
309 void grid_render_elevation_line(vector *pos, grid* gridp)
310 {
311         vector  gpos;   //      Location of point on grid.
312         vector  tpos;
313         float           dxz;
314         plane           tplane;
315         vector  *gv;
316         
317         tplane.A = gridp->gmatrix.v.uvec.xyz.x;
318         tplane.B = gridp->gmatrix.v.uvec.xyz.y;
319         tplane.C = gridp->gmatrix.v.uvec.xyz.z;
320         tplane.D = gridp->planeD;
321
322         compute_point_on_plane(&gpos, &tplane, pos);
323
324         dxz = vm_vec_dist(pos, &gpos)/8.0f;
325
326         gv = &gridp->gmatrix.v.uvec;
327         if (gv->xyz.x * pos->xyz.x + gv->xyz.y * pos->xyz.y + gv->xyz.z * pos->xyz.z < -gridp->planeD)
328                 gr_set_color(127, 127, 127);
329         else
330                 gr_set_color(255, 255, 255);   // white
331
332         rpd_line(&gpos, pos);   //      Line from grid to object center.
333
334         tpos = gpos;
335
336         vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.rvec, -dxz/2);
337         vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.fvec, -dxz/2);
338         
339         vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.rvec, dxz/2);
340         vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.fvec, dxz/2);
341         
342         rpd_line(&gpos, &tpos);
343
344         vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.rvec, dxz);
345         vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.rvec, -dxz);
346
347         rpd_line(&gpos, &tpos);
348 }