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