/* get_camera_matrix_f: * Floating point version of get_camera_matrix(). */ void get_camera_matrix_f(MATRIX_f *m, float x, float y, float z, float xfront, float yfront, float zfront, float xup, float yup, float zup, float fov, float aspect) { MATRIX_f camera, scale; float xside, yside, zside, width, d; ASSERT(m); /* make 'in-front' into a unit vector, and negate it */ normalize_vector_f(&xfront, &yfront, &zfront); xfront = -xfront; yfront = -yfront; zfront = -zfront; /* make sure 'up' is at right angles to 'in-front', and normalize */ d = dot_product_f(xup, yup, zup, xfront, yfront, zfront); xup -= d * xfront; yup -= d * yfront; zup -= d * zfront; normalize_vector_f(&xup, &yup, &zup); /* calculate the 'sideways' vector */ cross_product_f(xup, yup, zup, xfront, yfront, zfront, &xside, &yside, &zside); /* set matrix rotation parameters */ camera.v[0][0] = xside; camera.v[0][1] = yside; camera.v[0][2] = zside; camera.v[1][0] = xup; camera.v[1][1] = yup; camera.v[1][2] = zup; camera.v[2][0] = xfront; camera.v[2][1] = yfront; camera.v[2][2] = zfront; /* set matrix translation parameters */ camera.t[0] = -(x*xside + y*yside + z*zside); camera.t[1] = -(x*xup + y*yup + z*zup); camera.t[2] = -(x*xfront + y*yfront + z*zfront); /* construct a scaling matrix to deal with aspect ratio and FOV */ width = floattan(64.0 - fov/2); get_scaling_matrix_f(&scale, width, -aspect*width, -1.0); /* combine the camera and scaling matrices */ matrix_mul_f(&camera, &scale, m); }
/* outside of cylinder projection function */ static int project_cylinder(float *f, int *i, int c) { static MATRIX_f mtx; static int virgin = TRUE; if (virgin) { MATRIX_f m1, m2; get_z_rotate_matrix_f(&m1, -64); qtranslate_matrix_f(&m1, 0, 1.75, 0); get_scaling_matrix_f(&m2, 2.0, 1.0, 1.0); matrix_mul_f(&m1, &m2, &mtx); virgin = FALSE; } while (c > 0) { float ang = (f[0] - player_pos()) * M_PI * 2.0; float xsize = view_right - view_left; float ysize = view_bottom - view_top; float size = MIN(xsize, ysize) / 2.0; float x = cos(ang); float y = sin(ang); float z = 1.0 + (1.0 - f[1]) * 4.0; float xout, yout, zout; apply_matrix_f(&mtx, x, y, z, &xout, &yout, &zout); if (yout > 1.5) return FALSE; i[0] = xout/zout * size + (view_left + view_right) / 2.0; i[1] = (yout/zout * 2 - 1) * size + (view_top + view_bottom) / 2.0; f += 2; i += 2; c -= 2; } return TRUE; }