-
Notifications
You must be signed in to change notification settings - Fork 0
/
camera.cpp
96 lines (87 loc) · 3.91 KB
/
camera.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Homepage: https://github.com/ananthvk/cpp-raytracer
#include "camera.hpp"
#include "config.h"
MovableCamera::MovableCamera(const Config &conf)
: image_width(conf.image_width), image_height(conf.image_height)
{
fov = conf.camera_fov;
position = conf.camera_position;
vec3 lookat = conf.camera_lookat;
vec3 camera_up = conf.camera_up;
defocus_angle = conf.camera_defocus_angle;
focal_length = conf.camera_focal_length;
// Calculated properties
defocus_radius = focal_length * std::tan(defocus_angle / 2.0);
// Use the Gram-Schimdt process to find the orthonormal basis
// https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
// Use left-handed coordinate system, camera points towards positive z
// Create a left handed coordinate system centered at the camera's position, with one vector in
// the direction of lookat - lookfrom
direction = linalg::normalize(lookat - position);
right = linalg::normalize(linalg::cross(direction, camera_up));
up = linalg::normalize(linalg::cross(right, direction));
// Some other calculations
aspect_ratio = static_cast<double>(image_width) / image_height;
viewport_height = 2.0 * std::tan(fov / 2.0) * focal_length;
viewport_width = aspect_ratio * viewport_height;
// Spacing between two pixels on the viewport
delta_x = viewport_width / image_width;
delta_y = viewport_height / image_height;
}
Ray MovableCamera::get_ray(int row, int col, bool sample) const
{
// Find the other point on this ray, one end point is the position of
// the camera.
// In PCC (Pixel coordinate system), the center is represented as
// image_width/2, image_height/2
double x0 = std::max(image_width / 2.0, 1.0);
double y0 = std::max(image_height / 2.0, 1.0);
// x and y represent the position of the pixel in cartesian system on
// the viewport (but as pixels)
double x = col - x0;
double y = y0 - row;
// Convert the pixel values to viewport system
double vx = x * delta_x;
double vy = y * delta_y;
if (sample)
{
vx += (uniform() - 0.5) * delta_x;
vy += (uniform() - 0.5) * delta_y;
}
// Translate the viewport, keeping the camera's position as origin.
// The bug resulted in not shifting the origin of the viewport.
auto pixel_sample = position + (up * vy) + (right * vx) + (direction * focal_length);
auto ray_origin = (defocus_angle <= 0) ? position : get_defocused_origin();
auto ray_direction = pixel_sample - ray_origin;
return Ray(ray_origin, ray_direction);
}
vec3 MovableCamera::get_defocused_origin() const
{
// Get a random origin for a new ray on the plane of the actual origin of the camera
// This acts as thin lens approximation
auto p = random_in_unit_disk();
return position + (p[0] * up * defocus_radius) + (p[1] * right * defocus_radius);
}
void MovableCamera::debug_info(std::ostream &os) const
{
os << "Camera debug info" << std::endl;
os << "******************" << std::endl;
os << "Up: " << up << std::endl;
os << "Right: " << right << std::endl;
os << "Direction: " << direction << std::endl;
os << "Position: " << position << std::endl;
os << "Focal length: " << focal_length << std::endl;
os << "FOV: " << fov << std::endl;
os << "Image width: " << image_width << std::endl;
os << "Image height: " << image_height << std::endl;
os << "Aspect ratio: " << aspect_ratio << std::endl;
os << "Viewport width: " << viewport_width << std::endl;
os << "Viewport height: " << viewport_height << std::endl;
os << "Delta x:" << delta_x << std::endl;
os << "Delta y:" << delta_y << std::endl;
os << "Defocus angle:" << defocus_angle << std::endl;
os << "Defocus radius:" << defocus_radius << std::endl;
os << "Defocus u:" << defocus_radius * right << std::endl;
os << "Defocus v:" << defocus_radius * up << std::endl;
os << "******************" << std::endl;
}