]> git.sesse.net Git - nageru/blob - util.h
Fix a problem with visualizing flow that goes exactly left.
[nageru] / util.h
1 #ifndef _UTIL_H
2 #define _UTIL_H 1
3
4 #include <math.h>
5 #include <stdint.h>
6 #include <algorithm>
7 #include <memory>
8
9 struct Vec2 {
10         float du, dv;
11 };
12
13 struct Flow {
14         uint32_t width, height;
15         std::unique_ptr<Vec2[]> flow;
16 };
17
18 Flow read_flow(const char *filename);
19
20 // du and dv are in pixels.
21 inline void flow2rgb(float du, float dv, uint8_t *rr, uint8_t *gg, uint8_t *bb)
22 {
23         float angle = atan2(dv, du);
24         float magnitude = std::min(hypot(du, dv) / 20.0, 1.0);
25         
26         // HSV to RGB (from Wikipedia). Saturation is 1.
27         float c = magnitude;
28         float h = (angle + M_PI) * 6.0 / (2.0 * M_PI);
29         float X = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
30         float r = 0.0f, g = 0.0f, b = 0.0f;
31         if (h <= 1.0f) {
32                 r = c; g = X;
33         } else if (h <= 2.0f) {
34                 r = X; g = c;
35         } else if (h <= 3.0f) {
36                 g = c; b = X;
37         } else if (h <= 4.0f) {
38                 g = X; b = c;
39         } else if (h <= 5.0f) {
40                 r = X; b = c;
41         } else if (h <= 6.0f) {
42                 r = c; b = X;
43         } else {
44                 // h is NaN, so black is fine.
45         }
46         float m = magnitude - c;
47         r += m; g += m; b += m;
48         r = std::max(std::min(r, 1.0f), 0.0f);
49         g = std::max(std::min(g, 1.0f), 0.0f);
50         b = std::max(std::min(b, 1.0f), 0.0f);
51         *rr = lrintf(r * 255.0f);
52         *gg = lrintf(g * 255.0f);
53         *bb = lrintf(b * 255.0f);
54 }
55
56 #endif  // !defined(_UTIL_H)