diff --git a/assets/should.png b/assets/should.png index 86f02fd..32c54ff 100644 Binary files a/assets/should.png and b/assets/should.png differ diff --git a/config/should.cfg b/config/should.cfg index b3180ba..3bbbb5e 100644 --- a/config/should.cfg +++ b/config/should.cfg @@ -63,7 +63,7 @@ scene = { id = "light_sphere"; type = "sphere"; args = { - center = (0.0, 3.0, 0.0); + center = (0.0, 7.0, 0.0); radius = 1.0; material = "material_light" }; @@ -94,9 +94,9 @@ scene = { image_width = 1200; samples_per_pixel = 500; max_depth = 100; - v_fov = 20; - look_from = (26.0, 6.0, 3.0); - look_at = (0.0, 3.0, 0.0); + v_fov = 18; + look_from = (26.0, 8.0, 0.0); + look_at = (0.0, 2.5, 0.0); v_up = (0.0, 1.0, 0.0); defocus_angle = 0.0 background_color = (0.0, 0.0, 0.0); diff --git a/sources/shapes/Cone.cpp b/sources/shapes/Cone.cpp index b3fdcf2..de48299 100644 --- a/sources/shapes/Cone.cpp +++ b/sources/shapes/Cone.cpp @@ -52,6 +52,22 @@ bool Raytracer::Shapes::Cone::hit(const Core::Ray &ray, - oc.y() * oc.y() * _radius * _radius / (_height * _height); double discriminant = b * b - 4 * a * c; + double top_cap = _center.y() + _height; + double t = ((top_cap - ray.origin().y()) / ray.direction().y()); + if (interval.contains(t)) { + double x = ray.origin().x() + t * ray.direction().x(); + double z = ray.origin().z() + t * ray.direction().z(); + double distance_squared = (x - _center.x()) * (x - _center.x()) + + (z - _center.z()) * (z - _center.z()); + if (distance_squared <= _radius * _radius) { + payload.t(t); + payload.point(ray.at(payload.t())); + payload.setFaceNormal(ray, Utils::Vec3(0, 1, 0)); + payload.material(_material); + return true; + } + } + if (discriminant < 0) { return false; } diff --git a/sources/shapes/Cylinder.cpp b/sources/shapes/Cylinder.cpp index 1608cfc..2232db7 100644 --- a/sources/shapes/Cylinder.cpp +++ b/sources/shapes/Cylinder.cpp @@ -40,10 +40,39 @@ Raytracer::Shapes::Cylinder::Cylinder(const Utils::Point3 ¢er, bool Raytracer::Shapes::Cylinder::hit(const Core::Ray &ray, Utils::Interval interval, Core::Payload &payload) const { - // TODO: Implement cylinder caps intersection Utils::Vec3 direction = ray.direction(); Utils::Point3 origin = ray.origin(); + double t_cap = (_center.y() - origin.y()) / direction.y(); + if (interval.surrounds(t_cap)) { + Utils::Point3 hit_point = ray.at(t_cap); + double dist_squared = + (hit_point.x() - _center.x()) * (hit_point.x() - _center.x()) + + (hit_point.z() - _center.z()) * (hit_point.z() - _center.z()); + if (dist_squared <= _radius * _radius) { + payload.t(t_cap); + payload.point(hit_point); + payload.setFaceNormal(ray, Utils::Vec3(0, 1, 0)); + payload.material(_material); + return true; + } + } + + t_cap = (_center.y() + _height - origin.y()) / direction.y(); + if (interval.surrounds(t_cap)) { + Utils::Point3 hit_point = ray.at(t_cap); + double dist_squared = + (hit_point.x() - _center.x()) * (hit_point.x() - _center.x()) + + (hit_point.z() - _center.z()) * (hit_point.z() - _center.z()); + if (dist_squared <= _radius * _radius) { + payload.t(t_cap); + payload.point(hit_point); + payload.setFaceNormal(ray, Utils::Vec3(0, -1, 0)); + payload.material(_material); + return true; + } + } + double a = std::pow(direction.x(), 2) + std::pow(direction.z(), 2); double h = 2 * (direction.x() * (origin.x() - _center.x())