-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
162 lines (134 loc) · 5.17 KB
/
main.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
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#pragma clang diagnostic push
#pragma ide diagnostic ignored "openmp-use-default-none"
#include <cstdio>
#include <cstdint>
//opencv headers
#include <random>
#include <opencv2/core/mat.hpp> //cv::Mat
#include <opencv2/highgui.hpp> //cv::imshow, cv::waitKey
#include <opencv2/imgproc.hpp> //cv::imread
#include "timer.h"
static const unsigned int COLS = 1920 ;
static const unsigned int ROWS = 1080 ;
static const unsigned int DEAD = 0;
static const unsigned int ALIVE = 255;
static const unsigned int GENERATIONS = 1000;
int main() {
cv::Mat buffer1(ROWS, COLS, CV_8UC1);
cv::Mat buffer2(ROWS, COLS, CV_8UC1);
std::mt19937_64 engine(
static_cast<uint64_t> (std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())));
std::uniform_real_distribution<double> rngDistribution(0.0, 1.0);
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (row == 0 || col == 0 || row == ROWS - 1 || col == COLS - 1) {
buffer1.at<uint8_t>(row, col) = DEAD;
} else {
if (rngDistribution(engine) > 0.9) {
buffer1.at<uint8_t>(row, col) = ALIVE;
} else {
buffer1.at<uint8_t>(row, col) = DEAD;
}
}
}
}
cv::Mat *renderBufferPtr = &buffer2;
cv::Mat *modelBufferPtr = &buffer1;
uint64_t generation = 0;
cv::namedWindow("Game of life", cv::WINDOW_NORMAL | cv::WINDOW_KEEPRATIO);
cv::setWindowProperty("Game of life", cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
Timer logicTimer;
float logicMs = 0.f;
Timer renderTimer;
float renderMs = 0.f;
float sumTime = logicMs;
cv::Mat rgbDebugRenderImg(ROWS, COLS, CV_8UC3);
do {
//rendering
renderTimer.reset();
{
if (renderBufferPtr == &buffer1) {
renderBufferPtr = &buffer2;
modelBufferPtr = &buffer1;
} else {
renderBufferPtr = &buffer1;
modelBufferPtr = &buffer2;
}
#pragma omp parallel for num_threads(4)
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
uint8_t pix = renderBufferPtr->at<uint8_t>(row, col);
rgbDebugRenderImg.at<cv::Vec3b>(row, col) = cv::Vec3b(pix, pix, pix);
}
}
cv::putText(rgbDebugRenderImg, //target image
"Logic: " + std::to_string(logicMs) + " ms", //text
cv::Point(10, 30), //top-left position
cv::FONT_HERSHEY_DUPLEX,
1.f,
CV_RGB(255, 0, 0), //font color
2);
cv::putText(rgbDebugRenderImg, //target image
"Render: " + std::to_string(renderMs) + " ms", //text
cv::Point(10, 60), //top-left position
cv::FONT_HERSHEY_DUPLEX,
1.f,
CV_RGB(255, 0, 0), //font color
2);
cv::putText(rgbDebugRenderImg, //target image
"Generation: " + std::to_string(generation), //text
cv::Point(10, 90), //top-left position
cv::FONT_HERSHEY_DUPLEX,
1.f,
CV_RGB(255, 0, 0), //font color
2);
// cv::imshow("Game of life", *renderBufferPtr);
cv::imshow("Game of life", rgbDebugRenderImg);
*modelBufferPtr = renderBufferPtr->clone();
}
renderMs = renderTimer.elapsed();
//Game logic
logicTimer.reset();
{
#pragma omp parallel for num_threads(4)
for (int row = 1; row < ROWS - 1; row++) {
for (int col = 1; col < COLS - 1; col++) {
uint8_t pix = modelBufferPtr->at<uint8_t>(row, col);
int aliveNeighbors = 0;
aliveNeighbors = renderBufferPtr->at<uint8_t>(row - 1, col - 1) +
renderBufferPtr->at<uint8_t>(row - 1, col) +
renderBufferPtr->at<uint8_t>(row - 1, col + 1) +
renderBufferPtr->at<uint8_t>(row, col - 1) +
renderBufferPtr->at<uint8_t>(row, col + 1) +
renderBufferPtr->at<uint8_t>(row + 1, col - 1) +
renderBufferPtr->at<uint8_t>(row + 1, col) +
renderBufferPtr->at<uint8_t>(row + 1, col + 1);
aliveNeighbors /= ALIVE;
if (pix == DEAD) {
if (aliveNeighbors == 3) {
//Jesus f***ing Christ is alive
pix = ALIVE;
}
} else {
if (aliveNeighbors < 2 || aliveNeighbors > 3) {
//Die motherfucker
pix = DEAD;
}
if (aliveNeighbors == 2 || aliveNeighbors == 3) {
//Stay alive... for now
pix = ALIVE;
}
}
modelBufferPtr->at<uint8_t>(row, col) = pix;
}
}
}
logicMs = logicTimer.elapsed() * 1000.f;
printf("Generation: %d\t elapsed: %fms\t render: %fms\n", generation++, logicMs, renderMs);
sumTime += logicMs;
} while (cv::waitKey(1) < 0 /*&& generation < GENERATIONS*/);
float avgTime = sumTime / generation;
printf("Average time: %f ms\n", avgTime);
return 0;
}
#pragma clang diagnostic pop