1
0

feat: add generic hittable class

This commit is contained in:
Rokas Puzonas 2022-03-12 15:23:35 +02:00
parent ddad81b6f8
commit 88527f91ea
6 changed files with 34105 additions and 33975 deletions

23
hittable.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef HITTABLE_H
#define HITTABLE_H
#include "ray.h"
struct hit_record {
point3 p;
vec3 normal;
double t;
bool front_face;
inline void set_face_normal(const ray& r, const vec3& outward_normal) {
front_face = dot(r.direction(), outward_normal) < 0;
normal = front_face ? outward_normal : -outward_normal;
}
};
class hittable {
public:
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& hit) const = 0;
};
#endif

43
hittable_list.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef HITTABLE_LIST_H
#define HITTABLE_LIST_H
#include "hittable.h"
#include <memory>
#include <vector>
using std::shared_ptr;
using std::make_shared;
class hittable_list : public hittable {
public:
hittable_list() {}
hittable_list(shared_ptr<hittable> object) { add(object); }
void clear() { objects.clear(); }
void add(shared_ptr<hittable> object) { objects.push_back(object); }
virtual bool hit(
const ray& r, double t_min, double t_max, hit_record& rec) const override;
public:
std::vector<shared_ptr<hittable>> objects;
};
bool hittable_list::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
hit_record temp_rec;
bool hit_anything = false;
auto closest_so_far = t_max;
for (const auto& object : objects) {
if (object->hit(r, t_min, closest_so_far, temp_rec)) {
hit_anything = true;
closest_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
#endif

67904
image.ppm

File diff suppressed because it is too large Load Diff

38
main.cc
View File

@ -1,32 +1,19 @@
#include "rtweekend.h"
#include "color.h"
#include "ray.h"
#include "vec3.h"
#include "hittable_list.h"
#include "sphere.h"
#include <iostream>
double hit_sphere(const point3& center, double radius, const ray& r) {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
auto c = oc.length_squared() - radius*radius;
auto discriminant = half_b*half_b - a*c;
if (discriminant < 0) {
return -1.0;
} else {
return (-half_b - sqrt(discriminant)) / a;
}
}
color ray_color(const ray& r) {
auto t = hit_sphere(point3(0, 0, -1), 0.5, r);
if (t > 0.0) {
vec3 N = unit_vector(r.at(t) - vec3(0, 0, -1));
return 0.5*color(N.x()+1, N.y()+1, N.z()+1);
color ray_color(const ray& r, const hittable& world) {
hit_record rec;
if (world.hit(r, 0, infinity, rec)) {
return 0.5 * (rec.normal + color(1, 1, 1));
}
vec3 unit_direction = unit_vector(r.direction());
t = 0.5*(unit_direction.y() + 1.0);
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0 - t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
@ -36,6 +23,11 @@ int main() {
const int image_width = 400;
const int image_height = static_cast<int>(image_width / aspect_ratio);
// World
hittable_list world;
world.add(make_shared<sphere>(point3(0, 0, -1), 0.5));
world.add(make_shared<sphere>(point3(0, -100.5, -1), 100));
// Camera
auto viewport_height = 2.0;
auto viewport_width = aspect_ratio * viewport_height;
@ -54,7 +46,7 @@ int main() {
auto u = double(i) / (image_width-1);
auto v = double(j) / (image_height-1);
ray r(origin, lower_left_corner + u*horizontal + v*vertical - origin);
color pixel_color = ray_color(r);
color pixel_color = ray_color(r, world);
write_color(std::cout, pixel_color);
}
}

26
rtweekend.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef RTWEEKEND_H
#define RTWEEKEND_H
#include <cmath>
#include <limits>
#include <memory>
// Usings
using std::shared_ptr;
using std::make_shared;
using std::sqrt;
// Constants
const double infinity = std::numeric_limits<double>::infinity();
const double pi = 3.1415926535897932385;
// Utility functions
inline double degrees_to_radians(double degrees) {
return degrees * pi / 180.0;
}
// Common headers
#include "ray.h"
#include "vec3.h"
#endif

46
sphere.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef SPHERE_H
#define SPHERE_H
#include "hittable.h"
#include "vec3.h"
class sphere : public hittable {
public:
sphere() {}
sphere(point3 cen, double r) : center(cen), radius(r) {};
virtual bool hit(
const ray& r, double t_min, double t_max, hit_record& rec) const override;
public:
point3 center;
double radius;
};
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
vec3 oc = r.origin() - center;
auto a = r.direction().length_squared();
auto half_b = dot(oc, r.direction());
auto c = oc.length_squared() - radius*radius;
auto discriminant = half_b*half_b - a*c;
if (discriminant < 0) return false;
auto sqrtd = sqrt(discriminant);
// Find the nearest root that lies in the acceptable range.
auto root = (-half_b - sqrtd) / a;
if (root < t_min || t_max < root) {
root = (-half_b + sqrtd) / a;
if (root < t_min || t_max < root)
return false;
}
rec.t = root;
rec.p = r.at(rec.t);
vec3 outward_normal = (rec.p - center) / radius;
rec.set_face_normal(r, outward_normal);
return true;
}
#endif