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