diff --git a/include/camera.h b/include/camera.h index 0f68329..f8b423f 100644 --- a/include/camera.h +++ b/include/camera.h @@ -1,52 +1,29 @@ #pragma once -#include "rtweekend.h" +#include "math.h" +#include "vec3.h" +#include "ray.h" #include "image.h" class camera { - public: - camera( - point3 lookfrom, - point3 lookat, - vec3 vup, - double vfov, // vertical field of view in degrees - double aspect_ratio, - double aperture, - double focus_dist) - { - auto theta = degrees_to_radians(vfov); - auto h = tan(theta/2); - auto viewport_height = 2.0 * h; - auto viewport_width = aspect_ratio * viewport_height; +public: + camera( + point3 lookfrom, + point3 lookat, + vec3 vup, + double vfov, // vertical field of view in degrees + double aspect_ratio, + double aperture, + double focus_dist); - w_ = unit_vector(lookfrom - lookat); - u_ = unit_vector(cross(vup, w_)); - v_ = cross(w_, u_); + ray get_ray(double s, double t) const; - origin_ = lookfrom; - horizontal_ = focus_dist * viewport_width * u_; - vertical_ = focus_dist * viewport_height * v_; - lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_; - - lens_radius_ = aperture / 2; - } - - ray get_ray(double s, double t) const - { - vec3 rd = lens_radius_ * random_in_unit_disk(); - vec3 offset = (u_ * rd.x()) + (v_ * rd.y()); - - return ray( - origin_ + offset, - lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset); - } - - private: - point3 origin_; - point3 lower_left_corner_; - vec3 horizontal_; - vec3 vertical_; - vec3 u_, v_, w_; - double lens_radius_; +private: + point3 origin_; + point3 lower_left_corner_; + vec3 horizontal_; + vec3 vertical_; + vec3 u_, v_, w_; + double lens_radius_; }; diff --git a/include/material.h b/include/material.h index fb8f666..78a2ef3 100644 --- a/include/material.h +++ b/include/material.h @@ -54,7 +54,7 @@ class metal : public material colour& attenuation, ray& scattered) const { - vec3 reflected = vec3::reflect(unit_vector(r_in.direction()), rec.normal); + vec3 reflected = reflect(normalize(r_in.direction()), rec.normal); scattered = ray(rec.p, reflected + fuzz_ * vec3::random_in_unit_sphere()); attenuation = albedo_; return dot(scattered.direction(), rec.normal) > 0; @@ -79,13 +79,13 @@ class dielectric : public material attenuation = colour(1.0,1.0,1.0); double etai_over_etat = rec.front_face ? (1.0 / refraction_index_) : refraction_index_; - vec3 unit_direction = unit_vector(r_in.direction()); + vec3 unit_direction = normalize(r_in.direction()); double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0); double sin_theta = sqrt(1.0 - cos_theta*cos_theta); if (etai_over_etat * sin_theta > 1.0) { - vec3 reflected = vec3::reflect(unit_direction, rec.normal); + vec3 reflected = reflect(unit_direction, rec.normal); scattered = ray(rec.p, reflected); return true; } @@ -93,12 +93,12 @@ class dielectric : public material double reflect_prob = schlick(cos_theta, etai_over_etat); if (math::random_double() < reflect_prob) { - vec3 reflected = vec3::reflect(unit_direction, rec.normal); + vec3 reflected = reflect(unit_direction, rec.normal); scattered = ray(rec.p, reflected); return true; } - vec3 refracted = vec3::refract(unit_direction, rec.normal, etai_over_etat); + vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); scattered = ray(rec.p, refracted); return true; diff --git a/include/scene.h b/include/scene.h index dba330b..2a2f7c0 100644 --- a/include/scene.h +++ b/include/scene.h @@ -28,7 +28,7 @@ colour ray_colour(const ray& r, const hittable& world, int depth) return grey; } - vec3 unit_direction = unit_vector(r.direction()); + vec3 unit_direction = normalize(r.direction()); auto t = 0.5 * (unit_direction.y() + 1.0) + 0.5; return lerp(grey, pink, t); diff --git a/include/vec3.h b/include/vec3.h index 061c222..e591529 100755 --- a/include/vec3.h +++ b/include/vec3.h @@ -7,21 +7,12 @@ class vec3 { public: - inline static vec3 random() - { - return vec3(math::random_double(),math::random_double(),math::random_double()); - } - - inline static vec3 random(double min, double max) - { - return vec3(math::random_double(min,max),math::random_double(min,max),math::random_double(min,max)); - } - + static vec3 random(); + static vec3 random(double min, double max); static vec3 random_in_unit_disk(); static vec3 random_unit_vector(); static vec3 random_in_unit_sphere(); - static vec3 reflect(const vec3& v, const vec3& n); - static vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat); + static vec3 random_in_hemisphere(const vec3& normal); vec3() : e{0,0,0} {} vec3(double e0, double e1, double e2) : e{e0, e1, e2} {} @@ -29,43 +20,33 @@ public: double x() const { return e[0]; } double y() const { return e[1]; } double z() const { return e[2]; } + double length() const; + double length_squared() const; vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); } double operator[](int i) const { return e[i]; } double& operator[](int i) { return e[i]; } - vec3& operator+=(const vec3 &v) - { - e[0] += v.e[0]; - e[1] += v.e[1]; - e[2] += v.e[2]; - return *this; - } + vec3& operator+=(const vec3 &v); + vec3& operator*=(const double t); + vec3& operator/=(const double t); - vec3& operator*=(const double t) - { - e[0] *= t; - e[1] *= t; - e[2] *= t; - return *this; - } + friend std::ostream& operator<<(std::ostream &out, const vec3 &v); + friend vec3 operator+(const vec3 &u, const vec3 &v); + friend vec3 operator-(const vec3 &u, const vec3 &v); + friend vec3 operator*(const vec3 &u, const vec3 &v); + friend vec3 operator*(double t, const vec3 &v); + friend vec3 operator*(const vec3 &v, double t); + friend vec3 operator/(vec3 v, double t); - vec3& operator/=(const double t) - { - return *this *= 1 / t; - } + friend vec3 lerp(const vec3 &a, const vec3 &b, double t); + friend vec3 reflect(const vec3& v, const vec3& n); + friend vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat); + friend double dot(const vec3 &u, const vec3 &v); + friend vec3 cross(const vec3 &u, const vec3 &v); + friend vec3 normalize(vec3 v); - double length() const - { - return std::sqrt(length_squared()); - } - - double length_squared() const - { - return e[0]*e[0] + e[1]*e[1] + e[2]*e[2]; - } - -public: +private: double e[3]; }; @@ -73,64 +54,3 @@ public: using point3 = vec3; // 3D point using colour = vec3; // RGB colour -// utility functions - -inline std::ostream& operator<<(std::ostream &out, const vec3 &v) -{ - return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2]; -} - -inline vec3 operator+(const vec3 &u, const vec3 &v) -{ - return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]); -} - -inline vec3 operator-(const vec3 &u, const vec3 &v) -{ - return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]); -} - -inline vec3 operator*(const vec3 &u, const vec3 &v) -{ - return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]); -} - -inline vec3 operator*(double t, const vec3 &v) -{ - return vec3(t * v.e[0], t * v.e[1], t * v.e[2]); -} - -inline vec3 operator*(const vec3 &v, double t) -{ - return t * v; -} - -inline vec3 operator/(vec3 v, double t) -{ - return (1 / t) * v; -} - -inline double dot(const vec3 &u, const vec3 &v) -{ - return u.e[0] * v.e[0] - + u.e[1] * v.e[1] - + u.e[2] * v.e[2]; -} - -inline vec3 cross(const vec3 &u, const vec3 &v) -{ - return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1], - u.e[2] * v.e[0] - u.e[0] * v.e[2], - u.e[0] * v.e[1] - u.e[1] * v.e[0]); -} - -inline vec3 lerp(const vec3 &a, const vec3 &b, double t) -{ - return (1.0 - t) * a + t * b; -} - -inline vec3 unit_vector(vec3 v) -{ - return v / v.length(); -} - diff --git a/src/camera.cpp b/src/camera.cpp index 08151c7..463685c 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -15,8 +15,8 @@ camera::camera( auto viewport_height = 2.0 * h; auto viewport_width = aspect_ratio * viewport_height; - w_ = unit_vector(lookfrom - lookat); - u_ = unit_vector(cross(vup, w_)); + w_ = normalize(lookfrom - lookat); + u_ = normalize(cross(vup, w_)); v_ = cross(w_, u_); origin_ = lookfrom; diff --git a/src/camera.h b/src/camera.h deleted file mode 100644 index f8b423f..0000000 --- a/src/camera.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "math.h" -#include "vec3.h" -#include "ray.h" -#include "image.h" - -class camera -{ -public: - camera( - point3 lookfrom, - point3 lookat, - vec3 vup, - double vfov, // vertical field of view in degrees - double aspect_ratio, - double aperture, - double focus_dist); - - ray get_ray(double s, double t) const; - -private: - point3 origin_; - point3 lower_left_corner_; - vec3 horizontal_; - vec3 vertical_; - vec3 u_, v_, w_; - double lens_radius_; -}; diff --git a/src/vec3.cpp b/src/vec3.cpp index 08fd529..9b742d9 100644 --- a/src/vec3.cpp +++ b/src/vec3.cpp @@ -1,5 +1,15 @@ #include "vec3.h" +vec3 vec3::random() +{ + return vec3(math::random_double(),math::random_double(),math::random_double()); +} + +vec3 vec3::random(double min, double max) +{ + return vec3(math::random_double(min,max),math::random_double(min,max),math::random_double(min,max)); +} + vec3 vec3::random_unit_vector() { auto a = math::random_double(0, 2 * math::pi); @@ -8,20 +18,6 @@ vec3 vec3::random_unit_vector() return vec3(r*cos(a), r*sin(a), z); } -vec3 vec3::reflect(const vec3& v, const vec3& n) -{ - return v - 2*dot(v,n)*n; -} - -vec3 vec3::refract(const vec3& uv, const vec3& n, double etai_over_etat) -{ - auto cos_theta = dot(-uv, n); - vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n); - vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n; - - return r_out_parallel + r_out_perp; -} - vec3 vec3::random_in_unit_disk() { while(true) @@ -42,7 +38,7 @@ vec3 vec3::random_in_unit_sphere() } } -vec3 random_in_hemisphere(const vec3& normal) +vec3 vec3::random_in_hemisphere(const vec3& normal) { vec3 in_unit_sphere = vec3::random_in_unit_sphere(); if (dot(in_unit_sphere, normal) > 0.0) @@ -55,3 +51,107 @@ vec3 random_in_hemisphere(const vec3& normal) } } +vec3 normalize(vec3 v) +{ + return v / v.length(); +} + +double vec3::length() const +{ + return std::sqrt(length_squared()); +} + +double vec3::length_squared() const +{ + return e[0]*e[0] + e[1]*e[1] + e[2]*e[2]; +} + +vec3& vec3::operator+=(const vec3 &v) +{ + e[0] += v.e[0]; + e[1] += v.e[1]; + e[2] += v.e[2]; + return *this; +} + +vec3& vec3::operator*=(const double t) +{ + e[0] *= t; + e[1] *= t; + e[2] *= t; + return *this; +} + +vec3& vec3::operator/=(const double t) +{ + return *this *= 1 / t; +} + +std::ostream& operator<<(std::ostream &out, const vec3 &v) +{ + return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2]; +} + +vec3 operator+(const vec3 &u, const vec3 &v) +{ + return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]); +} + +vec3 operator-(const vec3 &u, const vec3 &v) +{ + return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]); +} + +vec3 operator*(const vec3 &u, const vec3 &v) +{ + return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]); +} + +vec3 operator*(const vec3 &v, double t) +{ + return t * v; +} + +vec3 operator*(double t, const vec3 &v) +{ + return vec3(t * v.e[0], t * v.e[1], t * v.e[2]); +} + +vec3 operator/(vec3 v, double t) +{ + return (1 / t) * v; +} + +vec3 lerp(const vec3 &a, const vec3 &b, double t) +{ + return (1.0 - t) * a + t * b; +} + +double dot(const vec3 &u, const vec3 &v) +{ + return u[0] * v[0] + + u[1] * v[1] + + u[2] * v[2]; +} + +vec3 cross(const vec3 &u, const vec3 &v) +{ + return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1], + u.e[2] * v.e[0] - u.e[0] * v.e[2], + u.e[0] * v.e[1] - u.e[1] * v.e[0]); +} + +vec3 reflect(const vec3& v, const vec3& n) +{ + return v - 2*dot(v,n)*n; +} + +vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat) +{ + auto cos_theta = dot(-uv, n); + vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n); + vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n; + + return r_out_parallel + r_out_perp; +} +