-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvec3.h
66 lines (64 loc) · 3.72 KB
/
vec3.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef VEC3_H
#define VEC3_H
#include <cmath>
#include <iostream>
#include "utils.h"
struct vec3 {
vec3() : e{0,0,0} {}
vec3(double e) : e{e, e, e} {}
vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}
double e[3];
double x() const {return e[0];}
double y() const {return e[1];}
double z() const {return e[2];}
vec3 operator-() const {return vec3(-e[0], -e[1], -e[2]);}
double operator[](int i) const {return e[i];}
double& operator[](int i) {return e[i];}
vec3& operator+=(const vec3 &v) {e[0] += v.e[0]; e[1] += v.e[1]; e[2] += v.e[2]; return *this;}
vec3& operator-=(const vec3 &v) {e[0] -= v.e[0]; e[1] -= v.e[1]; e[2] -= v.e[2]; return *this;}
vec3& operator*=(const double t) {e[0] *= t; e[1] *= t; e[2] *= t; return *this;}
vec3& operator/=(const double t) {return *this *= 1/t;}
double length() const {return std::sqrt(length_squared());}
double length_squared() const {return e[0]*e[0] + e[1]*e[1] + e[2]*e[2];}
inline static vec3 random() {return vec3(random_double(), random_double(), random_double());}
inline static vec3 random(double min, double max) {return vec3(random_double(min,max), random_double(min,max), random_double(min,max));}
bool near_zero() const {const auto s = 1e-8; return (fabs(e[0]) < s) && (fabs(e[1]) < s) && (fabs(e[2]) < s);}
};
using point3 = vec3; using color = vec3;
inline std::ostream& operator<<(std::ostream &out, const vec3 &v) {return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2];}
inline vec3 operator+(const vec3 &u, const vec3 &v) {return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]);}
inline vec3 operator-(const vec3 &u, const vec3 &v) {return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]);}
inline vec3 operator*(const vec3 &u, const vec3 &v) {return vec3(u.e[0]*v.e[0], u.e[1]*v.e[1], u.e[2]*v.e[2]);}
inline vec3 operator*(double t, const vec3 &v) {return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);}
inline vec3 operator*(const vec3 &v, double t) {return t*v;}
inline vec3 operator/(vec3 v, double t) {return (1/t)*v;}
inline double dot(const vec3 &u, const vec3 &v) {return u.e[0]*v.e[0] + u.e[1]*v.e[1] + u.e[2]*v.e[2];}
inline vec3 cross(const vec3 &u, const vec3 &v) {return vec3(u.e[1]*v.e[2] - u.e[2]*v.e[1], u.e[2]*v.e[0] - u.e[0]*v.e[2], u.e[0]*v.e[1] - u.e[1]*v.e[0]);}
// unit stuff
inline vec3 unit_vector(vec3 v) {return v/v.length();}
vec3 random_in_unit_sphere() {while (true) {auto p = vec3::random(-1,1); if (p.length_squared() < 1) return p;}}
vec3 random_unit_vector() {return unit_vector(random_in_unit_sphere());}
vec3 random_in_hemisphere(const vec3& normal) {vec3 vec = random_in_unit_sphere(); if (dot(vec, normal) > 0.0) return vec; else return -vec;}
vec3 random_in_unit_disk() {while (true) {auto p = vec3(random_double(-1,1), random_double(-1,1), 0); if (p.length_squared() < 1) return p;}}
inline vec3 random_cosine_direction() {
auto r1 = random_double(), r2 = random_double();
auto z = sqrt(1 - r2), phi = 2 * Pi * r1, sqrtr2 = sqrt(r2);
auto x = cos(phi)*sqrtr2, y = sin(phi)*sqrtr2;
return vec3(x, y, z);
}
inline vec3 random_to_sphere(double radius, double distance_squared) {
auto r1 = random_double(), r2 = random_double();
auto z = 1 + r2*(sqrt(1 - radius*radius/distance_squared) - 1);
auto phi = 2*Pi*r1;
auto x = cos(phi)*sqrt(1 - z*z), y = sin(phi)*sqrt(1 - z*z);
return vec3(x, y, z);
}
// optics stuff
vec3 reflect(const vec3& v, const vec3& n) {return v - 2*dot(v,n)*n;}
vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat) {
auto cos_theta = fmin(dot(-uv, n), 1.0);
vec3 r_out_perp = etai_over_etat * (uv + cos_theta*n);
vec3 r_out_parallel = -sqrt(fabs(1.0 - r_out_perp.length_squared())) * n;
return r_out_perp + r_out_parallel;
}
#endif