Hittables abstraction
This commit is contained in:
parent
0c8191be28
commit
b9862477cd
6 changed files with 165 additions and 26 deletions
|
@ -3,4 +3,9 @@ project(rtiww)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
add_executable(rtiww src/main.cpp src/vec3.h src/color.h src/ray.h)
|
add_executable(rtiww src/main.cpp
|
||||||
|
src/vec3.h src/ray.h
|
||||||
|
src/color.h
|
||||||
|
src/hittable.h src/hittable_list.h
|
||||||
|
src/sphere.h
|
||||||
|
src/rtweekend.h)
|
||||||
|
|
25
rtiww/src/hittable.h
Normal file
25
rtiww/src/hittable.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef HITTABLE_H_
|
||||||
|
#define HITTABLE_H_
|
||||||
|
|
||||||
|
#include "ray.h"
|
||||||
|
#include "vec3.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 &rec) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HITTABLE_H_
|
44
rtiww/src/hittable_list.h
Normal file
44
rtiww/src/hittable_list.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef HITTABLE_LIST_H_
|
||||||
|
#define HITTABLE_LIST_H_
|
||||||
|
|
||||||
|
#include "hittable.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
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 // HITTABLE_LIST_H_
|
|
@ -1,33 +1,19 @@
|
||||||
|
#include "hittable.h"
|
||||||
|
#include "rtweekend.h"
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "vec3.h"
|
#include "hittable_list.h"
|
||||||
#include "ray.h"
|
#include "sphere.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
double hit_sphere(const point3 ¢er, double radius, const ray &r) {
|
color ray_color(const ray &r, const hittable& world) {
|
||||||
vec3 oc = r.origin() - center;
|
hit_record rec;
|
||||||
|
if(world.hit(r, 0, infinity, rec)) {
|
||||||
auto a = r.direction().length_squared();
|
return 0.5 * (rec.normal + color(1,1,1));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 unit_direction = unit_vector(r.direction());
|
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);
|
return (1.0 - t) * color(1.0, 1.0, 1.0) + t * color(0.5, 0.7, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +24,11 @@ int main() {
|
||||||
const int image_width = 400;
|
const int image_width = 400;
|
||||||
const int image_height = static_cast<int>(image_width / aspect_ratio);
|
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
|
// Camera
|
||||||
auto viewport_height = 2.0;
|
auto viewport_height = 2.0;
|
||||||
auto viewport_width = aspect_ratio * viewport_height;
|
auto viewport_width = aspect_ratio * viewport_height;
|
||||||
|
@ -58,7 +49,7 @@ int main() {
|
||||||
auto v = double(j) / (image_height - 1);
|
auto v = double(j) / (image_height - 1);
|
||||||
|
|
||||||
ray r(origin, lower_left_corner + u * horizontal + v * vertical - origin);
|
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);
|
write_color(std::cout, pixel_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
rtiww/src/rtweekend.h
Normal file
32
rtiww/src/rtweekend.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef RTWEEKEND_H_
|
||||||
|
#define RTWEEKEND_H_
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
using std::make_shared;
|
||||||
|
using std::sqrt;
|
||||||
|
|
||||||
|
const double infinity = std::numeric_limits<double>::infinity();
|
||||||
|
const double pi = 3.1415926535897932385;
|
||||||
|
|
||||||
|
inline double degrees_to_radians(double degrees) {
|
||||||
|
return degrees * pi / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double random_double() {
|
||||||
|
// Returns a random real in [0,1).
|
||||||
|
return rand() / (RAND_MAX + 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double random_double(double min, double max) {
|
||||||
|
// Returns a random real in [min, max).
|
||||||
|
return min + (max-min)*random_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ray.h"
|
||||||
|
#include "vec3.h"
|
||||||
|
|
||||||
|
#endif // RTWEEKEND_H_
|
42
rtiww/src/sphere.h
Normal file
42
rtiww/src/sphere.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef SPHERE_H_
|
||||||
|
#define SPHERE_H_
|
||||||
|
|
||||||
|
#include "hittable.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 // SPHERE_H_
|
Loading…
Reference in a new issue