summaryrefslogtreecommitdiff
path: root/ray.h
blob: 11baa30c1496ce1aa18ccd5bed7567ee4e2e65dd (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
//
// Created by Keuin on 2022/4/11.
//

#ifndef RT_RAY_H
#define RT_RAY_H

#include "vec.h"
#include "bitmap.h"

// A ray is a half-line, starts from a 3d point, along the direction of a unit vector, to the infinity
template<typename T>
class ray3 {
    vec3<T> source_;
    vec3<T> direction_; // unit vector
    vec3d decay_; // How much power remaining

public:
    ~ray3() = default;

    ray3() = delete;

    ray3(const ray3<T> &other) = default;

    ray3<T> &operator=(const ray3<T> &other) {
        source_ = other.source_;
        direction_ = other.direction_;
        decay_ = other.decay_;
        return *this;
    }

    ray3(const vec3<T> &source, const vec3<T> &direction) :
            source_(source), direction_(direction.unit_vec()), decay_{vec3d::one()} {}

    // Get the source point from where the ray emits.
    vec3<T> source() const {
        return source_;
    }

    void source(const vec3<T> &s) {
        source_ = s;
    }

    // Get the unit vector along the ray's direction.
    vec3<T> direction() const {
        return direction_;
    }

    // d should be a unit vector
    void direction(const vec3<T> &d) {
        assert(fabs(d.mod2() - 1.0) < 1e-6);
        direction_ = d;
    }

    // Compute the point this ray reaches at the time `t`.
    template<typename U>
    vec3<T> at(U t) const {
        return source_ + direction_ * t;
    }

    // Get the final color we got at the ray's origin, by tracing back along with the ray's path.
    // Currently, here is only a simple power decay accumulation.
    template<typename U>
    pixel<U> hit(const pixel<U> &color) const {
        return decay_ * color;
    }

    void decay(const vec3d &a) {
        decay_ = decay_.scale(a);
    }

    vec3d decay() const {
        return decay_;
    }

    // Get a ray starts from zero and directs to undefined direction.
    static ray3<T> null() {
        return ray3<T>{vec3<T>::zero(), vec3<T>::zero()};
    }
};

using ray3d = ray3<double>;

#endif //RT_RAY_H