From 97784e54aebc4bf4421e1a1a8dcc26a12852cfd6 Mon Sep 17 00:00:00 2001 From: Moritz Gmeiner Date: Sun, 31 Dec 2023 13:48:44 +0100 Subject: [PATCH] made camera movable --- src/camera.h | 107 ++++++++++++++++++++++++++++++++++++++++++--------- src/main.cc | 12 +++++- src/vec3.h | 2 +- 3 files changed, 100 insertions(+), 21 deletions(-) diff --git a/src/camera.h b/src/camera.h index ca1baca..7914d38 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,30 +1,63 @@ #pragma once +#include + #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(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(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_; diff --git a/src/main.cc b/src/main.cc index c96e20f..eaa7186 100644 --- a/src/main.cc +++ b/src/main.cc @@ -27,7 +27,7 @@ int main(int /* argc */, char* /* argv */[]) { auto mat_ground = std::make_shared(Colour(0.8, 0.8, 0.0)); auto mat_lamb = std::make_shared(Colour(0.1, 0.2, 0.5)); - auto mat_metal = std::make_shared(Colour(0.8, 0.6, 0.2), 0.0); + auto mat_metal = std::make_shared(Colour(0.9, 0.4, 0.6), 0.0); auto mat_dielec = std::make_shared(1.5, 0.0); auto mat_dielec2 = std::make_shared(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}; diff --git a/src/vec3.h b/src/vec3.h index 889dc40..edec1f9 100644 --- a/src/vec3.h +++ b/src/vec3.h @@ -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); }