rev |
line source |
nuclear@2
|
1 #include <string.h>
|
nuclear@2
|
2 #include <limits.h>
|
nuclear@2
|
3 #include <chrono>
|
nuclear@2
|
4 #include <random>
|
nuclear@2
|
5 #include "erebus.h"
|
nuclear@2
|
6 #include "vmath/vector.h"
|
nuclear@2
|
7 #include "image.h"
|
nuclear@2
|
8
|
nuclear@2
|
9 using namespace std::chrono;
|
nuclear@2
|
10
|
nuclear@2
|
11 struct Rect {
|
nuclear@2
|
12 int x, y, width, height;
|
nuclear@2
|
13
|
nuclear@2
|
14 bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; }
|
nuclear@2
|
15 bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; }
|
nuclear@2
|
16 };
|
nuclear@2
|
17
|
nuclear@2
|
18 #define INVALID_RECT Rect{0, 0, 0, 0}
|
nuclear@2
|
19
|
nuclear@2
|
20 struct erebus {
|
nuclear@2
|
21 Image<float> fbimg;
|
nuclear@2
|
22 Vector4 options[ERB_NUM_OPTIONS];
|
nuclear@2
|
23
|
nuclear@2
|
24 // render state
|
nuclear@2
|
25 long cur_time;
|
nuclear@2
|
26 int cur_pixel_x, cur_pixel_y;
|
nuclear@2
|
27 Rect cur_rect;
|
nuclear@2
|
28 };
|
nuclear@2
|
29
|
nuclear@2
|
30 static void render_pixel(struct erebus *ctx, int x, int y);
|
nuclear@2
|
31
|
nuclear@2
|
32 static std::mt19937 rnd_gen;
|
nuclear@2
|
33
|
nuclear@2
|
34 extern "C" {
|
nuclear@2
|
35
|
nuclear@2
|
36 struct erebus *erb_init(void)
|
nuclear@2
|
37 {
|
nuclear@2
|
38 struct erebus *ctx;
|
nuclear@2
|
39 try {
|
nuclear@2
|
40 ctx = new struct erebus;
|
nuclear@2
|
41 }
|
nuclear@2
|
42 catch(...) {
|
nuclear@2
|
43 return 0;
|
nuclear@2
|
44 }
|
nuclear@2
|
45
|
nuclear@2
|
46 ctx->cur_time = 0;
|
nuclear@2
|
47 ctx->cur_rect = INVALID_RECT;
|
nuclear@2
|
48 return ctx;
|
nuclear@2
|
49 }
|
nuclear@2
|
50
|
nuclear@2
|
51 void erb_destroy(struct erebus *ctx)
|
nuclear@2
|
52 {
|
nuclear@2
|
53 delete ctx;
|
nuclear@2
|
54 }
|
nuclear@2
|
55
|
nuclear@2
|
56 void erb_setopti(struct erebus *ctx, enum erb_option opt, int val)
|
nuclear@2
|
57 {
|
nuclear@2
|
58 ctx->options[opt].x = val;
|
nuclear@2
|
59 }
|
nuclear@2
|
60 void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val)
|
nuclear@2
|
61 {
|
nuclear@2
|
62 ctx->options[opt].x = val;
|
nuclear@2
|
63 }
|
nuclear@2
|
64 void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec)
|
nuclear@2
|
65 {
|
nuclear@2
|
66 for(int i=0; i<4; i++) {
|
nuclear@2
|
67 ctx->options[opt][i] = vec[i];
|
nuclear@2
|
68 }
|
nuclear@2
|
69 }
|
nuclear@2
|
70
|
nuclear@2
|
71 int erb_getopti(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
72 {
|
nuclear@2
|
73 return ctx->options[opt].x;
|
nuclear@2
|
74 }
|
nuclear@2
|
75 float erb_getoptf(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
76 {
|
nuclear@2
|
77 return ctx->options[opt].x;
|
nuclear@2
|
78 }
|
nuclear@2
|
79 float *erb_getoptfv(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
80 {
|
nuclear@2
|
81 return &ctx->options[opt].x;
|
nuclear@2
|
82 }
|
nuclear@2
|
83
|
nuclear@2
|
84 float *erb_get_framebuffer(struct erebus *ctx)
|
nuclear@2
|
85 {
|
nuclear@2
|
86 return ctx->fbimg.get_pixels();
|
nuclear@2
|
87 }
|
nuclear@2
|
88
|
nuclear@2
|
89 void erb_begin_frame(struct erebus *ctx, long ms)
|
nuclear@2
|
90 {
|
nuclear@2
|
91 ctx->cur_time = ms;
|
nuclear@2
|
92 }
|
nuclear@2
|
93
|
nuclear@2
|
94 int erb_render(struct erebus *ctx, long timeout)
|
nuclear@2
|
95 {
|
nuclear@2
|
96 return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout);
|
nuclear@2
|
97 }
|
nuclear@2
|
98
|
nuclear@2
|
99 int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout)
|
nuclear@2
|
100 {
|
nuclear@2
|
101 if(!width || !height) return -1;
|
nuclear@2
|
102
|
nuclear@2
|
103 Rect rect{x, y, width, height};
|
nuclear@2
|
104 if(ctx->cur_rect != rect) {
|
nuclear@2
|
105 ctx->cur_rect = rect;
|
nuclear@2
|
106 ctx->cur_pixel_x = x;
|
nuclear@2
|
107 ctx->cur_pixel_y = y;
|
nuclear@2
|
108 }
|
nuclear@2
|
109
|
nuclear@2
|
110 if(timeout > 0) {
|
nuclear@2
|
111 auto start_time = steady_clock::now();
|
nuclear@2
|
112 while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) {
|
nuclear@2
|
113 render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y);
|
nuclear@2
|
114
|
nuclear@2
|
115 if(++ctx->cur_pixel_x >= ctx->cur_rect.width) {
|
nuclear@2
|
116 if(++ctx->cur_pixel_y >= ctx->cur_rect.height) {
|
nuclear@2
|
117 ctx->cur_rect = INVALID_RECT;
|
nuclear@2
|
118 return 0;
|
nuclear@2
|
119 }
|
nuclear@2
|
120 }
|
nuclear@2
|
121 }
|
nuclear@2
|
122 return 1;
|
nuclear@2
|
123 }
|
nuclear@2
|
124
|
nuclear@2
|
125 for(int i=0; i<height; i++) {
|
nuclear@2
|
126 for(int j=0; j<width; j++) {
|
nuclear@2
|
127 render_pixel(ctx, j, i);
|
nuclear@2
|
128 }
|
nuclear@2
|
129 }
|
nuclear@2
|
130 return 0;
|
nuclear@2
|
131 }
|
nuclear@2
|
132
|
nuclear@2
|
133 int erb_get_progress(struct erebus *ctx)
|
nuclear@2
|
134 {
|
nuclear@2
|
135 return 0; // TODO
|
nuclear@2
|
136 }
|
nuclear@2
|
137
|
nuclear@2
|
138 int erb_load_scene(struct erebus *ctx, const char *fname)
|
nuclear@2
|
139 {
|
nuclear@2
|
140 //delete ctx->scene;
|
nuclear@2
|
141 //ctx->scene = new Scene;
|
nuclear@2
|
142
|
nuclear@2
|
143 return false; // TODO
|
nuclear@2
|
144 }
|
nuclear@2
|
145
|
nuclear@2
|
146 } // extern "C"
|
nuclear@2
|
147
|
nuclear@2
|
148 float randf(float low, float high)
|
nuclear@2
|
149 {
|
nuclear@2
|
150 std::uniform_real_distribution<float> unirnd(low, high);
|
nuclear@2
|
151 return unirnd(rnd_gen);
|
nuclear@2
|
152 }
|
nuclear@2
|
153
|
nuclear@2
|
154 static void render_pixel(struct erebus *ctx, int x, int y)
|
nuclear@2
|
155 {
|
nuclear@2
|
156 float *pix = ctx->fbimg.get_pixels() + (y * ctx->fbimg.get_width() + x) * 4;
|
nuclear@2
|
157 pix[0] = pix[1] = pix[2] = 0.0f;
|
nuclear@2
|
158 pix[3] = 1.0f;
|
nuclear@2
|
159 }
|