aboutsummaryrefslogtreecommitdiffstats
path: root/view.h
blob: 0f973580cb422790091d6fd142da293849991fe3 (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
#ifndef VIEW_H
#define VIEW_H

#include "random.h"
#include "vec3.h"

#include <cmath>

struct View
{
    static constexpr auto lookat = point3(0, 0, -1); // Point camera is looking at
    static constexpr auto vup    = vec3(0, 1, 0);    // Camera-relative "up" direction

    float fieldOfView = 90.f;
    point3 camera {0, 0.5, 0.5};

    float focalLength;
    float viewportHeight;
    float viewportWidth;
    vec3 viewportX;
    vec3 viewportY;
    vec3 pixelDX;
    vec3 pixelDY;
    vec3 viewportUL;
    vec3 pixelUL;

    View() {
        recalculate();
    }

    void recalculate() {
        focalLength = (camera - lookat).length();
        viewportHeight = 2 * std::tan(fieldOfView * 3.14159265 / 180.0 / 2.0) * focalLength;
        viewportWidth  = viewportHeight * Aspect;

        const auto w = (camera - lookat).normalize();
        const auto u = cross(vup, w).normalize();
        const auto v = cross(w, u);

        viewportX = viewportWidth * u;
        viewportY = -viewportHeight * v;

        pixelDX = viewportX / Width;
        pixelDY = viewportY / Height;
        viewportUL = camera - focalLength * w - viewportX / 2 - viewportY / 2;
        pixelUL = viewportUL + 0.5 * (pixelDX + pixelDY);
    }

    ray getRay(int x, int y, bool addRandom = false) const {
        double X = x;
        double Y = y;

        if (addRandom) {
            X += randomN() - 0.5;
            Y += randomN() - 0.5;
        }

        auto pixel = pixelUL + X * pixelDX + Y * pixelDY;
        return ray(camera, pixel - camera);
    }
};

#endif // VIEW_H