aboutsummaryrefslogtreecommitdiffstats
path: root/vec3.h
blob: 46367d21a51c8baa357ce9e6b4e2ca967453c67f (plain)
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
#ifndef VEC3_H
#define VEC3_H

#include "random.h"

#include <cmath>
#include <iostream>

struct vec3 {
  public:
    double e[3];

    constexpr vec3() : e{0,0,0} {}
    constexpr vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}

    constexpr double x() const { return e[0]; }
    constexpr double y() const { return e[1]; }
    constexpr double z() const { return e[2]; }
    double& x() { return e[0]; }
    double& y() { return e[1]; }
    double& z() { return e[2]; }

    constexpr vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
    constexpr double operator[](int i) const { return e[i]; }
    constexpr double& operator[](int i) { return e[i]; }

    constexpr vec3& operator+=(const vec3& v) {
        e[0] += v.e[0];
        e[1] += v.e[1];
        e[2] += v.e[2];
        return *this;
    }

    constexpr vec3& operator*=(double t) {
        e[0] *= t;
        e[1] *= t;
        e[2] *= t;
        return *this;
    }

    constexpr vec3& operator/=(double t) {
        return *this *= 1/t;
    }

    constexpr vec3 operator+(const vec3& v) const {
        return vec3(e[0] + v.e[0], e[1] + v.e[1], e[2] + v.e[2]);
    }
    
    constexpr vec3 operator-(const vec3& v) const {
        return vec3(e[0] - v.e[0], e[1] - v.e[1], e[2] - v.e[2]);
    }
    
    constexpr vec3 operator*(const vec3& v) const {
        return vec3(e[0] * v.e[0], e[1] * v.e[1], e[2] * v.e[2]);
    }
    
    constexpr vec3 operator*(double t) const {
        return vec3(t*e[0], t*e[1], t*e[2]);
    }

    constexpr vec3 operator/(double t) const {
        t = 1 / t;
        return vec3(t*e[0], t*e[1], t*e[2]);
    }
    
    constexpr double length() const {
        return std::sqrt(length_squared());
    }

    constexpr double length_squared() const {
        return e[0]*e[0] + e[1]*e[1] + e[2]*e[2];
    }

    constexpr vec3 normalize() const {
        auto v = *this;
        v /= length();
        return v;
    }

    constexpr double dot(const vec3& v) const {
        return e[0] * v.e[0] + e[1] * v.e[1] + e[2] * v.e[2];
    }

    constexpr vec3 reflect(vec3 v) const {
        v *= -2 * dot(v);
        v += *this;
        return v;
    }

    constexpr vec3 refract(vec3 v, double etaietat) const {
        auto inv = -(*this);
        auto cos_theta = std::min(inv.dot(v), 1.0);
        auto rperp = (*this + v * cos_theta) * etaietat;
        auto rpara = v * -std::sqrt(std::fabs(1.0 - rperp.length_squared()));
        return rperp + rpara;
    }
};

// point3 is just an alias for vec3, but useful for geometric clarity in the code.
using point3 = vec3;

// Vector Utility Functions

inline std::ostream& operator<<(std::ostream& out, const vec3& v) {
    return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2];
}

constexpr inline vec3 operator*(double t, const vec3& v) {
    return v * t;
}
    
constexpr inline vec3 operator/(double t, const vec3& v) {
    return v * (1 / t);
}

inline constexpr 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]);
}

inline constexpr vec3 unit_vector(const vec3& v) {
    return v / v.length();
}

inline vec3 randomUnitSphere() {
    for (;;) {
        if (auto p = vec3(randomN(), randomN(), randomN()) * 2 - vec3(1, 1, 1); p.length_squared() < 1)
            return p;
    }
}

inline vec3 randomHemisphere(const vec3& normal) {
    vec3 unit = randomUnitSphere().normalize();
    return unit.dot(normal) > 0 ? unit : -unit;
}

#endif