#ifndef VEC3_H #define VEC3_H #include "rtweekend.hpp" struct vec3 { /* Members */ double x; double y; double z; // Constructor proper. Values default to 0 vec3(double x = 0, double y = 0, double z = 0) { this->x = x; this->y = y; this->z = z; } /* Overriden operators */ // - operator. Not to be confused with substraction vec3 operator-() const { return vec3(-x, -y, -z); } // Straightforward vector sum vec3& operator+=(const vec3 &v) { this->x += v.x; this->y += v.y; this->z += v.z; return *this; } // Scalar multiplication vec3& operator*=(const double t) { x *= t; y *= t; z *= t; return *this; } // Division by a scalar t vec3& operator/=(const double t) { x /= t; y /= t; z /= t; return *this; } /* Methods */ double length() const { return sqrt(x*x + y*y + z*z); } // Length squared, useful for some calculations double length_squared() const { return x*x + y*y + z*z; } // Get a vec3 with random components in the range [0,1) inline static vec3 random() { return vec3(random_double(), random_double(), random_double()); } // Get a vec3 with random components in the range [min, max) inline static vec3 random(double min, double max) { return vec3(random_double(min, max), random_double(min, max), random_double(min, max)); } // Check if all vector components are near zero bool near_zero() const { double s = 1e-8; return (fabs(x) < s) && (fabs(y) < s) && (fabs(z) < s); } }; /* Type aliases */ typedef vec3 point3; typedef vec3 color; /* More overloads */ // Straightforward vector sum inline vec3 operator+(const vec3 &u, const vec3 &v) { return vec3(u.x + v.x, u.y + v.y, u.z + v.z); } // Straightforward vector difference inline vec3 operator-(const vec3 &u, const vec3 &v) { return vec3(u.x - v.x, u.y - v.y, u.z - v.z); } // Hadamard product inline vec3 operator*(const vec3 &u, const vec3 &v) { return vec3(u.x * v.x, u.y * v.y, u.z * v.z); } // Scalar product inline vec3 operator*(double t,const vec3 &v) { return vec3(t*v.x, t*v.y, t*v.z); } inline vec3 operator*(const vec3 &v, double t) { return t * v; } // Vector division by scalar. Note that we redefine it as multiplying by 1/t to avoid division by 0 inline vec3 operator/(vec3 v, double t) { return 1/t * v; } // Straightforward dot product inline double dot(const vec3 &u, const vec3 &v) { return u.x*v.x + u.y*v.y + u.z*v.z; } // Cross product between two vectors inline vec3 cross(const vec3 &u, const vec3 &v) { return vec3(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x); } // Normalize vector so its length = 1 inline vec3 normalize(const vec3 v) { return v / v.length(); } // Returns a vec3 of random components between [-1,1) that is inside a unit sphere vec3 random_in_unit_sphere() { // Iterate until we find a vector with length < 1 while (true) { vec3 p = vec3::random(-1,1); if (p.length_squared() >= 1) continue; return p; } } // Returns a normalized version of the above vector vec3 random_unit_vector() { return normalize(random_in_unit_sphere()); } vec3 random_in_hemisphere(const vec3& normal) { vec3 in_unit_sphere = random_in_unit_sphere(); if (dot(in_unit_sphere, normal) > 0.0) return in_unit_sphere; else return -in_unit_sphere; } // Reflect like a metallic material vec3 reflect(const vec3& v, const vec3 n) { return v - 2*dot(v,n)*n; } #endif