[FEAT] Add normalize

This commit is contained in:
NADAL Jean-Baptiste
2024-01-30 15:26:14 +01:00
parent 6bbc2b7d96
commit 65e26baf5f
3 changed files with 101 additions and 46 deletions

View File

@@ -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))
{

View File

@@ -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;
};
};

View File

@@ -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);
}