/* See {rdo_camera.h}. */ #define rdo_camera_C_COPYRIGHT "Copyright © 2008 Danillo Pereira and J. Stolfi, UNICAMP" /* Last edited on 2008-08-15 17:51:27 by stolfi */ #define _GNU_SOURCE #include #include #include #include #include #include #include void rdo_camera_free(camera_t *cam) { free(cam); } void rdo_camera_find_image_axes(camera_t *cam) { /* Computes the unit direction vector {cam->t} pointing from the {scene} to the {eye}: */ cam->t = rdo_geometry_pt_pt_dir(&(cam->scene), &(cam->eye)); /* Chooses the camera's horizontal axis direction {cam->r}: */ r3_cross(&(cam->sky), &(cam->t), &(cam->r)); r3_dir(&(cam->r), &(cam->r)); /* Computes the camera's vertical axis direction {cam->s}: */ r3_cross(&(cam->t), &(cam->r), &(cam->s)); r3_dir(&(cam->s), &(cam->s)); /* Computes the scene coordinates {cam->ctr} of the image's center: */ r3_mix(1.0, &(cam->eye), -cam->dist, &(cam->t), &(cam->ctr)); } #define camera_FILE_VERSION "2008-07-28" void rdo_camera_write(FILE *wr, camera_t *cam) { /* Writes the header line: */ filefmt_write_header(wr, "camera_t", camera_FILE_VERSION); /* Here we should write comments provided by the client. */ /* Writes the external camera parameters: */ r3_gen_print(wr, &(cam->eye), "%+8.3f", "eye = ", " ", "\n"); r3_gen_print(wr, &(cam->scene), "%+8.3f", "scene = ", " ", "\n"); r3_gen_print(wr, &(cam->sky), "%+8.3f", "sky = ", " ", "\n"); fprintf(wr, "dist = %8.3f\n", cam->dist); fprintf(wr, "radius = %8.3f\n", cam->radius); /* Writes the footer line, and synchronizes the file: */ filefmt_write_footer(wr, "camera_t"); fflush(wr); } camera_t *rdo_camera_read(FILE *rd) { /* Reads the header line, and comments (if any): */ filefmt_read_header(rd, "camera_t", camera_FILE_VERSION); char *cmt = filefmt_read_comment(rd, '#'); free(cmt); //por enquanto. camera_t *cam = NOTNULL(malloc(sizeof(camera_t))); /* Reads the external camera parameters: */ nget_name_eq(rd, "eye"); cam->eye = fget_r3(rd); fget_eol(rd); nget_name_eq(rd, "scene"); cam->scene = fget_r3(rd); fget_eol(rd); nget_name_eq(rd, "sky"); cam->sky = fget_r3(rd); fget_eol(rd); cam->dist = nget_double(rd, "dist"); fget_eol(rd); cam->radius = nget_double(rd, "radius"); fget_eol(rd); /* The signs of {.dist} and {.radius} are irrelevant: */ cam->dist = fabs(cam->dist); cam->radius = fabs(cam->radius); /* Compute the derived parameters: */ rdo_camera_find_image_axes(cam); /* Reads the footer line: */ filefmt_read_footer(rd, "camera_t"); return cam; } void rdo_camera_compute_ray_direction(double x, double y, camera_t *cam, vector3_t *dir) { /* Compute the scene coordinates {pix} of the image point {h,v}: */ point3_t pix = cam->ctr; r3_mix_in(x * cam->radius, &cam->r, &pix); r3_mix_in(y * cam->radius, &cam->s, &pix); (*dir) = rdo_geometry_pt_pt_dir(&(cam->eye), &pix); } #define NEAR_CLIP_Z (1.0e-6) /* Distance (relative to {cam->dist}) from camera eye to the near clipping plane. */ void rdo_camera_project_point(point3_t *p, camera_t *cam, double *xP, double *yP) { vector3_t d; r3_sub(p, &cam->eye, &d); double x_cam = r3_dot(&d, &cam->r); double y_cam = r3_dot(&d, &cam->s); double z_cam = r3_dot(&d, &cam->t); if (z_cam > NEAR_CLIP_Z*cam->dist) { (*xP) = NAN; (*yP) = NAN; } else { double fac = -cam->dist/z_cam/cam->radius; (*xP) = fac * x_cam; (*yP) = fac * y_cam; } }