-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcosmos_sketch.cpp
176 lines (108 loc) · 3.42 KB
/
cosmos_sketch.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
### cosmos_sketch
To compile, use the command
```bash
clang++ cosmos_sketch.cpp -o cosmos_sketch -std=c++11 -lOpenCL
```
To run, use the command
```bash
./cosmos_sketch <frames> [bodies=24576]
```
This will cause cosmos_sketch to output a bunch of ugly rendered frames to the
directory that it was started in. These rendered frames will be image files,
produced by rendering the corresponding simulation frames generated by running
cosmos_simulate.
## Even more speed
To speed up simulations and renders even more, compile with
```bash
clang++ cosmos_tool.cpp -o cosmos_tool -std=c++11 -lOpenCL -Ofast -march=native
```
*/
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
#include <memory>
// Include stb_image_write.
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
// Include OpenCL.
#ifdef __APPLE__
#define CL_SILENCE_DEPRECATION
#include <OpenCL/OpenCL.h>
#else
#include <CL/cl.h>
#endif
// Include the thermal colormap.
#include "thermal_colormap.h"
// Entry point.
int main(int argc, char** argv)
{
// Parse command line arguments.
if (argc != 2)
{
std::cout << "Usage: " << argv[0] << " <frames> [bodies=24576]" << std::endl;
return EXIT_FAILURE;
}
int frames = atoi(argv[1]);
int n = 24576;
if (argc == 3)
{
n = atoi(argv[2]);
}
// Allocate a buffer to hold the frame body data.
cl_float4* bodies = (cl_float4*)malloc(n * sizeof(cl_float4));
// PARAM: The dimensions of the image (which is square).
int res = 800;
// Allocate a buffer to hold the rendered frame.
unsigned char* img = (unsigned char*)malloc(res * res * 3 * sizeof(unsigned char));
int stride_in_bytes = res * 3;
// Start the render!
for (int i = 0; i < frames; i++)
{
// Get the starting time.
clock_t frame_start = clock();
// Load the current frame.
std::stringstream name_builder;
name_builder << "frame_" << i << ".dat";
std::ifstream frame(name_builder.str());
frame.read((char*)bodies, n * sizeof(cl_float4));
frame.close();
// PARAM: The zoom factor.
float inv_scale = i / 60.0f;
// Clear the frame.
memset(img, 0, res * res * 3 * sizeof(unsigned char));
// Render the first pass of the bodies.
for (int i = 0; i < n; i++)
{
int x = bodies[i].s[0] / inv_scale + res / 2;
int y = bodies[i].s[1] / inv_scale + res / 2;
if (x >= 0 && y >= 0 && x < res && y < res)
{
img[y * stride_in_bytes + x * 3] = std::min(255.0f, img[y * stride_in_bytes + x * 3] + 4096 / inv_scale);
}
}
// Render the second pass of the bodies.
for (int i = 0; i < n; i++)
{
int x = bodies[i].s[0] / inv_scale + res / 2;
int y = bodies[i].s[1] / inv_scale + res / 2;
if (x >= 0 && y >= 0 && x < res && y < res)
{
int value = img[y * stride_in_bytes + x * 3];
img[y * stride_in_bytes + x * 3 + 0] = __thermal_data[value].r * 255;
img[y * stride_in_bytes + x * 3 + 1] = __thermal_data[value].g * 255;
img[y * stride_in_bytes + x * 3 + 2] = __thermal_data[value].b * 255;
}
}
// Save the image.
std::stringstream out_name_builder;
out_name_builder << "sketch_" << i << ".png";
stbi_write_png(out_name_builder.str().c_str(), res, res, 3, img, stride_in_bytes);
// Get the ending time.
clock_t frame_end = clock();
// Print the frame elapsed time.
std::cout << "Frame " << i << " sketched in " << float(frame_end - frame_start) / float(CLOCKS_PER_SEC) << " s" << std::endl;
}
return EXIT_SUCCESS;
}