10 vec3(Real e0, Real e1, Real e2) : e{e0, e1, e2} {}
11 vec3(Real e0) : e{e0, e0, e0} {}
12 vec3(
const Real e1[3]) : e{e1[0], e1[1], e1[2]} {}
14 Real x()
const {
return e[0]; }
15 Real y()
const {
return e[1]; }
16 Real z()
const {
return e[2]; }
17 Real r()
const {
return x(); }
18 Real g()
const {
return y(); }
19 Real b()
const {
return z(); }
21 vec3 operator-()
const {
22 return vec3(-e[0], -e[1], -e[2]);
24 Real operator[](
int i)
const {
return e[i]; }
25 Real &operator[](
int i) {
return e[i]; }
32 vec3 &operator*=(
const Real t) {
38 vec3 &operator/=(
const Real t) {
return *
this *= 1 / t; }
40 return vec3(x() + v.x(), y() + v.y(), z() + v.z());
42 Real sum() {
return x() + y() + z(); }
43 Real average() {
return sum() / 3.0; }
44 vec3 add(
const Real &v) {
45 return vec3(x() + v, y() + v, z() + v);
47 vec3 subt(
const Real &v) {
48 return vec3(x() - v, y() - v, z() - v);
51 return vec3(x() - v.x(), y() - v.y(), z() - v.z());
54 return vec3(x() * v.x(), y() * v.y(), z() * v.z());
56 vec3 multip(
const Real &v) {
57 return vec3(x() * v, y() * v, z() * v);
59 vec3 div(
const Real &v) {
61 throw std::runtime_error(
"no zero division");
62 return vec3(x() / v, y() / v, z() / v);
66 throw std::runtime_error(
67 "no zero division x is zero");
69 throw std::runtime_error(
70 "no zero division y is zero");
72 throw std::runtime_error(
73 "no zero division z is zero");
74 return vec3(x() / v.x(), y() / v.y(), z() / v.z());
76 Real length()
const {
return sqrt(length_squared()); }
77 Real length_squared()
const {
78 return e[0] * e[0] + e[1] * e[1] + e[2] * e[2];
80 inline Real min()
const {
81 return fmin(fmin(x(), y()), z());
83 inline Real max()
const {
84 return fmax(fmax(x(), y()), z());
86 bool near_zero()
const {
90 return (fabs(e[0]) < s) && (fabs(e[1]) < s) &&
93 inline static vec3 random() {
94 return vec3(random_real(), random_real(),
97 inline static vec3 random(Real min, Real max) {
98 return vec3(random_real(min, max),
99 random_real(min, max),
100 random_real(min, max));
102 std::vector<Real> to_vector()
const {
103 std::vector<Real> vdata(3);
109 void conditional_set(
110 Real setval,
int index,
111 const std::function<
bool(Real indval)> &fn) {
116 void conditional_set(
118 const std::function<
bool(Real indval)> &fn) {
119 for (
int index = 0; index < 3; index++) {
135 inline std::ostream &operator<<(std::ostream &out,
137 return out << v.e[0] <<
' ' << v.e[1] <<
' ' << v.e[2];
139 inline vec3 operator+(
const vec3 &u,
const vec3 &v) {
140 return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1],
143 inline vec3 operator-(
const vec3 &u,
const vec3 &v) {
144 return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1],
147 inline vec3 operator*(
const vec3 &u,
const vec3 &v) {
148 return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1],
151 inline vec3 operator*(Real t,
const vec3 &v) {
152 return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
154 inline vec3 operator*(
const vec3 &v, Real t) {
157 inline vec3 operator/(vec3 v, Real t) {
160 inline vec3 operator/(Real t, vec3 v) {
163 inline vec3 operator/(vec3 v, vec3 t) {
167 inline Real dot(
const vec3 &u,
const vec3 &v) {
168 return u.e[0] * v.e[0] + u.e[1] * v.e[1] +
171 vec3 sqrt_vec(
const vec3 &v) {
172 auto r = sqrt(v.x());
173 auto g = sqrt(v.y());
174 auto b = sqrt(v.z());
175 vec3 rgb = vec3(r, g, b);
178 vec3 clamp(
const vec3 &v, Real mn, Real mx) {
179 auto r = clamp(v.x(), mn, mx);
180 auto g = clamp(v.y(), mn, mx);
181 auto b = clamp(v.z(), mn, mx);
182 return vec3(r, g, b);
184 inline vec3 cross(
const vec3 &u,
const vec3 &v) {
185 return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1],
186 u.e[2] * v.e[0] - u.e[0] * v.e[2],
187 u.e[0] * v.e[1] - u.e[1] * v.e[0]);
190 inline vec3 unit_vector(vec3 v) {
return v / v.length(); }
191 inline vec3 min_vec(
const vec3 &v1,
const vec3 &v2) {
192 float x = fmin(v1.x(), v2.x());
193 float y = fmin(v1.y(), v2.y());
194 float z = fmin(v1.z(), v2.z());
195 return vec3(x, y, z);
197 inline vec3 max_vec(
const vec3 &v1,
const vec3 &v2) {
198 float x = fmax(v1.x(), v2.x());
199 float y = fmax(v1.y(), v2.y());
200 float z = fmax(v1.z(), v2.z());
201 return vec3(x, y, z);
204 inline vec3 random_in_unit_disk() {
207 vec3(random_real(-1, 1), random_real(-1, 1), 0);
208 if (p.length_squared() >= 1)
214 inline vec3 random_in_unit_sphere() {
216 auto p = vec3::random(-1, 1);
217 if (p.length_squared() >= 1)
223 inline vec3 random_unit_vector() {
224 return unit_vector(random_in_unit_sphere());
227 inline vec3 random_in_hemisphere(
const vec3 &normal) {
228 vec3 in_unit_sphere = random_in_unit_sphere();
229 if (dot(in_unit_sphere, normal) >
231 return in_unit_sphere;
233 return -in_unit_sphere;
236 inline vec3 reflect(
const vec3 &v,
const vec3 &n) {
237 return v - 2 * dot(v, n) * n;
240 inline vec3 refract(
const vec3 &uv,
const vec3 &n,
241 Real etai_over_etat) {
242 auto cos_theta = fmin(dot(-uv, n), 1.0);
243 vec3 r_out_perp = etai_over_etat * (uv + cos_theta * n);
244 vec3 r_out_parallel =
245 -sqrt(fabs(1.0 - r_out_perp.length_squared())) * n;
246 return r_out_perp + r_out_parallel;
249 inline vec3 random_cosine_direction() {
250 auto r1 = random_real();
251 auto r2 = random_real();
252 auto z = sqrt(1 - r2);
254 auto phi = 2 * M_PI * r1;
255 auto x = cos(phi) * sqrt(r2);
256 auto y = sin(phi) * sqrt(r2);
258 return vec3(x, y, z);
261 inline vec3 random_to_sphere(Real radius,
262 Real distance_squared) {
263 auto r1 = random_real();
264 auto r2 = random_real();
267 r2 * (sqrt(1 - radius * radius / distance_squared) -
270 auto phi = 2 * M_PI * r1;
271 auto x = cos(phi) * sqrt(1 - z * z);
272 auto y = sin(phi) * sqrt(1 - z * z);
274 return vec3(x, y, z);