diff --git a/raytracing/src/tuple.cpp b/raytracing/src/tuple.cpp index 2957a63..0ff1e2d 100644 --- a/raytracing/src/tuple.cpp +++ b/raytracing/src/tuple.cpp @@ -34,13 +34,25 @@ #include "tuple.h" #define kEpsilon 0.00001 -#define square(a) (a)*(a) +#define square(a) (a) * (a) using namespace Raytracer; /* ------------------------------------------------------------------------- */ -Tuple::Tuple(float a_x, float a_y, float a_z, float a_w) : m_x(a_x), m_y(a_y), m_z(a_z), m_w(a_w) +Tuple::Tuple(void) : m_x(0.0), m_y(0.0), m_z(0.0), m_w(0.0) +{ +} + +/* ------------------------------------------------------------------------- */ + +Tuple::Tuple(const Tuple &a_copy) : m_x(a_copy.m_x), m_y(a_copy.m_y), m_z(a_copy.m_z), m_w(a_copy.m_w) +{ +} + +/* ------------------------------------------------------------------------- */ + +Tuple::Tuple(double a_x, double a_y, double a_z, double a_w) : m_x(a_x), m_y(a_y), m_z(a_z), m_w(a_w) { } @@ -48,7 +60,7 @@ Tuple::Tuple(float a_x, float a_y, float a_z, float a_w) : m_x(a_x), m_y(a_y), m bool Tuple::operator==(const Tuple &an_other) const { - if (float_equal(m_x, an_other.m_x) && float_equal(m_y, an_other.m_y) && float_equal(m_z, an_other.m_z) && float_equal(m_w, an_other.m_w)) + if (double_equal(m_x, an_other.m_x) && double_equal(m_y, an_other.m_y) && double_equal(m_z, an_other.m_z) && double_equal(m_w, an_other.m_w)) { return true; } @@ -94,7 +106,7 @@ const Tuple &Tuple::operator-(void) /* ------------------------------------------------------------------------- */ -const Tuple &Tuple::operator*(float a_scalar) +const Tuple &Tuple::operator*(double a_scalar) { m_x *= a_scalar; m_y *= a_scalar; @@ -106,7 +118,7 @@ const Tuple &Tuple::operator*(float a_scalar) /* ------------------------------------------------------------------------- */ -const Tuple &Tuple::operator/(float a_scalar) +const Tuple &Tuple::operator/(double a_scalar) { m_x /= a_scalar; m_y /= a_scalar; @@ -118,42 +130,42 @@ const Tuple &Tuple::operator/(float a_scalar) /* ------------------------------------------------------------------------- */ -Tuple Tuple::Point(float an_x, float an_y, float an_z) +Tuple Tuple::Point(double an_x, double an_y, double an_z) { return Tuple(an_x, an_y, an_z, kRaytracerTuplePoint); } /* ------------------------------------------------------------------------- */ -Tuple Tuple::Vector(float an_x, float an_y, float an_z) +Tuple Tuple::Vector(double an_x, double an_y, double an_z) { return Tuple(an_x, an_y, an_z, kRaytracerTupleVector); } /* ------------------------------------------------------------------------- */ -float Tuple::x(void) const +double Tuple::x(void) const { return m_x; } /* ------------------------------------------------------------------------- */ -float Tuple::y(void) const +double Tuple::y(void) const { return m_y; } /* ------------------------------------------------------------------------- */ -float Tuple::z(void) const +double Tuple::z(void) const { return m_z; } /* ------------------------------------------------------------------------- */ -float Tuple::w(void) const +double Tuple::w(void) const { return m_w; } @@ -162,29 +174,39 @@ float Tuple::w(void) const bool Tuple::is_point(void) { - return float_equal(m_w, kRaytracerTuplePoint); + return double_equal(m_w, kRaytracerTuplePoint); } /* ------------------------------------------------------------------------- */ bool Tuple::is_vector(void) { - return float_equal(m_w, kRaytracerTupleVector); + return double_equal(m_w, kRaytracerTupleVector); } /* ------------------------------------------------------------------------- */ -float Tuple::magnitude(void) +double Tuple::magnitude(void) const { - return sqrtf( - square(m_x) + square(m_y) + square(m_z) + square(m_w) - ); - + return std::sqrt( + square(m_x) + square(m_y) + square(m_z) + square(m_w)); } /* ------------------------------------------------------------------------- */ -bool Tuple::float_equal(float a, float b) const +Tuple Tuple::normalize(void) +{ + double the_magnitude = magnitude(); + + return Tuple(m_x / the_magnitude, + m_y / the_magnitude, + m_z / the_magnitude, + m_w / the_magnitude); +} + +/* ------------------------------------------------------------------------- */ + +bool Tuple::double_equal(double a, double b) const { if ((std::abs((a) - (b)) < kEpsilon)) { diff --git a/raytracing/src/tuple.h b/raytracing/src/tuple.h index d72a728..ae5a2af 100644 --- a/raytracing/src/tuple.h +++ b/raytracing/src/tuple.h @@ -38,37 +38,40 @@ namespace Raytracer class Tuple { public: - Tuple(float an_x, float an_y, float an_z, float an_w); + Tuple(void); + Tuple(const Tuple &a_copy); + Tuple(double an_x, double an_y, double an_z, double an_w); bool operator==(const Tuple &an_other) const; const Tuple &operator+(const Tuple &an_other); const Tuple &operator-(const Tuple &an_other); const Tuple &operator-(void); - const Tuple &operator*(float a_scalar); - const Tuple &operator/(float a_scalar); + const Tuple &operator*(double a_scalar); + const Tuple &operator/(double a_scalar); - static Tuple Point(float an_x, float an_y, float an_z); - static Tuple Vector(float an_x, float an_y, float an_z); + static Tuple Point(double an_x, double an_y, double an_z); + static Tuple Vector(double an_x, double an_y, double an_z); // Access - float x(void) const; - float y(void) const; - float z(void) const; - float w(void) const; + double x(void) const; + double y(void) const; + double z(void) const; + double w(void) const; bool is_point(void); bool is_vector(void); - float magnitude(void); + double magnitude(void) const; + Tuple normalize(void); protected: - float m_x; - float m_y; - float m_z; - float m_w; - + double m_x; + double m_y; + double m_z; + double m_w; + private: - bool float_equal(float a, float b) const; + bool double_equal(double a, double b) const; }; }; diff --git a/tests/chapitre01_tuples.cpp b/tests/chapitre01_tuples.cpp index a8e958a..1e303fa 100644 --- a/tests/chapitre01_tuples.cpp +++ b/tests/chapitre01_tuples.cpp @@ -39,10 +39,10 @@ TEST_CASE("a tuple with w=1.0 is a point", "[Tuple]") { Tuple a(4.3, -4.2, 3.1, 1.0); - REQUIRE(a.x() == 4.3f); - REQUIRE(a.y() == -4.2f); - REQUIRE(a.z() == 3.1f); - REQUIRE(a.w() == 1.0f); + REQUIRE(a.x() == 4.3); + REQUIRE(a.y() == -4.2); + REQUIRE(a.z() == 3.1); + REQUIRE(a.w() == 1.0); REQUIRE(a.is_point() == true); REQUIRE(a.is_vector() == false); @@ -54,10 +54,10 @@ TEST_CASE("a tuple with w=0 is a vector", "[Tuple]") { Tuple a(4.3, -4.2, 3.1, 0.0); - REQUIRE(a.x() == 4.3f); - REQUIRE(a.y() == -4.2f); - REQUIRE(a.z() == 3.1f); - REQUIRE(a.w() == 0.0f); + REQUIRE(a.x() == 4.3); + REQUIRE(a.y() == -4.2); + REQUIRE(a.z() == 3.1); + REQUIRE(a.w() == 0.0); REQUIRE(a.is_point() == false); } @@ -105,7 +105,7 @@ TEST_CASE("Subtracting two points", "[Tuple][Operations]") TEST_CASE("Subtracting a vector from a point", "[Tuple][Operations]") { Tuple p = Tuple::Point(3, 2, 1); - Tuple v= Tuple::Vector(5, 6, 7); + Tuple v = Tuple::Vector(5, 6, 7); REQUIRE((p - v) == Tuple::Point(-2, -4, -6)); } @@ -190,7 +190,7 @@ TEST_CASE("Computing the magnitude of vector(1,2,3)", "[Tuple][Magnitude]") { Tuple v = Tuple::Vector(1, 2, 3); - REQUIRE(v.magnitude() == sqrtf(14)); + REQUIRE(v.magnitude() == sqrt(14)); } /* ------------------------------------------------------------------------- */ @@ -199,5 +199,35 @@ TEST_CASE("Computing the magnitude of vector(-1,-2,-3)", "[Tuple][Magnitude]") { Tuple v = Tuple::Vector(-1, -2, -3); - REQUIRE(v.magnitude() == sqrtf(14)); + REQUIRE(v.magnitude() == sqrt(14)); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("Normalize vector(4,0,0) gives (1,0,0)", "[Tuple][Normalize]") +{ + Tuple v = Tuple::Vector(4, 0, 0); + + REQUIRE(v.normalize() == Tuple::Vector(1, 0, 0)); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("Normalize vector(1,2,3)", "[Tuple][Normalize]") +{ + Tuple v = Tuple::Vector(1, 2, 3); + + REQUIRE(v.normalize() == Tuple::Vector(1 / sqrtf(14), 2 / sqrtf(14), 3 / sqrtf(14))); +} + +/* ------------------------------------------------------------------------- */ + +TEST_CASE("The magnitude of a normalized vector", "[Tuple][Normalize]") +{ + Tuple norm; + Tuple v = Tuple::Vector(1, 2, 3); + + norm = v.normalize(); + + REQUIRE(norm.magnitude() == 1); }