mirror of
https://github.com/MorizzG/ray-tracer.git
synced 2025-12-06 04:22:42 +00:00
moved rendering code into own class
implemented antialiasing using random subsampling
This commit is contained in:
parent
882918f09b
commit
29832e8f1b
13 changed files with 238 additions and 124 deletions
42
src/camera.h
42
src/camera.h
|
|
@ -1,19 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "image.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderobject.h"
|
||||
#include "vec3.h"
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
constexpr Camera(Vec3 centre, u32 image_width, u32 image_height, double focal_length)
|
||||
: centre_{centre} {
|
||||
constexpr double viewport_height = 2.0;
|
||||
double viewport_width = viewport_height * static_cast<double>(image_width) / image_height;
|
||||
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;
|
||||
|
|
@ -31,31 +26,17 @@ class Camera {
|
|||
|
||||
constexpr Vec3 centre() const { return centre_; }
|
||||
|
||||
constexpr void Render(Image& img, const RenderObject& world) const {
|
||||
for (u32 j = 0; j < img.height(); j++) {
|
||||
std::clog << "\rWriting line " << j << " of " << img.height() << std::flush;
|
||||
constexpr Vec3 d_u_pixel() const { return d_u_pixel_; }
|
||||
constexpr Vec3 d_v_pixel() const { return d_v_pixel_; }
|
||||
|
||||
for (u32 i = 0; i < img.width(); i++) {
|
||||
auto ray = CastRay(i, j);
|
||||
constexpr u32 image_width() const { return image_width_; }
|
||||
constexpr u32 image_height() const { return image_height_; }
|
||||
|
||||
img[i, j] = Cast(ray, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr Vec3 Image2World(u32 i, u32 j) const {
|
||||
constexpr Vec3 PixelToWorld(u32 i, u32 j) const {
|
||||
return pixel_00_ + i * d_u_pixel_ + j * d_v_pixel_;
|
||||
}
|
||||
|
||||
constexpr Ray CastRay(u32 i, u32 j) const {
|
||||
auto pixel_centre = Image2World(i, j);
|
||||
|
||||
auto ray_direction = pixel_centre - centre();
|
||||
|
||||
return Ray{centre(), ray_direction};
|
||||
}
|
||||
|
||||
private:
|
||||
Vec3 centre_;
|
||||
|
||||
// position of pixel 0, 0
|
||||
|
|
@ -64,4 +45,7 @@ class Camera {
|
|||
// Vec3 pointing from pixel to right/lower neighbour resp.
|
||||
Vec3 d_u_pixel_;
|
||||
Vec3 d_v_pixel_;
|
||||
|
||||
u32 image_width_;
|
||||
u32 image_height_;
|
||||
};
|
||||
|
|
|
|||
45
src/colour.h
45
src/colour.h
|
|
@ -17,21 +17,31 @@ class Colour {
|
|||
static const Colour kWhite;
|
||||
|
||||
constexpr Colour() = default;
|
||||
constexpr Colour(double r, double g, double b) : r_{r}, g_{g}, b_{b} {
|
||||
assert(0.0 <= r && r <= 1.0);
|
||||
assert(0.0 <= g && g <= 1.0);
|
||||
assert(0.0 <= b && b <= 1.0);
|
||||
constexpr Colour(f64 r, f64 g, f64 b) : r_{r}, g_{g}, b_{b} {}
|
||||
|
||||
constexpr void CheckValid() const {
|
||||
assert(0.0 <= r() && r() <= 1.0);
|
||||
assert(0.0 <= g() && g() <= 1.0);
|
||||
assert(0.0 <= b() && b() <= 1.0);
|
||||
}
|
||||
|
||||
constexpr explicit Colour(Vec3 v) : Colour{v.x(), v.y(), v.z()} {}
|
||||
|
||||
constexpr double& r() { return r_; }
|
||||
constexpr double& g() { return g_; }
|
||||
constexpr double& b() { return b_; }
|
||||
constexpr f64& r() { return r_; }
|
||||
constexpr f64& g() { return g_; }
|
||||
constexpr f64& b() { return b_; }
|
||||
|
||||
constexpr double r() const { return r_; }
|
||||
constexpr double g() const { return g_; }
|
||||
constexpr double b() const { return b_; }
|
||||
constexpr f64 r() const { return r_; }
|
||||
constexpr f64 g() const { return g_; }
|
||||
constexpr f64 b() const { return b_; }
|
||||
|
||||
constexpr Colour& operator+=(const Colour& c) {
|
||||
r_ += c.r();
|
||||
g_ += c.g();
|
||||
b_ += c.b();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
std::stringstream ss;
|
||||
|
|
@ -46,17 +56,22 @@ class Colour {
|
|||
}
|
||||
|
||||
private:
|
||||
double r_;
|
||||
double g_;
|
||||
double b_;
|
||||
f64 r_ = 0.0;
|
||||
f64 g_ = 0.0;
|
||||
f64 b_ = 0.0;
|
||||
};
|
||||
|
||||
constexpr Colour Colour::kBlack{0.0, 0.0, 0.0};
|
||||
|
||||
constexpr Colour operator*(double t, Colour col) { return {t * col.r(), t * col.g(), t * col.b()}; }
|
||||
constexpr Colour operator*(f64 t, Colour col) { return {t * col.r(), t * col.g(), t * col.b()}; }
|
||||
constexpr Colour operator/(Colour col, f64 t) { return (1.0 / t) * col; }
|
||||
|
||||
constexpr Colour operator+(Colour c1, Colour c2) {
|
||||
return {c1.r() + c2.r(), c1.g() + c2.g(), c1.b() + c2.b()};
|
||||
Colour out{c1};
|
||||
|
||||
out += c2;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, Colour colour) {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ constexpr std::ostream& operator<<(std::ostream& os, const Image& img) {
|
|||
for (u32 i = 0; i < img.width(); i++) {
|
||||
const Colour col = img[i, j];
|
||||
|
||||
col.CheckValid();
|
||||
|
||||
os << col << newline;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "raytracer.h"
|
||||
class Interval {
|
||||
public:
|
||||
static const Interval kEmpty, kFull, kPositive;
|
||||
|
||||
constexpr Interval() = default;
|
||||
constexpr Interval(double min, double max) : min_{min}, max_{max} {}
|
||||
constexpr Interval(f64 min, f64 max) : min_{min}, max_{max} {}
|
||||
|
||||
constexpr double min() const { return min_; }
|
||||
constexpr double max() const { return max_; }
|
||||
constexpr f64 min() const { return min_; }
|
||||
constexpr f64 max() const { return max_; }
|
||||
|
||||
constexpr bool contains(double x) const { return min_ <= x && x <= max_; }
|
||||
constexpr bool surronds(double x) const { return min_ < x && x < max_; }
|
||||
constexpr bool contains(f64 x) const { return min_ <= x && x <= max_; }
|
||||
constexpr bool surronds(f64 x) const { return min_ < x && x < max_; }
|
||||
|
||||
constexpr double clamp(f64 x) const { return std::clamp(x, min_, max_); }
|
||||
|
||||
private:
|
||||
double min_ = kInf;
|
||||
double max_ = -kInf;
|
||||
f64 min_ = kInf;
|
||||
f64 max_ = -kInf;
|
||||
};
|
||||
|
||||
constexpr Interval Interval::kEmpty{kInf, -kInf};
|
||||
|
|
|
|||
33
src/main.cc
33
src/main.cc
|
|
@ -4,42 +4,43 @@
|
|||
#include "camera.h"
|
||||
#include "image.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderer.h"
|
||||
#include "renderobject.h"
|
||||
#include "renderobjectlist.h"
|
||||
#include "sphere.h"
|
||||
#include "vec3.h"
|
||||
|
||||
int main(int /* argc */, char* /* argv */[]) {
|
||||
// image
|
||||
|
||||
constexpr double aspect_ratio = 16.0 / 9.0;
|
||||
|
||||
constexpr u32 image_width = 800;
|
||||
|
||||
constexpr auto image_height = static_cast<u32>(image_width / aspect_ratio);
|
||||
|
||||
static_assert(image_height >= 1);
|
||||
|
||||
Image img{image_width, image_height};
|
||||
|
||||
// world
|
||||
|
||||
RenderObjectList world;
|
||||
|
||||
world.Add(std::make_shared<Sphere>(Vec3{0, -100.5, -1}, 100));
|
||||
// world.Add(std::make_shared<Sphere>(Vec3{0, -100.5, -1}, 100));
|
||||
world.Add(std::make_shared<Sphere>(-Vec3::e_z, 0.5));
|
||||
|
||||
// camera
|
||||
|
||||
constexpr double focal_length = 1.0;
|
||||
// constexpr f64 aspect_ratio = 16.0 / 9.0;
|
||||
|
||||
// constexpr u32 image_width = 800;
|
||||
// constexpr auto image_height = static_cast<u32>(image_width / aspect_ratio);
|
||||
|
||||
constexpr u32 image_width = 1920;
|
||||
constexpr u32 image_height = 1080;
|
||||
|
||||
static_assert(image_height >= 1);
|
||||
|
||||
constexpr f64 focal_length = 1.0;
|
||||
|
||||
constexpr Point3 camera_centre{0.0, 0.0, 0.0};
|
||||
|
||||
Camera camera{camera_centre, img.width(), img.height(), focal_length};
|
||||
Camera camera{camera_centre, image_width, image_height, focal_length};
|
||||
|
||||
// render
|
||||
|
||||
camera.Render(img, world);
|
||||
Renderer renderer{camera};
|
||||
|
||||
auto img = renderer.Render(world);
|
||||
|
||||
std::cout << img;
|
||||
|
||||
|
|
|
|||
47
src/rand.h
Normal file
47
src/rand.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "raytracer.h"
|
||||
class Random {
|
||||
public:
|
||||
constexpr explicit Random(u64 j) {
|
||||
assert(j != v_);
|
||||
|
||||
u_ = j ^ v_;
|
||||
GenU64();
|
||||
|
||||
v_ = u_;
|
||||
GenU64();
|
||||
|
||||
w_ = v_;
|
||||
GenU64();
|
||||
}
|
||||
|
||||
constexpr u64 GenU64() {
|
||||
u_ = u_ * 2862933555777941757ULL + 7046029254386353087ULL;
|
||||
|
||||
v_ ^= v_ >> 17;
|
||||
v_ ^= v_ << 31;
|
||||
v_ ^= v_ >> 8;
|
||||
|
||||
w_ = 4294957665ULL * (w_ & 0xffffffffULL) + (w_ >> 32);
|
||||
|
||||
u64 x = u_ ^ (u_ << 21);
|
||||
x ^= x >> 35;
|
||||
x ^= x << 4;
|
||||
|
||||
return (x + v_) ^ w_;
|
||||
}
|
||||
|
||||
constexpr u32 GenU32() { return static_cast<u32>(GenU64()); }
|
||||
|
||||
constexpr f64 GenF64() { return 5.42101086242752217E-20 * static_cast<f64>(GenU64()); }
|
||||
|
||||
constexpr f64 GenF64(f64 min, f64 max) { return min + (max - min) * GenF64(); }
|
||||
|
||||
private:
|
||||
u64 u_ = 0ULL;
|
||||
u64 v_ = 4101842887655102017ULL;
|
||||
u64 w_ = 1ULL;
|
||||
};
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "raytracer.h"
|
||||
#include "vec3.h"
|
||||
|
||||
class Ray {
|
||||
|
|
@ -11,7 +12,7 @@ class Ray {
|
|||
Point3 origin() const { return orig_; }
|
||||
Vec3 direction() const { return dir_; }
|
||||
|
||||
constexpr Point3 At(double t) const { return orig_ + t * dir_; }
|
||||
constexpr Point3 At(f64 t) const { return orig_ + t * dir_; }
|
||||
|
||||
private:
|
||||
Point3 orig_;
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@
|
|||
#include <numbers>
|
||||
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
constexpr double kInf = std::numeric_limits<double>::infinity();
|
||||
constexpr double kPi = std::numbers::pi_v<double>;
|
||||
using f64 = double;
|
||||
|
||||
constexpr f64 kInf = std::numeric_limits<f64>::infinity();
|
||||
constexpr f64 kPi = std::numbers::pi_v<f64>;
|
||||
|
||||
constexpr char newline = '\n';
|
||||
|
||||
constexpr u32 FToU8(double x) { return static_cast<uint16_t>(255.999 * x); }
|
||||
constexpr u32 FToU8(f64 x) { return static_cast<uint16_t>(255.999 * x); }
|
||||
|
||||
constexpr double deg2rad(double deg) { return deg * kPi / 180.0; }
|
||||
constexpr f64 deg2rad(f64 deg) { return deg * kPi / 180.0; }
|
||||
|
|
|
|||
79
src/renderer.h
Normal file
79
src/renderer.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "camera.h"
|
||||
#include "colour.h"
|
||||
#include "image.h"
|
||||
#include "interval.h"
|
||||
#include "rand.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderobject.h"
|
||||
#include "vec3.h"
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
constexpr explicit Renderer(Camera camera, u32 samples_per_pixel = 10)
|
||||
: camera_{camera}, rand_{0}, samples_per_pixel_{samples_per_pixel} {}
|
||||
|
||||
constexpr Image Render(const RenderObject& world) {
|
||||
Image img{camera_.image_width(), camera_.image_height()};
|
||||
|
||||
for (u32 j = 0; j < img.height(); j++) {
|
||||
std::clog << "\rWriting line " << j << " of " << img.height() << std::flush;
|
||||
|
||||
for (u32 i = 0; i < img.width(); i++) {
|
||||
Colour colour_sum{0.0, 0.0, 0.0};
|
||||
|
||||
for (u32 num_sample = 0; num_sample < samples_per_pixel_; num_sample++) {
|
||||
auto ray = SampleRay(i, j);
|
||||
|
||||
colour_sum += Cast(ray, world);
|
||||
}
|
||||
|
||||
img[i, j] = colour_sum / samples_per_pixel_;
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr Ray SampleRay(u32 i, u32 j) {
|
||||
auto pixel_centre = camera_.PixelToWorld(i, j);
|
||||
|
||||
pixel_centre += rand_.GenF64(-0.5, 0.5) * camera_.d_u_pixel();
|
||||
pixel_centre += rand_.GenF64(-0.5, 0.5) * camera_.d_v_pixel();
|
||||
|
||||
auto ray_direction = pixel_centre - camera_.centre();
|
||||
|
||||
return Ray{camera_.centre(), ray_direction};
|
||||
}
|
||||
|
||||
static constexpr Colour Cast(const Ray& ray, const RenderObject& world) {
|
||||
auto hit_record = world.hit(ray, Interval::kPositive);
|
||||
|
||||
if (hit_record.has_value()) {
|
||||
Vec3 n = hit_record->normal;
|
||||
|
||||
if (!hit_record->front_face) {
|
||||
return Colour::kBlack;
|
||||
}
|
||||
|
||||
return Colour{0.5 * (n + Vec3{1, 1, 1})};
|
||||
}
|
||||
|
||||
auto unit_dir = ray.direction().normed();
|
||||
|
||||
f64 a = 0.5 * (unit_dir.y() + 1.0);
|
||||
|
||||
return (1.0 - a) * Colour{1.0, 1.0, 1.0} + a * Colour{0.5, 0.7, 1.0};
|
||||
}
|
||||
|
||||
Camera camera_;
|
||||
|
||||
Random rand_;
|
||||
|
||||
u32 samples_per_pixel_;
|
||||
};
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "colour.h"
|
||||
#include "interval.h"
|
||||
#include "ray.h"
|
||||
#include "vec3.h"
|
||||
|
|
@ -11,7 +10,7 @@
|
|||
struct HitRecord {
|
||||
Point3 p;
|
||||
Vec3 normal;
|
||||
double t = 0.0;
|
||||
f64 t = 0.0;
|
||||
bool front_face = true;
|
||||
};
|
||||
|
||||
|
|
@ -31,27 +30,3 @@ class RenderObject {
|
|||
};
|
||||
|
||||
using SharedRenderObject = std::shared_ptr<RenderObject>;
|
||||
|
||||
constexpr Colour Cast(const Ray& ray, const RenderObject& world) {
|
||||
auto hit_record = world.hit(ray, Interval::kPositive);
|
||||
// auto hit_record = world.hit(ray, Interval{0.505, kInf});
|
||||
|
||||
if (hit_record.has_value()) {
|
||||
// assert(hit_record.front_face);
|
||||
|
||||
Vec3 n = hit_record->normal;
|
||||
|
||||
if (!hit_record->front_face) {
|
||||
// return Colour{0.0, 0.0, 0.0};
|
||||
return Colour::kBlack;
|
||||
}
|
||||
|
||||
return Colour{0.5 * (n + Vec3{1, 1, 1})};
|
||||
}
|
||||
|
||||
auto unit_dir = ray.direction().normed();
|
||||
|
||||
double a = 0.5 * (unit_dir.y() + 1.0);
|
||||
|
||||
return (1.0 - a) * Colour{1.0, 1.0, 1.0} + a * Colour{0.5, 0.7, 1.0};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class RenderObjectList : public RenderObject {
|
|||
std::optional<HitRecord> hit(const Ray& ray, Interval ts) const override {
|
||||
std::optional<HitRecord> closest_hit_record = std::nullopt;
|
||||
|
||||
double closest_t = ts.max();
|
||||
f64 closest_t = ts.max();
|
||||
|
||||
for (const auto& obj : objs_) {
|
||||
Interval _ts{ts.min(), closest_t};
|
||||
|
|
|
|||
17
src/sphere.h
17
src/sphere.h
|
|
@ -6,29 +6,30 @@
|
|||
|
||||
#include "interval.h"
|
||||
#include "ray.h"
|
||||
#include "raytracer.h"
|
||||
#include "renderobject.h"
|
||||
#include "vec3.h"
|
||||
|
||||
class Sphere : public RenderObject {
|
||||
public:
|
||||
constexpr Sphere() = default;
|
||||
constexpr Sphere(Point3 centre, double radius) : centre_{centre}, radius_{radius} {
|
||||
constexpr Sphere(Point3 centre, f64 radius) : centre_{centre}, radius_{radius} {
|
||||
assert(radius >= 0);
|
||||
}
|
||||
|
||||
constexpr Point3 centre() const { return centre_; }
|
||||
constexpr double radius() const { return radius_; }
|
||||
constexpr f64 radius() const { return radius_; }
|
||||
|
||||
std::optional<HitRecord> hit(const Ray& ray, Interval ts) const override {
|
||||
HitRecord hit_record;
|
||||
|
||||
Vec3 oc = ray.origin() - centre_;
|
||||
|
||||
double a = ray.direction().squared();
|
||||
double b_half = dot(oc, ray.direction());
|
||||
double c = oc.squared() - radius_ * radius_;
|
||||
f64 a = ray.direction().squared();
|
||||
f64 b_half = dot(oc, ray.direction());
|
||||
f64 c = oc.squared() - radius_ * radius_;
|
||||
|
||||
auto discr = b_half * b_half - a * c;
|
||||
f64 discr = b_half * b_half - a * c;
|
||||
|
||||
if (discr < 0) {
|
||||
// miss
|
||||
|
|
@ -38,7 +39,7 @@ class Sphere : public RenderObject {
|
|||
// hit
|
||||
|
||||
// smaller of the ts that hit the sphere
|
||||
double t = (-b_half - std::sqrt(discr)) / a;
|
||||
f64 t = (-b_half - std::sqrt(discr)) / a;
|
||||
|
||||
if (t >= ts.max()) {
|
||||
// if the smaller t is already too large, we don't need to check the second one since it
|
||||
|
|
@ -77,5 +78,5 @@ class Sphere : public RenderObject {
|
|||
|
||||
private:
|
||||
Point3 centre_{};
|
||||
double radius_ = 0.0;
|
||||
f64 radius_ = 0.0;
|
||||
};
|
||||
|
|
|
|||
36
src/vec3.h
36
src/vec3.h
|
|
@ -6,31 +6,33 @@
|
|||
#include <cstddef>
|
||||
#include <ostream>
|
||||
|
||||
#include "raytracer.h"
|
||||
|
||||
class Vec3 {
|
||||
public:
|
||||
static const Vec3 e_x;
|
||||
static const Vec3 e_y;
|
||||
static const Vec3 e_z;
|
||||
|
||||
constexpr Vec3(double x, double y, double z) : xyz_{x, y, z} {}
|
||||
constexpr Vec3(f64 x, f64 y, f64 z) : xyz_{x, y, z} {}
|
||||
constexpr Vec3() : Vec3{0, 0, 0} {}
|
||||
|
||||
constexpr double& x() { return xyz_[0]; }
|
||||
constexpr double& y() { return xyz_[1]; }
|
||||
constexpr double& z() { return xyz_[2]; }
|
||||
constexpr f64& x() { return xyz_[0]; }
|
||||
constexpr f64& y() { return xyz_[1]; }
|
||||
constexpr f64& z() { return xyz_[2]; }
|
||||
|
||||
constexpr double x() const { return xyz_[0]; }
|
||||
constexpr double y() const { return xyz_[1]; }
|
||||
constexpr double z() const { return xyz_[2]; }
|
||||
constexpr f64 x() const { return xyz_[0]; }
|
||||
constexpr f64 y() const { return xyz_[1]; }
|
||||
constexpr f64 z() const { return xyz_[2]; }
|
||||
|
||||
constexpr Vec3 operator-() const { return Vec3{-x(), -y(), -z()}; }
|
||||
|
||||
constexpr double& operator[](std::size_t i) {
|
||||
constexpr f64& operator[](std::size_t i) {
|
||||
assert(i <= 3);
|
||||
return xyz_[i];
|
||||
}
|
||||
|
||||
constexpr double operator[](std::size_t i) const {
|
||||
constexpr f64 operator[](std::size_t i) const {
|
||||
assert(i <= 3);
|
||||
return xyz_[i];
|
||||
}
|
||||
|
|
@ -43,7 +45,7 @@ class Vec3 {
|
|||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vec3& operator*=(double t) {
|
||||
constexpr Vec3& operator*=(f64 t) {
|
||||
x() *= t;
|
||||
y() *= t;
|
||||
z() *= t;
|
||||
|
|
@ -51,15 +53,15 @@ class Vec3 {
|
|||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vec3& operator/=(double t) {
|
||||
constexpr Vec3& operator/=(f64 t) {
|
||||
*this *= 1 / t;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr double squared() const { return x() * x() + y() * y() + z() * z(); }
|
||||
constexpr f64 squared() const { return x() * x() + y() * y() + z() * z(); }
|
||||
|
||||
constexpr double norm() const { return std::sqrt(squared()); }
|
||||
constexpr f64 norm() const { return std::sqrt(squared()); }
|
||||
|
||||
constexpr Vec3 normed() const {
|
||||
auto r = *this;
|
||||
|
|
@ -68,7 +70,7 @@ class Vec3 {
|
|||
}
|
||||
|
||||
private:
|
||||
std::array<double, 3> xyz_;
|
||||
std::array<f64, 3> xyz_;
|
||||
};
|
||||
|
||||
constexpr Vec3 Vec3::e_x{1.0, 0.0, 0.0};
|
||||
|
|
@ -93,15 +95,15 @@ constexpr Vec3 operator*(const Vec3& u, const Vec3& v) {
|
|||
return {u.x() * v.x(), u.y() * v.y(), u.z() * v.z()};
|
||||
}
|
||||
|
||||
constexpr Vec3 operator*(double t, const Vec3& v) {
|
||||
constexpr Vec3 operator*(f64 t, const Vec3& v) {
|
||||
Vec3 out = v;
|
||||
out *= t;
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr Vec3 operator/(const Vec3& v, double t) { return (1 / t) * v; }
|
||||
constexpr Vec3 operator/(const Vec3& v, f64 t) { return (1 / t) * v; }
|
||||
|
||||
constexpr double dot(const Vec3& u, const Vec3& v) {
|
||||
constexpr f64 dot(const Vec3& u, const Vec3& v) {
|
||||
Vec3 tmp = u * v;
|
||||
return tmp.x() + tmp.y() + tmp.z();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue