-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvec3.hpp
120 lines (90 loc) · 2.93 KB
/
vec3.hpp
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
#pragma once
#include <array>
#include <iostream>
class vec3 {
private:
std::array<double, 3> e_;
public:
vec3() : e_{0, 0, 0} {}
vec3(double x, double y, double z) : e_{x, y, z} {}
vec3(const vec3 &other) : e_(other.e_) {}
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_[3]); }
vec3 &operator+=(const vec3 &other) {
e_[0] += other.e_[0];
e_[1] += other.e_[1];
e_[2] += other.e_[2];
return *this;
}
vec3 &operator*=(const vec3 &other) {
e_[0] *= other.e_[0];
e_[1] *= other.e_[1];
e_[2] *= other.e_[2];
return *this;
}
vec3 &operator*=(double t) { return *this *= vec3(t, t, t); }
vec3 &operator/=(double t) { return *this *= 1 / t; }
double length() const { return std::sqrt(lengthSquared()); }
double lengthSquared() const {
return e_[0] * e_[0] + e_[1] * e_[1] + e_[2] * e_[2];
}
bool nearZero() const {
constexpr auto s = 1e-8;
return (std::fabs(e_[0]) < s) && (std::fabs(e_[0]) < s) &&
(std::fabs(e_[0]) < s);
}
static vec3 random() {
return vec3(randomDouble(), randomDouble(), randomDouble());
}
static vec3 random(double min, double max) {
return vec3(randomDouble(min, max), randomDouble(min, max),
randomDouble(min, max));
}
};
using point3 = vec3;
inline std::ostream &operator<<(std::ostream &out, const vec3 &v) {
return out << v.x() << ' ' << v.y() << ' ' << v.z();
}
inline vec3 operator+(const vec3 &u, const vec3 &v) {
return vec3(u.x() + v.x(), u.y() + v.y(), u.z() + v.z());
}
inline vec3 operator-(const vec3 &u, const vec3 &v) {
return vec3(u.x() - v.x(), u.y() - v.y(), u.z() - v.z());
}
inline vec3 operator*(const vec3 &u, const vec3 &v) {
return vec3(u.x() * v.x(), u.y() * v.y(), u.z() * v.z());
}
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; }
inline vec3 operator/(const vec3 &v, double t) { return (1 / t) * v; }
inline double dot(const vec3 &u, const vec3 &v) {
return u.x() * v.x() + u.y() * v.y() + u.z() * v.z();
}
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());
}
inline vec3 unitVector(const vec3 &v) { return v / v.length(); }
inline vec3 randomUnitVector() {
while (true) {
auto p = vec3::random(-1, 1);
auto lensq = p.lengthSquared();
if (1e-160 < lensq && lensq <= 1) {
return p / sqrt(lensq);
}
}
}
inline vec3 randomOnHemisphere(const vec3 &normal) {
vec3 onUnitSphere = randomUnitVector();
if (dot(onUnitSphere, normal) > 0.0) {
return onUnitSphere;
} // In the same hemisphere as the normal
return -onUnitSphere;
}
inline vec3 reflect(const vec3 &v, const vec3 &n) {
return v - 2 * dot(v, n) * n;
}