diff --git a/Makefile b/Makefile index ffad87f..fc7d1f7 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX = g++ CXXFLAGS = -std=c++20 -Wall -Wextra -Wno-unused-parameter -march=native -O3 -flto -fopenmp DEPS = util.h vec3.h color.h ray.h camera.h hittable.h hittable_list.h sphere.h material.h lodepng.h moving_sphere.h bvh.h aabb.h texture.h aarect.h box.h -OBJ = main.o material.o vec3.o lodepng.o sphere.o moving_sphere.o bvh.o aarect.o box.o hittable_list.o +OBJ = main.o material.o vec3.o lodepng.o sphere.o moving_sphere.o bvh.o aarect.o box.o hittable_list.o hittable.o TARGET = toytracer diff --git a/hittable.cpp b/hittable.cpp new file mode 100644 index 0000000..1bac0b2 --- /dev/null +++ b/hittable.cpp @@ -0,0 +1,93 @@ +#include "hittable.h" + +#include + +bool Flip_face::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const { + if (!ptr->hit(r, tmin, tmax, rec)) + return false; + + rec.front_face = !rec.front_face; + return true; +} + +bool Translate::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const { + Ray moved_r(r.origin() - offset, r.direction(), r.time()); + if (!ptr->hit(moved_r, tmin, tmax, rec)) + return false; + + rec.p += offset; + rec.set_face_normal(moved_r, rec.normal); + + return true; +} + +bool Translate::bounding_box(double t0, double t1, Aabb& output_box) const { + if (!ptr->bounding_box(t0, t1, output_box)) + return false; + + output_box = Aabb(output_box.min() + offset, output_box.max() + offset); + return true; +} + +Rotate_y::Rotate_y(std::shared_ptr p, double angle) : ptr(p) { + auto radians = degrees_to_radians(angle); + sin_theta = std::sin(radians); + cos_theta = std::cos(radians); + + hasbox = ptr->bounding_box(0, 1, bbox); + + Point3 min( infinity, infinity, infinity); + Point3 max(-infinity, -infinity, -infinity); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + auto x = i*bbox.max().x() + (1-i)*bbox.min().x(); + auto y = j*bbox.max().y() + (1-j)*bbox.min().y(); + auto z = k*bbox.max().z() + (1-k)*bbox.min().z(); + + auto newx = cos_theta*x + sin_theta*z; + auto newz = -sin_theta*x + cos_theta*z; + + Vec3 tester(newx, y, newz); + + for (int c = 0; c < 3; c++) { + min[c] = std::fmin(min[c], tester[c]); + max[c] = std::fmin(max[c], tester[c]); + } + } + } + } + + bbox = Aabb(min, max); +} + +bool Rotate_y::hit(const Ray& r, double tmin, double tmax, hit_record& rec) const { + auto origin = r.origin(); + auto direction = r.direction(); + + origin[0] = cos_theta*r.origin()[0] - sin_theta*r.origin()[2]; + origin[2] = sin_theta*r.origin()[0] + cos_theta*r.origin()[2]; + + direction[0] = cos_theta*r.direction()[0] - sin_theta*r.direction()[2]; + direction[2] = sin_theta*r.direction()[0] + cos_theta*r.direction()[2]; + + Ray rotated_r(origin, direction, r.time()); + + if (!ptr->hit(rotated_r, tmin, tmax, rec)) + return false; + + auto p = rec.p; + auto normal = rec.normal; + + p[0] = cos_theta*rec.p[0] + sin_theta*rec.p[2]; + p[2] = -sin_theta*rec.p[0] + cos_theta*rec.p[2]; + + normal[0] = cos_theta*rec.normal[0] + sin_theta*rec.normal[2]; + normal[2] = -sin_theta*rec.normal[0] + cos_theta*rec.normal[2]; + + rec.p = p; + rec.set_face_normal(rotated_r, normal); + + return true; +} diff --git a/hittable.h b/hittable.h index 79c6e1f..2579120 100644 --- a/hittable.h +++ b/hittable.h @@ -34,13 +34,7 @@ class Flip_face : public Hittable { public: Flip_face(std::shared_ptr p) : ptr(p) {} - virtual bool hit(const Ray &r, double tmin, double tmax, hit_record &rec) const { - if (!ptr->hit(r, tmin, tmax, rec)) - return false; - - rec.front_face = !rec.front_face; - return true; - } + virtual bool hit(const Ray &r, double tmin, double tmax, hit_record &rec) const; virtual bool bounding_box(double t0, double t1, Aabb& output_box) const { return ptr->bounding_box(t0, t1, output_box); @@ -50,4 +44,34 @@ class Flip_face : public Hittable { std::shared_ptr ptr; }; +class Translate : public Hittable { + public: + Translate(std::shared_ptr p, const Vec3& displacement) : ptr(p), offset(displacement) {} + + virtual bool hit(const Ray &r, double tmin, double tmax, hit_record &rec) const; + virtual bool bounding_box(double t0, double t1, Aabb& output_box) const; + + private: + std::shared_ptr ptr; + Vec3 offset; +}; + +class Rotate_y : public Hittable { + public: + Rotate_y(std::shared_ptr p, double angle); + + virtual bool hit(const Ray& r, double tmin, double tmax, hit_record& rec) const; + virtual bool bounding_box(double t0, double t1, Aabb& output_box) const { + output_box = bbox; + return hasbox; + } + + private: + std::shared_ptr ptr; + double sin_theta; + double cos_theta; + bool hasbox; + Aabb bbox; +}; + #endif // HITTABLE_H diff --git a/main.cpp b/main.cpp index a5bc288..d7e9635 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,7 @@ #include "moving_sphere.h" #include "camera.h" #include "aarect.h" +#include "box.h" Color ray_color(const Ray& r, const Color& background, const Hittable& world, int depth) { hit_record rec; @@ -153,7 +154,9 @@ std::pair cornell_box(const double aspect_ratio) { auto white = std::make_shared(std::make_shared(0.73, 0.73, 0.73)); auto green = std::make_shared(std::make_shared(0.12, 0.45, 0.15)); - auto light = std::make_shared(std::make_shared(15, 15, 15)); + //auto light = std::make_shared(std::make_shared(15, 15, 15)); + auto light = std::make_shared(std::make_shared(30, 30, 30)); + //auto light = std::make_shared(std::make_shared(100, 100, 100)); objects.add(std::make_shared(std::make_shared( 0, 555, 0, 555, 555, green))); objects.add(std::make_shared( 0, 555, 0, 555, 0, red )); @@ -162,6 +165,16 @@ std::pair cornell_box(const double aspect_ratio) { objects.add(std::make_shared( 0, 555, 0, 555, 555, white)); objects.add(std::make_shared(std::make_shared( 0, 555, 0, 555, 555, white))); + std::shared_ptr box1 = std::make_shared(Point3(0, 0, 0), Point3(165, 300, 165), white); + box1 = std::make_shared(box1, 15); + box1 = std::make_shared(box1, Vec3(265, 0, 295)); + objects.add(box1); + + std::shared_ptr box2 = std::make_shared(Point3(0, 0, 0), Point3(165, 165, 165), white); + box2 = std::make_shared(box2, -18); + box2 = std::make_shared(box2, Vec3(130, 0, 65)); + objects.add(box2); + Point3 lookfrom(278, 278, -800); Point3 lookat(278, 278, 0); Vec3 vup(0, 1, 0); @@ -190,15 +203,15 @@ int main() { //const int image_width = 384; const int image_height = static_cast(image_width / aspect_ratio); //const int samples_per_pixel = 10000; - //const int samples_per_pixel = 5000; + const int samples_per_pixel = 5000; //const int samples_per_pixel = 2000; - const int samples_per_pixel = 1000; + //const int samples_per_pixel = 1000; //const int samples_per_pixel = 400; //const int samples_per_pixel = 50; const int max_depth = 50; - const int tile_size = 128; - //const int tile_size = 64; + //const int tile_size = 128; + const int tile_size = 64; //const int sph_i = 3; //const int sph_i = 5; diff --git a/util.h b/util.h index ae9d1a0..08e8a78 100644 --- a/util.h +++ b/util.h @@ -14,11 +14,9 @@ inline double degrees_to_radians(double degrees) { } inline double random_double() { - static std::uniform_real_distribution distribution(0.0, 1.0); - //static std::mt19937 generator(std::time(nullptr)); + static thread_local std::uniform_real_distribution distribution(0.0, 1.0); static thread_local std::mt19937 generator(std::random_device{}()); - static std::function rand_gen = std::bind(distribution, generator); - return rand_gen(); + return distribution(generator); } inline double random_double(double min, double max) {