-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvec3.h
140 lines (99 loc) · 3.99 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef VEC3_H
#define VEC3_H
#include <cmath>
#include <ostream>
double const PI = 3.1415926535897932385;
class Vec3 {
public:
double x;
double y;
double z;
Vec3();
Vec3(double i, double j, double k);
Vec3 operator+(Vec3 const & right) const;
Vec3 operator-() const;
Vec3 operator-(Vec3 const & right) const;
Vec3 operator*(double const constant) const;
Vec3 operator/(double const constant) const;
double length_squared() const;
double length() const;
Vec3 unit() const;
bool is_near_zero() const;
Vec3 reflect(Vec3 const & normal);
Vec3 refract(Vec3 const & normal, double const refractiveIndexRatio);
double dot(Vec3 const & right) const;
Vec3 cross(Vec3 const & right) const;
};
Vec3 operator*(double left, Vec3 const & right);
std::ostream & operator<<(std::ostream & out, Vec3 const & v);
using Point3 = Vec3;
// ------
Vec3::Vec3() : x(0), y(0), z(0) { }
Vec3::Vec3(double i, double j, double k) : x(i), y(j), z(k) { }
Vec3 Vec3::operator+(Vec3 const & right) const {
return Vec3(this->x + right.x, this->y + right.y, this->z + right.z);
}
Vec3 Vec3::operator-() const {
return Vec3(-this->x, -this->y, -this->z);
}
Vec3 Vec3::operator-(Vec3 const & right) const {
return Vec3(this->x - right.x, this->y - right.y, this->z - right.z);
}
Vec3 Vec3::operator*(double const constant) const {
return Vec3(constant * this->x, constant * this->y, constant * this->z);
}
Vec3 Vec3::operator/(double const constant) const {
return *this * (1 / constant);
}
double Vec3::length_squared() const {
return (x * x) + (y * y) + (z * z);
}
double Vec3::length() const {
return std::sqrt(this->length_squared());
}
Vec3 Vec3::unit() const {
return *this / this->length();
}
bool Vec3::is_near_zero() const {
auto const granularity = 1e-8;
return (fabs(x) < granularity) && (fabs(y) < granularity) && (fabs(z) < granularity);
}
// reflects this Vec3 along the normal vector given
// reflection of a vector v is v - 2(the projection of v onto the normal)
// which leads to the equation v - 2(v.n)*n
Vec3 Vec3::reflect(Vec3 const & normal) {
return *this - ((2 * this->dot(normal)) * normal);
}
// refraction is a ray coming into a material one angle from a normal, and
// leaving at another angle from the normal into the second material
// this function returns the refracted vector
// normal is the vector perpendicular to the material surface where the ray is coming,
// default direction is "upwards" from the material
// refractiveIndexRatio is the ratio of the refractive index of the outside material (usually air)
// over the inside material of the inside
// NOTE: "this" vector must be a unit vector when you use this function on it
Vec3 Vec3::refract(Vec3 const & normal, double const refractiveIndexRatio) {
Vec3 thisVec = *this;
// the component of the refracted vector that is perpendicular to the normal
Vec3 refractedVectorPerp = refractiveIndexRatio * (thisVec + (fmin((-thisVec).dot(normal), 1.0) * normal));
// the component of the refracted vector that is parallel to the normal
Vec3 refractedVectorParallel = -sqrt(fabs(1.0 - refractedVectorPerp.length_squared())) * normal;
return refractedVectorParallel + refractedVectorPerp;
}
double Vec3::dot(Vec3 const & right) const {
return (this->x * right.x) + (this->y * right.y) + (this->z * right.z);
}
Vec3 Vec3::cross(Vec3 const & right) const {
return Vec3((this->y * right.z) - (this->z * right.y),
(this->z * right.x) - (this->x * right.z),
(this->x * right.y) - (this->y * right.x));
}
// specific overload for when constant is on the left hand side of the operator
// so technically this is an overload for double
Vec3 operator*(double const left, Vec3 const & right) {
return right * left;
}
std::ostream & operator<<(std::ostream & out, Vec3 const & v) {
return out << v.x << " " << v.y << " " << v.z;
}
#endif