made camera movable

This commit is contained in:
Moritz Gmeiner 2023-12-31 13:48:44 +01:00
commit 97784e54ae
3 changed files with 100 additions and 21 deletions

View file

@ -1,30 +1,63 @@
#pragma once
#include <cmath>
#include "raytracer.h"
#include "vec3.h"
class Camera {
public:
constexpr Camera(Vec3 centre, u32 image_width, u32 image_height, f64 focal_length)
: centre_{centre}, image_width_{image_width}, image_height_{image_height} {
constexpr f64 viewport_height = 2.0;
f64 viewport_width = viewport_height * static_cast<f64>(image_width) / image_height;
Vec3 u_viewport = viewport_width * Vec3::e_x;
Vec3 v_viewport = -viewport_height * Vec3::e_y;
d_u_pixel_ = u_viewport / image_width;
d_v_pixel_ = v_viewport / image_height;
// upper left of viewport: move from camera centre `focal_length` in z direction, then half
// of the viewport length in x and y direction respectively
auto viewport_upper_left =
centre_ - focal_length * Vec3::e_z - u_viewport / 2 - v_viewport / 2;
pixel_00_ = viewport_upper_left + 0.5 * d_u_pixel_ + 0.5 * d_v_pixel_;
constexpr Camera(Point3 centre, u32 image_width, u32 image_height, f64 focal_length)
: centre_{centre},
focal_length_{focal_length},
image_width_{image_width},
image_height_{image_height} {
Recalculate();
}
constexpr Vec3 centre() const { return centre_; }
// can be changed, need to recalculate parameters
constexpr Point3 centre() const { return centre_; }
constexpr void centre(Point3 centre) {
centre_ = centre;
Recalculate();
}
constexpr Vec3 u() const { return u_; }
constexpr Vec3 v() const { return v_; }
constexpr Vec3 w() const { return w_; }
constexpr void look_at(Point3 look_at, Vec3 up = Vec3::e_y) {
w_ = (look_at - centre_).normed();
v_ = (up - dot(up, w_) * w_).normed();
u_ = cross(v_, w_);
focal_length_ = (look_at - centre_).norm();
Recalculate();
}
constexpr void rotate(f64 deg) {
f64 rad = deg2rad(deg);
Vec3 u = std::cos(rad) * u_ + std::sin(rad) * v_;
Vec3 v = -std::sin(rad) * u_ + std::cos(rad) * v_;
u_ = u;
v_ = v;
Recalculate();
}
constexpr f64 fov_angle_v() const { return fov_deg_v_; }
constexpr void fov_angle_v(f64 fov) {
fov_deg_v_ = fov;
Recalculate();
}
// const-only accessors
constexpr Vec3 d_u_pixel() const { return d_u_pixel_; }
constexpr Vec3 d_v_pixel() const { return d_v_pixel_; }
@ -37,7 +70,43 @@ class Camera {
}
private:
Vec3 centre_;
constexpr void Recalculate() {
const f64 aspect_ratio = static_cast<f64>(image_width_) / image_height_;
f64 fov_rad_v = deg2rad(fov_deg_v_);
f64 h = std::tan(fov_rad_v / 2);
// constexpr f64 viewport_height = 2.0;
const f64 viewport_height = 2 * h * focal_length_;
f64 viewport_width = viewport_height * aspect_ratio;
Vec3 u_viewport = viewport_width * u_;
Vec3 v_viewport = -viewport_height * v_;
d_u_pixel_ = u_viewport / image_width_;
d_v_pixel_ = v_viewport / image_height_;
// upper left of viewport: move from camera centre half the viewport length in u and v
// direction respectively and focal_length` in negative w direction
auto viewport_upper_left = centre_ - u_viewport / 2 - v_viewport / 2 - focal_length_ * w_;
pixel_00_ = viewport_upper_left + 0.5 * d_u_pixel_ + 0.5 * d_v_pixel_;
}
// settable camera parameters
Point3 centre_ = Vec3::origin;
Vec3 u_ = Vec3::e_x; // points to right of camera
Vec3 v_ = Vec3::e_y; // points to up of camera
Vec3 w_ = Vec3::e_z; // points backward of camera
f64 focal_length_;
f64 fov_deg_v_ = 80;
// saved camera properties
// position of pixel 0, 0
Vec3 pixel_00_;

View file

@ -27,7 +27,7 @@ int main(int /* argc */, char* /* argv */[]) {
auto mat_ground = std::make_shared<Lambertian>(Colour(0.8, 0.8, 0.0));
auto mat_lamb = std::make_shared<Lambertian>(Colour(0.1, 0.2, 0.5));
auto mat_metal = std::make_shared<Metal>(Colour(0.8, 0.6, 0.2), 0.0);
auto mat_metal = std::make_shared<Metal>(Colour(0.9, 0.4, 0.6), 0.0);
auto mat_dielec = std::make_shared<Dielectric>(1.5, 0.0);
auto mat_dielec2 = std::make_shared<Dielectric>(0.66, 0.0);
@ -58,6 +58,16 @@ int main(int /* argc */, char* /* argv */[]) {
Camera camera{camera_centre, image_width, image_height, focal_length};
std::clog << camera.u() << newline;
std::clog << camera.v() << newline;
std::clog << camera.w() << newline << newline;
camera.look_at(Point3{0.8, 0.0, 1.0}, Vec3::e_x);
std::clog << camera.u() << newline;
std::clog << camera.v() << newline;
std::clog << camera.w() << newline << newline;
// render
Renderer renderer{camera};

View file

@ -119,7 +119,7 @@ constexpr f64 dot(const Vec3& u, const Vec3& v) {
constexpr Vec3 cross(const Vec3& u, const Vec3& v) {
return {u.y() * v.z() - u.z() - v.y(), u.z() * v.x() - u.x() * v.z(),
u.x() * v.y() - u.y() - v.x()};
u.x() * v.y() - u.y() * v.x()};
}
constexpr f64 Vec3::squared() const { return dot(*this, *this); }