forked from sol-prog/async_tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
/
movie_async_ctrl_threads.cpp
106 lines (88 loc) · 2.75 KB
/
movie_async_ctrl_threads.cpp
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
#include <future>
#include <iostream>
#include <cmath>
#include <string>
#include <chrono>
#include <vector>
#include "ppm.h"
#include "PerlinNoise.h"
//Split "mem" into "parts", e.g. if mem = 10 and parts = 4 you will have: 0,2,4,6,10
//if possible the function will split mem into equal chuncks, if not
//the last chunck will be slightly larger
std::vector<int> bounds(int parts, int mem) {
std::vector<int>bnd;
int delta = mem / parts;
int reminder = mem % parts;
int N1 = 0, N2 = 0;
bnd.push_back(N1);
for (int i = 0; i < parts; ++i) {
N2 = N1 + delta;
if (i == parts - 1)
N2 += reminder;
bnd.push_back(N2);
N1 = N2;
}
return bnd;
}
void make_perlin_noise(int id, int id_width, double z) {
// Define the size of the image
unsigned int width = 1280, height = 720;
// Create an empty PPM image
ppm image(width, height);
// Create a PerlinNoise object with a random permutation vector generated with seed
unsigned int seed = 237;
PerlinNoise pn(seed);
unsigned int kk = 0;
// Visit every pixel of the image and assign a color generated with Perlin noise
for(unsigned int i = 0; i < height; ++i) { // y
for(unsigned int j = 0; j < width; ++j) { // x
double x = (double)j/((double)width);
double y = (double)i/((double)height);
// Wood like structure
double n = 20 * pn.noise(x, y, z);
n = n - floor(n);
// Map the values to the [0, 255] interval, for simplicity we use
// tones of grey
image.r[kk] = floor(255 * n);
image.g[kk] = floor(255 * n);
image.b[kk] = floor(255 * n);
kk++;
}
}
// generate a unique name from id, example
std::string tmp, name;
tmp = std::to_string(id);
if (int diff = id_width - tmp.length()) {
for(int i = 0; i < diff; ++i) name += "0";
}
name = "img_" + name + tmp + ".ppm";
// Save the image in a PPM file
image.write(name);
}
// Control the numbers of threads used
void drive_make_perlin_noise(int left, int right, int id_width, double delta) {
for(int id = left; id < right; ++id) {
double z = (double) id * delta;
make_perlin_noise(id, id_width, z);
}
}
int main() {
std::vector<std::future<void>> futures;
int frames = 1800;
int id_width = 4;
double delta = 1.0 / (double) frames;
//Number of threads to use
int parts = 2;
std::vector<int>bnd = bounds(parts, frames);
auto start = std::chrono::steady_clock::now();
for (int i = 0; i < parts; ++i) {
futures.push_back(std::async(drive_make_perlin_noise, bnd[i], bnd[i + 1], id_width, delta));
}
for(auto &e : futures) {
e.get();
}
auto end = std::chrono::steady_clock::now();
auto diff = end - start;
std::cout << std::chrono::duration <double, std::milli> (diff).count() << " ms" << std::endl;
return 0;
}