[FEAT] Add Plane Chapter 09 is done
This commit is contained in:
@@ -23,6 +23,6 @@ The Web Site of the book: http://raytracerchallenge.com/
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
| Chapiter 07 | Chapiter 08 |
|
||||
| :------------------------: | :----------------------------: |
|
||||
|  |  |
|
||||
| Chapiter 07 | Chapiter 08 | Chapiter 09 |
|
||||
|:------------------------: | :------------------------: | :----------------------------: |
|
||||
| |  |  |
|
||||
|
||||
@@ -13,3 +13,6 @@ target_link_libraries(chapter_06 PRIVATE raytracing gcov)
|
||||
|
||||
add_executable(chapter_07 chapter_07.cpp)
|
||||
target_link_libraries(chapter_07 PRIVATE raytracing gcov)
|
||||
|
||||
add_executable(chapter_09 chapter_09.cpp)
|
||||
target_link_libraries(chapter_09 PRIVATE raytracing gcov)
|
||||
101
apps/chapter_09.cpp
Normal file
101
apps/chapter_09.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*!
|
||||
* chapter_09.cpp
|
||||
*
|
||||
* Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* @Author: NADAL Jean-Baptiste
|
||||
* @Date: 26/02/2024
|
||||
*
|
||||
*/
|
||||
|
||||
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
|
||||
#include <raytracing.h>
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
using namespace Raytracer;
|
||||
using namespace std;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
World the_world;
|
||||
Camera the_camera;
|
||||
Canvas the_canvas;
|
||||
Plane *the_floor;
|
||||
Sphere *the_middle, *the_right, *the_left;
|
||||
chrono::time_point<chrono::high_resolution_clock> the_start, the_end;
|
||||
|
||||
printf("Chapter 09 example.\n");
|
||||
|
||||
// Floor is an extremely flattened sphere with a matte texture.
|
||||
the_floor = new Plane();
|
||||
the_floor->material().set_color(Color(1, 0.9, 0.9));
|
||||
the_floor->material().set_specular(0);
|
||||
the_world.add_object(the_floor);
|
||||
|
||||
// The large sphere in the middle is a unit sphere, translated upward slightly and colored green.
|
||||
the_middle = new Sphere();
|
||||
the_middle->set_transform(Matrix::translation(-0.5, 1, 0.5));
|
||||
the_middle->material().set_color(Color(0.1, 1, 0.5));
|
||||
the_middle->material().set_diffuse(0.7);
|
||||
the_middle->material().set_specular(0.3);
|
||||
the_world.add_object(the_middle);
|
||||
|
||||
// The smaller green sphere on the right is scaled in half
|
||||
the_right = new Sphere();
|
||||
the_right->set_transform(Matrix::translation(1.5, 0.5, -0.5) * Matrix::scaling(0.5, 0.5, 0.5));
|
||||
the_right->material().set_color(Color(0.5, 1, 0.1));
|
||||
the_right->material().set_diffuse(0.7);
|
||||
the_right->material().set_specular(0.3);
|
||||
the_world.add_object(the_right);
|
||||
|
||||
// The smallest sphere is scaled by a third, before being translated
|
||||
the_left = new Sphere();
|
||||
the_left->set_transform(Matrix::translation(-1.5, 0.33, -0.75) * Matrix::scaling(0.33, 0.33, 0.33));
|
||||
the_left->material().set_color(Color(1, 0.8, 0.1));
|
||||
the_left->material().set_diffuse(0.7);
|
||||
the_left->material().set_specular(0.3);
|
||||
the_world.add_object(the_left);
|
||||
|
||||
// The Light source is white, shining from above and to the left
|
||||
the_world.set_light(PointLight(Tuple::Point(-10, 10, -10), Color(1, 1, 1)));
|
||||
|
||||
// Configure the camera.
|
||||
// the_camera = Camera(100, 50, std::numbers::pi / 2);
|
||||
the_camera = Camera(320, 200, std::numbers::pi / 2);
|
||||
the_camera.set_transform(
|
||||
Matrix::view_transform(Tuple::Point(0, 1.5, -3.5), Tuple::Point(0, 1, 0), Tuple::Vector(0, 1, 0)));
|
||||
|
||||
the_start = chrono::high_resolution_clock::now();
|
||||
the_canvas = the_camera.render(the_world);
|
||||
the_end = chrono::high_resolution_clock::now();
|
||||
|
||||
the_canvas.save_to_file("chapter09.ppm");
|
||||
|
||||
chrono::duration<double> the_elapsed_time = the_end - the_start;
|
||||
printf("Execution Time: %f secondes\n", the_elapsed_time.count());
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
data/chapter_09.png
Normal file
BIN
data/chapter_09.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -24,6 +24,7 @@ add_library(raytracing
|
||||
src/renderer/material.cpp
|
||||
src/renderer/ray.cpp
|
||||
src/renderer/world.cpp
|
||||
src/shapes/plane.cpp
|
||||
src/shapes/shape.cpp
|
||||
src/shapes/sphere.cpp
|
||||
)
|
||||
|
||||
@@ -38,4 +38,5 @@
|
||||
#include "renderer/material.h"
|
||||
#include "renderer/ray.h"
|
||||
#include "renderer/world.h"
|
||||
#include "shapes/sphere.h"
|
||||
#include "shapes/plane.h"
|
||||
#include "shapes/sphere.h"
|
||||
|
||||
@@ -34,7 +34,7 @@ using namespace Raytracer;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
IntersectionData::IntersectionData(void) : m_is_inside(false), m_distance(0)
|
||||
IntersectionData::IntersectionData(void) : m_is_inside(false), m_distance(0), m_shape(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ void IntersectionData::set_distance_t(double a_value)
|
||||
|
||||
const Shape &IntersectionData::object(void) const
|
||||
{
|
||||
return m_shape;
|
||||
return *m_shape;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void IntersectionData::set_object(const Shape &a_shape)
|
||||
void IntersectionData::set_object(Shape *a_shape)
|
||||
{
|
||||
m_shape = a_shape;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Raytracer
|
||||
void set_distance_t(double a_value);
|
||||
|
||||
const Shape &object(void) const;
|
||||
void set_object(const Shape &a_shape);
|
||||
void set_object(Shape *a_shape);
|
||||
|
||||
const Tuple &point(void) const;
|
||||
void set_point(const Tuple &a_point);
|
||||
@@ -65,7 +65,7 @@ namespace Raytracer
|
||||
private:
|
||||
bool m_is_inside;
|
||||
double m_distance;
|
||||
Shape m_shape; // TODO ??
|
||||
Shape *m_shape;
|
||||
Tuple m_point;
|
||||
Tuple m_over_point;
|
||||
Tuple m_eyev;
|
||||
|
||||
@@ -36,13 +36,13 @@ using namespace Raytracer;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Intersection::Intersection(void) : m_is_nothing(true), m_distance_t(0.0), m_shape()
|
||||
Intersection::Intersection(void) : m_is_nothing(true), m_distance_t(0.0), m_shape(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Intersection::Intersection(double a_distance_t, const Shape &a_shape) :
|
||||
Intersection::Intersection(double a_distance_t, Shape *a_shape) :
|
||||
m_is_nothing(false),
|
||||
m_distance_t(a_distance_t),
|
||||
m_shape(a_shape)
|
||||
@@ -143,7 +143,7 @@ double Intersection::distance_t(void) const
|
||||
|
||||
const Shape &Intersection::object(void) const
|
||||
{
|
||||
return m_shape;
|
||||
return *m_shape;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -173,7 +173,7 @@ IntersectionData Intersection::prepare_computations(Ray a_ray) const
|
||||
// Precompute some useful values
|
||||
the_data.set_point(a_ray.position(m_distance_t));
|
||||
the_data.set_eyev(-a_ray.direction());
|
||||
the_data.set_normalv(m_shape.normal_at(the_data.point()));
|
||||
the_data.set_normalv(m_shape->normal_at(the_data.point()));
|
||||
the_data.set_over_point(the_data.point() + the_data.normalv() * kEpsilon);
|
||||
the_data.set_inside();
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Raytracer
|
||||
{
|
||||
public:
|
||||
Intersection(void);
|
||||
Intersection(double a_distance_t, const Shape &a_shape);
|
||||
Intersection(double a_distance_t, Shape *a_shape);
|
||||
Intersection(Intersection &an_intersection);
|
||||
Intersection(const Intersection &an_intersection);
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Raytracer
|
||||
private:
|
||||
bool m_is_nothing;
|
||||
double m_distance_t;
|
||||
Shape m_shape;
|
||||
Shape *m_shape;
|
||||
};
|
||||
}; // namespace Raytracer
|
||||
|
||||
|
||||
63
raytracing/src/shapes/plane.cpp
Normal file
63
raytracing/src/shapes/plane.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*!
|
||||
* sphere.cpp
|
||||
*
|
||||
* Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* @Author: NADAL Jean-Baptiste
|
||||
* @Date: 05/02/2024
|
||||
*
|
||||
*/
|
||||
|
||||
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
|
||||
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "core/common.h"
|
||||
#include "core/intersections.h"
|
||||
|
||||
#include "plane.h"
|
||||
|
||||
using namespace Raytracer;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Intersections Plane::local_intersect(const Ray &a_ray)
|
||||
{
|
||||
Intersections the_intersections;
|
||||
|
||||
if (std::abs(a_ray.direction().y()) < kEpsilon)
|
||||
{
|
||||
return the_intersections;
|
||||
}
|
||||
|
||||
double the_t = -a_ray.origin().y() / a_ray.direction().y();
|
||||
|
||||
the_intersections.add(Intersection(the_t, this));
|
||||
|
||||
return the_intersections;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Tuple Plane::local_normal_at(const Tuple &a_local_point) const
|
||||
{
|
||||
return Tuple::Vector(0, 1, 0);
|
||||
}
|
||||
46
raytracing/src/shapes/plane.h
Normal file
46
raytracing/src/shapes/plane.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* plane.h
|
||||
*
|
||||
* Copyright (c) 2024, NADAL Jean-Baptiste. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*
|
||||
* @Author: NADAL Jean-Baptiste
|
||||
* @Date: 27/02/2024
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _RAYTRACER_PLANE_H
|
||||
#define _RAYTRACER_PLANE_H
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#include "shapes/shape.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
namespace Raytracer
|
||||
{
|
||||
class Plane : public Shape
|
||||
{
|
||||
public:
|
||||
Plane(void) = default;
|
||||
Intersections local_intersect(const Ray &a_ray) override;
|
||||
Tuple local_normal_at(const Tuple &a_local_point) const override;
|
||||
};
|
||||
}; // namespace Raytracer
|
||||
|
||||
#endif // _RAYTRACER_PLANE_H
|
||||
@@ -38,23 +38,21 @@ using namespace Raytracer;
|
||||
|
||||
#define kNothing 0
|
||||
|
||||
uint32_t Shape::s_current_index = 0;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Shape::Shape(void) : m_id(kNothing), m_transform(Matrix::identity())
|
||||
Shape::Shape(void) : m_transform(Matrix::identity())
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Shape::Shape(Shape &a_copy) : m_id(a_copy.m_id), m_transform(a_copy.m_transform), m_material(a_copy.m_material)
|
||||
Shape::Shape(Shape &a_copy) : m_transform(a_copy.m_transform), m_material(a_copy.m_material)
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Shape::Shape(const Shape &a_copy) : m_id(a_copy.m_id), m_transform(a_copy.m_transform), m_material(a_copy.m_material)
|
||||
Shape::Shape(const Shape &a_copy) : m_transform(a_copy.m_transform), m_material(a_copy.m_material)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -67,7 +65,6 @@ const Shape &Shape::operator=(const Shape &a_shape)
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_id = a_shape.m_id;
|
||||
m_transform = a_shape.m_transform;
|
||||
m_material = a_shape.m_material;
|
||||
|
||||
@@ -78,7 +75,6 @@ const Shape &Shape::operator=(const Shape &a_shape)
|
||||
|
||||
bool Shape::operator==(const Shape &a_shape) const
|
||||
{
|
||||
// (m_id == a_shape.m_id) && (
|
||||
return (m_transform == a_shape.m_transform) && (m_material == a_shape.m_material);
|
||||
}
|
||||
|
||||
@@ -159,10 +155,3 @@ Intersections Shape::local_intersect(const Ray &a_ray)
|
||||
|
||||
return the_ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void Shape::inc_id(void)
|
||||
{
|
||||
m_id = s_current_index++;
|
||||
}
|
||||
|
||||
@@ -66,14 +66,9 @@ namespace Raytracer
|
||||
Intersections intersect(const Ray &a_ray);
|
||||
virtual Intersections local_intersect(const Ray &a_ray);
|
||||
|
||||
protected:
|
||||
void inc_id(void);
|
||||
|
||||
private:
|
||||
uint32_t m_id;
|
||||
Matrix m_transform;
|
||||
Material m_material;
|
||||
static uint32_t s_current_index;
|
||||
};
|
||||
}; // namespace Raytracer
|
||||
|
||||
|
||||
@@ -39,13 +39,6 @@ using namespace Raytracer;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Sphere::Sphere(void)
|
||||
{
|
||||
inc_id();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
Intersections Sphere::local_intersect(const Ray &a_ray)
|
||||
{
|
||||
Intersections the_intersections;
|
||||
@@ -61,8 +54,8 @@ Intersections Sphere::local_intersect(const Ray &a_ray)
|
||||
if (discriminant >= 0)
|
||||
{
|
||||
double the_sqrt = std::sqrt(discriminant);
|
||||
the_intersections.add(Intersection((-the_b - the_sqrt) / (2 * the_a), *this));
|
||||
the_intersections.add(Intersection((-the_b + the_sqrt) / (2 * the_a), *this));
|
||||
the_intersections.add(Intersection((-the_b - the_sqrt) / (2 * the_a), this));
|
||||
the_intersections.add(Intersection((-the_b + the_sqrt) / (2 * the_a), this));
|
||||
}
|
||||
|
||||
return the_intersections;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Raytracer
|
||||
class Sphere : public Shape
|
||||
{
|
||||
public:
|
||||
Sphere(void);
|
||||
Sphere(void) = default;
|
||||
Intersections local_intersect(const Ray &a_ray) override;
|
||||
Tuple local_normal_at(const Tuple &a_local_point) const override;
|
||||
};
|
||||
|
||||
@@ -234,7 +234,7 @@ SCENARIO("An intersection encapsulates t and object", "[features/intersections.f
|
||||
Sphere s;
|
||||
WHEN("intersection(3.5,s)")
|
||||
{
|
||||
Intersection i(3.5, s);
|
||||
Intersection i(3.5, &s);
|
||||
|
||||
THEN("i.t = 3.5")
|
||||
{
|
||||
@@ -257,7 +257,7 @@ SCENARIO("An intersection could be affected", "[features/intersections.feature]"
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(3.5,s) and i2 <- intersection()")
|
||||
{
|
||||
Intersection i1(3.5, s);
|
||||
Intersection i1(3.5, &s);
|
||||
Intersection i2;
|
||||
|
||||
WHEN("i2 <- i1")
|
||||
@@ -286,8 +286,8 @@ SCENARIO("Intersection could be compared", "[features/intersections.feature]")
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(3,s) and i2 <- intersection(4,s)")
|
||||
{
|
||||
Intersection i1(3.0, s);
|
||||
Intersection i2(4.0, s);
|
||||
Intersection i1(3.0, &s);
|
||||
Intersection i2(4.0, &s);
|
||||
|
||||
THEN("i2 > i1")
|
||||
{
|
||||
@@ -326,10 +326,10 @@ SCENARIO("Aggregating intersections", "[features/intersections.feature]")
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(1,s)")
|
||||
{
|
||||
Intersection i1(1, s);
|
||||
Intersection i1(1, &s);
|
||||
AND_GIVEN("i2 <- intersection(2,s)")
|
||||
{
|
||||
Intersection i2(2, s);
|
||||
Intersection i2(2, &s);
|
||||
WHEN("xs <- intersections(i1,i2)")
|
||||
{
|
||||
Intersections xs = Intersections({i1, i2});
|
||||
@@ -361,7 +361,7 @@ SCENARIO("Operations with intersections", "[features/intersections.feature]")
|
||||
AND_GIVEN("s <- sphere()")
|
||||
{
|
||||
Sphere s;
|
||||
Intersection i1(1, s);
|
||||
Intersection i1(1, &s);
|
||||
AND_GIVEN("xs2 <- intersections({i1})")
|
||||
{
|
||||
Intersections xs2({i1});
|
||||
@@ -423,10 +423,10 @@ SCENARIO("The hit, when all intersections have positive t", "[features/intersect
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(1,s)")
|
||||
{
|
||||
Intersection i1(1, s);
|
||||
Intersection i1(1, &s);
|
||||
AND_GIVEN("i2 <- intersection(2,s)")
|
||||
{
|
||||
Intersection i2(2, s);
|
||||
Intersection i2(2, &s);
|
||||
AND_GIVEN("xs <- intersections(i1,i2)")
|
||||
{
|
||||
Intersections xs = Intersections({i2, i1});
|
||||
@@ -453,10 +453,10 @@ SCENARIO("The hit, when some intersections have negative t", "[features/intersec
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(-1,s)")
|
||||
{
|
||||
Intersection i1(-1, s);
|
||||
Intersection i1(-1, &s);
|
||||
AND_GIVEN("i2 <- intersection(2,s)")
|
||||
{
|
||||
Intersection i2(1, s);
|
||||
Intersection i2(1, &s);
|
||||
AND_GIVEN("xs <- intersections(i1,i2)")
|
||||
{
|
||||
Intersections xs = Intersections({i2, i1});
|
||||
@@ -483,10 +483,10 @@ SCENARIO("The hit, when all intersections have negative t", "[features/intersect
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(-2,s)")
|
||||
{
|
||||
Intersection i1(-2, s);
|
||||
Intersection i1(-2, &s);
|
||||
AND_GIVEN("i2 <- intersection(-1,s)")
|
||||
{
|
||||
Intersection i2(-1, s);
|
||||
Intersection i2(-1, &s);
|
||||
AND_GIVEN("xs <- intersections(i1,i2)")
|
||||
{
|
||||
Intersections xs = Intersections({i1, i2});
|
||||
@@ -514,16 +514,16 @@ SCENARIO("The hit is always the lowest nonnegative intersection", "[features/int
|
||||
Sphere s;
|
||||
AND_GIVEN("i1 <- intersection(5,s)")
|
||||
{
|
||||
Intersection i1(5, s);
|
||||
Intersection i1(5, &s);
|
||||
AND_GIVEN("i2 <- intersection(7,s)")
|
||||
{
|
||||
Intersection i2(7, s);
|
||||
Intersection i2(7, &s);
|
||||
AND_GIVEN("i3 <- intersection(-3,s)")
|
||||
{
|
||||
Intersection i3(-3, s);
|
||||
Intersection i3(-3, &s);
|
||||
AND_GIVEN("i4 <- intersection(2,s)")
|
||||
{
|
||||
Intersection i4(2, s);
|
||||
Intersection i4(2, &s);
|
||||
AND_GIVEN("xs <- intersections(i1, i2, i3, i4)")
|
||||
{
|
||||
Intersections xs = Intersections({i1, i2, i3, i4});
|
||||
|
||||
@@ -143,7 +143,7 @@ SCENARIO("Precompute the state of an intersection", "[features/intersections.fea
|
||||
Sphere shape;
|
||||
AND_GIVEN("i <- intersection(4, shape)")
|
||||
{
|
||||
Intersection i(4, shape);
|
||||
Intersection i(4, &shape);
|
||||
WHEN("comps <- prepare_computations(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
@@ -185,7 +185,7 @@ SCENARIO("The hit, when an intersection occurs on the outside", "[features/inter
|
||||
Sphere shape;
|
||||
AND_GIVEN("i <- intersection(4, shape)")
|
||||
{
|
||||
Intersection i(4, shape);
|
||||
Intersection i(4, &shape);
|
||||
WHEN("comps <- prepare_computations(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
@@ -211,7 +211,7 @@ SCENARIO("The hit, when an intersection occurs on the inside", "[features/inters
|
||||
Sphere shape;
|
||||
AND_GIVEN("i <- intersection(1, shape)")
|
||||
{
|
||||
Intersection i(1, shape);
|
||||
Intersection i(1, &shape);
|
||||
WHEN("comps <- prepare_computations(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
@@ -252,7 +252,7 @@ SCENARIO("Shading an intersection", "[features/world.feature]")
|
||||
Shape *shape = w.objects(0);
|
||||
AND_GIVEN("i <- intersection(4, shape)")
|
||||
{
|
||||
Intersection i(4, *shape);
|
||||
Intersection i(4, shape);
|
||||
WHEN("comps <- prepare_computations(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
@@ -289,7 +289,7 @@ SCENARIO("Shading an intersection from the inside", "[features/world.feature]")
|
||||
Shape *shape = w.objects(1);
|
||||
AND_GIVEN("i <- intersection(0.5, shape)")
|
||||
{
|
||||
Intersection i(0.5, *shape);
|
||||
Intersection i(0.5, shape);
|
||||
WHEN("comps <- prepare_computations(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
|
||||
@@ -164,7 +164,7 @@ SCENARIO("shade_hit() is given an intersection in the shadow", "[features/world.
|
||||
Ray r(Tuple::Point(0, 0, 5), Tuple::Vector(0, 0, 1));
|
||||
AND_GIVEN("i <- intersection(4, s2)")
|
||||
{
|
||||
Intersection i(4, *s2);
|
||||
Intersection i(4, s2);
|
||||
WHEN("comps <- prepare_computatons(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
@@ -200,7 +200,7 @@ SCENARIO("The hit should offset the point", "[features/intersections.feature]")
|
||||
shape.set_transform(Matrix::translation(0, 0, 1));
|
||||
AND_GIVEN("i <- intersection(5, shape)")
|
||||
{
|
||||
Intersection i(5, shape);
|
||||
Intersection i(5, &shape);
|
||||
WHEN("comps <- prepare_computatons(i,r)")
|
||||
{
|
||||
IntersectionData comps = i.prepare_computations(r);
|
||||
|
||||
@@ -244,3 +244,142 @@ SCENARIO("Computing the normal on a transformed shape", "[features/shapes.featur
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("The normal of a plane is constant everywhere", "[features/planes.feature]")
|
||||
{
|
||||
GIVEN("p <- plane()")
|
||||
{
|
||||
Plane p;
|
||||
WHEN("n1 <- local_normal_at(p, point(0, 0, 0)))")
|
||||
{
|
||||
Tuple n1 = p.local_normal_at(Tuple::Point(0, 0, 0));
|
||||
AND_WHEN("n2 <- local_normal_at(p, point(10, 0, 0)))")
|
||||
{
|
||||
Tuple n2 = p.local_normal_at(Tuple::Point(10, 0, 0));
|
||||
AND_WHEN("n3 <- local_normal_at(p, point(-5, 0, 150)))")
|
||||
{
|
||||
Tuple n3 = p.local_normal_at(Tuple::Point(-5, 0, 150));
|
||||
|
||||
THEN("n1 = vector(0, 1, 0)")
|
||||
{
|
||||
REQUIRE(n1 == Tuple::Vector(0, 1, 0));
|
||||
}
|
||||
AND_THEN("n2 = vector(0, 1, 0)")
|
||||
{
|
||||
REQUIRE(n1 == Tuple::Vector(0, 1, 0));
|
||||
}
|
||||
AND_THEN("n3 = vector(0, 1, 0)")
|
||||
{
|
||||
REQUIRE(n1 == Tuple::Vector(0, 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("Intersect with a ray parallel to the plane", "[features/planes.feature]")
|
||||
{
|
||||
GIVEN("p <- plane()")
|
||||
{
|
||||
Plane p;
|
||||
AND_GIVEN("r <- ray(point(0, 10, 0), vector(0, 0, 1))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 10, 0), Tuple::Vector(0, 0, 1));
|
||||
WHEN("xs <-local_intersect(p, r)")
|
||||
{
|
||||
Intersections xs = p.local_intersect(r);
|
||||
THEN("xs is empty")
|
||||
{
|
||||
REQUIRE(xs.count() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("Intersect with a coplanar ray", "[features/planes.feature]")
|
||||
{
|
||||
GIVEN("p <- plane()")
|
||||
{
|
||||
Plane p;
|
||||
AND_GIVEN("r <- ray(point(0, 0, 0), vector(0, 0, 1))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 0, 1));
|
||||
WHEN("xs <-local_intersect(p, r)")
|
||||
{
|
||||
Intersections xs = p.local_intersect(r);
|
||||
THEN("xs is empty")
|
||||
{
|
||||
REQUIRE(xs.count() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("A ray Intersecting a plane from above", "[features/planes.feature]")
|
||||
{
|
||||
GIVEN("p <- plane()")
|
||||
{
|
||||
Plane p;
|
||||
AND_GIVEN("r <- ray(point(0, 1, 0), vector(0, -1, 0))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, 1, 0), Tuple::Vector(0, -1, 0));
|
||||
WHEN("xs <-local_intersect(p, r)")
|
||||
{
|
||||
Intersections xs = p.local_intersect(r);
|
||||
THEN("xs.count = 1")
|
||||
{
|
||||
REQUIRE(xs.count() == 1);
|
||||
}
|
||||
AND_THEN("xs[0].t = 1")
|
||||
{
|
||||
REQUIRE(xs[0].distance_t() == 1);
|
||||
}
|
||||
AND_THEN("xs[0].object = p")
|
||||
{
|
||||
REQUIRE(xs[0].object() == p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
SCENARIO("A ray Intersecting a plane from below", "[features/planes.feature]")
|
||||
{
|
||||
GIVEN("p <- plane()")
|
||||
{
|
||||
Plane p;
|
||||
AND_GIVEN("r <- ray(point(0, -1, 0), vector(0, 1, 0))")
|
||||
{
|
||||
Ray r(Tuple::Point(0, -1, 0), Tuple::Vector(0, 1, 0));
|
||||
WHEN("xs <-local_intersect(p, r)")
|
||||
{
|
||||
Intersections xs = p.local_intersect(r);
|
||||
THEN("xs.count = 1")
|
||||
{
|
||||
REQUIRE(xs.count() == 1);
|
||||
}
|
||||
AND_THEN("xs[0].t = 1")
|
||||
{
|
||||
REQUIRE(xs[0].distance_t() == 1);
|
||||
}
|
||||
AND_THEN("xs[0].object = p")
|
||||
{
|
||||
REQUIRE(xs[0].object() == p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user