/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ #include "graphics/2d.h" #include "io/key.h" #include "math/fvi.h" #include "mission/missiongrid.h" #include "render/3d.h" grid Global_grid; grid *The_grid; bool double_fine_gridlines = false; void grid_read_camera_controls( control_info * ci, float /*frametime*/ ) { float kh; { float temp = ci->heading; float temp1 = ci->pitch; memset( ci, 0, sizeof(control_info) ); ci->heading = temp; ci->pitch = temp1; } // From keyboard... kh = key_down_timef(KEY_PAD6) - key_down_timef(KEY_PAD4); if (kh == 0.0f) ci->heading = 0.0f; else if (kh > 0.0f) { if (ci->heading < 0.0f) ci->heading = 0.0f; } else // kh < 0 if (ci->heading > 0.0f) ci->heading = 0.0f; ci->heading += kh; kh = key_down_timef(KEY_PAD8) - key_down_timef(KEY_PAD2); if (kh == 0.0f) ci->pitch = 0.0f; else if (kh > 0.0f) { if (ci->pitch < 0.0f) ci->pitch = 0.0f; } else // kh < 0 if (ci->pitch > 0.0f) ci->pitch = 0.0f; ci->pitch += kh; ci->bank = (key_down_timef(KEY_PAD7) - key_down_timef(KEY_PAD9)); ci->forward = (key_down_timef(KEY_A) - key_down_timef(KEY_Z)); ci->sideways = (key_down_timef(KEY_PAD3) - key_down_timef(KEY_PAD1)); ci->vertical = (key_down_timef(KEY_PADMINUS) - key_down_timef(KEY_PADPLUS)); } // Project the viewer's position onto the grid plane. If more than threshold distance // from grid center, move grid center. void maybe_create_new_grid(grid* gridp, vec3d *pos, matrix *orient, int force) { int roundoff; plane tplane; vec3d gpos, tmp, c; float dist_to_plane; float square_size, ux, uy, uz; ux = tplane.A = gridp->gmatrix.vec.uvec.xyz.x; uy = tplane.B = gridp->gmatrix.vec.uvec.xyz.y; uz = tplane.C = gridp->gmatrix.vec.uvec.xyz.z; tplane.D = gridp->planeD; compute_point_on_plane(&c, &tplane, pos); dist_to_plane = fl_abs(vm_dist_to_plane(pos, &gridp->gmatrix.vec.uvec, &c)); square_size = 1.0f; while (dist_to_plane >= 25.0f) { square_size *= 10.0f; dist_to_plane /= 10.0f; } if (fvi_ray_plane(&gpos, &gridp->center, &gridp->gmatrix.vec.uvec, pos, &orient->vec.fvec, 0.0f)<0.0f) { vec3d p; vm_vec_scale_add(&p,pos,&orient->vec.fvec, 100.0f ); compute_point_on_plane(&gpos, &tplane, &p ); } if (vm_vec_dist(&gpos, &c) > 50.0f * square_size) { vm_vec_sub(&tmp, &gpos, &c); vm_vec_normalize(&tmp); vm_vec_scale_add(&gpos, &c, &tmp, 50.0f * square_size); } roundoff = (int) square_size * 10; if (!ux) gpos.xyz.x = fl_roundoff(gpos.xyz.x, roundoff); if (!uy) gpos.xyz.y = fl_roundoff(gpos.xyz.y, roundoff); if (!uz) gpos.xyz.z = fl_roundoff(gpos.xyz.z, roundoff); if ((square_size != gridp->square_size) || (gpos.xyz.x != gridp->center.xyz.x) || (gpos.xyz.y != gridp->center.xyz.y) || (gpos.xyz.z != gridp->center.xyz.z) || force) { gridp->square_size = square_size; gridp->center = gpos; modify_grid(gridp); } } // Create a grid // *forward is vector pointing forward // *right is vector pointing right // *center is center point of grid // length is length of grid // width is width of grid // square_size is size of a grid square // For example: // *forward = (0.0, 0.0, 1.0) // *right = (1.0, 0.0, 0.0) // *center = (0.0, 0.0, 0.0) // nrows = 10 // ncols = 50.0 // square_size = 10.0 // will generate a grid of squares 10 long by 5 wide. // Each grid square will be 10.0 x 10.0 units. // The center of the grid will be at the global origin. // The grid will be parallel to the xz plane (because the normal is 0,1,0). // (In fact, it will be the xz plane because it is centered on the origin.) // // Stuffs grid in *gridp. If gridp == NULL, mallocs and returns a grid. grid *create_grid(grid *gridp, vec3d *forward, vec3d *right, vec3d *center, int nrows, int ncols, float square_size) { int i, ncols2, nrows2, d = 1; vec3d dfvec, drvec, cur, cur2, tvec, uvec, save, save2; Assert(square_size > 0.0); if (double_fine_gridlines) d = 2; if (gridp == NULL) gridp = (grid *) vm_malloc(sizeof(grid)); Assert(gridp); gridp->center = *center; gridp->square_size = square_size; // Create the plane equation. Assert(!IS_VEC_NULL(forward)); Assert(!IS_VEC_NULL(right)); vm_vec_copy_normalize(&dfvec, forward); vm_vec_copy_normalize(&drvec, right); vm_vec_cross(&uvec, &dfvec, &drvec); Assert(!IS_VEC_NULL(&uvec)); gridp->gmatrix.vec.uvec = uvec; gridp->planeD = -(center->xyz.x * uvec.xyz.x + center->xyz.y * uvec.xyz.y + center->xyz.z * uvec.xyz.z); Assert(!fl_is_nan(gridp->planeD)); gridp->gmatrix.vec.fvec = dfvec; gridp->gmatrix.vec.rvec = drvec; vm_vec_scale(&dfvec, square_size); vm_vec_scale(&drvec, square_size); vm_vec_scale_add(&cur, center, &dfvec, (float) -nrows * d / 2); vm_vec_scale_add2(&cur, &drvec, (float) -ncols * d / 2); vm_vec_scale_add(&cur2, center, &dfvec, (float) -nrows * 5 / 2); vm_vec_scale_add2(&cur2, &drvec, (float) -ncols * 5 / 2); save = cur; save2 = cur2; gridp->ncols = ncols; gridp->nrows = nrows; ncols2 = ncols / 2; nrows2 = nrows / 2; Assert(ncols < MAX_GRIDLINE_POINTS && nrows < MAX_GRIDLINE_POINTS); // Create the points along the edges of the grid, so we can just draw lines // between them to form the grid. for (i=0; i<=ncols*d; i++) { gridp->gpoints1[i] = cur; // small, dark gridline points vm_vec_scale_add(&tvec, &cur, &dfvec, (float) nrows * d); gridp->gpoints2[i] = tvec; vm_vec_add2(&cur, &drvec); } for (i=0; i<=ncols2; i++) { gridp->gpoints5[i] = cur2; // large, brighter gridline points vm_vec_scale_add(&tvec, &cur2, &dfvec, (float) nrows2 * 10); gridp->gpoints6[i] = tvec; vm_vec_scale_add2(&cur2, &drvec, 10.0f); } cur = save; cur2 = save2; for (i=0; i<=nrows*d; i++) { gridp->gpoints3[i] = cur; // small, dark gridline points vm_vec_scale_add(&tvec, &cur, &drvec, (float) ncols * d); gridp->gpoints4[i] = tvec; vm_vec_add2(&cur, &dfvec); } for (i=0; i<=nrows2; i++) { gridp->gpoints7[i] = cur2; // large, brighter gridline points vm_vec_scale_add(&tvec, &cur2, &drvec, (float) ncols2 * 10); gridp->gpoints8[i] = tvec; vm_vec_scale_add2(&cur2, &dfvec, 10.0f); } return gridp; } // Create a nice grid -- centered at origin, 10x10, 10.0 size squares, in xz plane. grid *create_default_grid(void) { grid *rgrid; vec3d fvec, rvec, cvec; vm_vec_make(&fvec, 0.0f, 0.0f, 1.0f); vm_vec_make(&rvec, 1.0f, 0.0f, 0.0f); vm_vec_make(&cvec, 0.0f, 0.0f, 0.0f); rgrid = create_grid(&Global_grid, &fvec, &rvec, &cvec, 100, 100, 5.0f); physics_init(&rgrid->physics); return rgrid; } // Rotate and project points and draw a line. void rpd_line(const vec3d *v0, const vec3d *v1) { vertex tv0, tv1; g3_rotate_vertex(&tv0, v0); g3_rotate_vertex(&tv1, v1); g3_draw_line(&tv0, &tv1); } void modify_grid(grid *gridp) { create_grid(gridp, &gridp->gmatrix.vec.fvec, &gridp->gmatrix.vec.rvec, &gridp->center, gridp->nrows, gridp->ncols, gridp->square_size); }