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