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@4
|
8 #include "scene.h"
|
nuclear@4
|
9 #include "geomobj.h"
|
nuclear@5
|
10 #include "rt.h"
|
nuclear@2
|
11
|
nuclear@2
|
12 using namespace std::chrono;
|
nuclear@2
|
13
|
nuclear@2
|
14 struct Rect {
|
nuclear@2
|
15 int x, y, width, height;
|
nuclear@2
|
16
|
nuclear@2
|
17 bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; }
|
nuclear@2
|
18 bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; }
|
nuclear@2
|
19 };
|
nuclear@2
|
20
|
nuclear@2
|
21 #define INVALID_RECT Rect{0, 0, 0, 0}
|
nuclear@2
|
22
|
nuclear@2
|
23 struct erebus {
|
nuclear@4
|
24 Scene *scn;
|
nuclear@4
|
25
|
nuclear@2
|
26 Image<float> fbimg;
|
nuclear@2
|
27 Vector4 options[ERB_NUM_OPTIONS];
|
nuclear@2
|
28
|
nuclear@2
|
29 // render state
|
nuclear@2
|
30 long cur_time;
|
nuclear@2
|
31 int cur_pixel_x, cur_pixel_y;
|
nuclear@2
|
32 Rect cur_rect;
|
nuclear@2
|
33 };
|
nuclear@2
|
34
|
nuclear@2
|
35 static void render_pixel(struct erebus *ctx, int x, int y);
|
nuclear@2
|
36
|
nuclear@2
|
37 static std::mt19937 rnd_gen;
|
nuclear@2
|
38
|
nuclear@2
|
39 extern "C" {
|
nuclear@2
|
40
|
nuclear@2
|
41 struct erebus *erb_init(void)
|
nuclear@2
|
42 {
|
nuclear@2
|
43 struct erebus *ctx;
|
nuclear@2
|
44 try {
|
nuclear@2
|
45 ctx = new struct erebus;
|
nuclear@2
|
46 }
|
nuclear@2
|
47 catch(...) {
|
nuclear@2
|
48 return 0;
|
nuclear@2
|
49 }
|
nuclear@2
|
50
|
nuclear@4
|
51 ctx->scn = 0;
|
nuclear@2
|
52 ctx->cur_time = 0;
|
nuclear@2
|
53 ctx->cur_rect = INVALID_RECT;
|
nuclear@2
|
54 return ctx;
|
nuclear@2
|
55 }
|
nuclear@2
|
56
|
nuclear@2
|
57 void erb_destroy(struct erebus *ctx)
|
nuclear@2
|
58 {
|
nuclear@2
|
59 delete ctx;
|
nuclear@2
|
60 }
|
nuclear@2
|
61
|
nuclear@2
|
62 void erb_setopti(struct erebus *ctx, enum erb_option opt, int val)
|
nuclear@2
|
63 {
|
nuclear@2
|
64 ctx->options[opt].x = val;
|
nuclear@2
|
65 }
|
nuclear@2
|
66 void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val)
|
nuclear@2
|
67 {
|
nuclear@2
|
68 ctx->options[opt].x = val;
|
nuclear@2
|
69 }
|
nuclear@2
|
70 void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec)
|
nuclear@2
|
71 {
|
nuclear@2
|
72 for(int i=0; i<4; i++) {
|
nuclear@2
|
73 ctx->options[opt][i] = vec[i];
|
nuclear@2
|
74 }
|
nuclear@2
|
75 }
|
nuclear@2
|
76
|
nuclear@2
|
77 int erb_getopti(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
78 {
|
nuclear@2
|
79 return ctx->options[opt].x;
|
nuclear@2
|
80 }
|
nuclear@2
|
81 float erb_getoptf(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
82 {
|
nuclear@2
|
83 return ctx->options[opt].x;
|
nuclear@2
|
84 }
|
nuclear@2
|
85 float *erb_getoptfv(struct erebus *ctx, enum erb_option opt)
|
nuclear@2
|
86 {
|
nuclear@2
|
87 return &ctx->options[opt].x;
|
nuclear@2
|
88 }
|
nuclear@2
|
89
|
nuclear@2
|
90 float *erb_get_framebuffer(struct erebus *ctx)
|
nuclear@2
|
91 {
|
nuclear@2
|
92 return ctx->fbimg.get_pixels();
|
nuclear@2
|
93 }
|
nuclear@2
|
94
|
nuclear@2
|
95 void erb_begin_frame(struct erebus *ctx, long ms)
|
nuclear@2
|
96 {
|
nuclear@2
|
97 ctx->cur_time = ms;
|
nuclear@4
|
98
|
nuclear@4
|
99 int xsz = ctx->options[ERB_OPT_WIDTH].x;
|
nuclear@4
|
100 int ysz = ctx->options[ERB_OPT_HEIGHT].x;
|
nuclear@4
|
101
|
nuclear@4
|
102 ctx->fbimg.create(xsz, ysz);
|
nuclear@2
|
103 }
|
nuclear@2
|
104
|
nuclear@2
|
105 int erb_render(struct erebus *ctx, long timeout)
|
nuclear@2
|
106 {
|
nuclear@2
|
107 return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout);
|
nuclear@2
|
108 }
|
nuclear@2
|
109
|
nuclear@2
|
110 int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout)
|
nuclear@2
|
111 {
|
nuclear@2
|
112 if(!width || !height) return -1;
|
nuclear@2
|
113
|
nuclear@2
|
114 Rect rect{x, y, width, height};
|
nuclear@2
|
115 if(ctx->cur_rect != rect) {
|
nuclear@2
|
116 ctx->cur_rect = rect;
|
nuclear@2
|
117 ctx->cur_pixel_x = x;
|
nuclear@2
|
118 ctx->cur_pixel_y = y;
|
nuclear@2
|
119 }
|
nuclear@2
|
120
|
nuclear@4
|
121 ctx->scn->update();
|
nuclear@4
|
122
|
nuclear@2
|
123 if(timeout > 0) {
|
nuclear@2
|
124 auto start_time = steady_clock::now();
|
nuclear@2
|
125 while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) {
|
nuclear@2
|
126 render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y);
|
nuclear@2
|
127
|
nuclear@2
|
128 if(++ctx->cur_pixel_x >= ctx->cur_rect.width) {
|
nuclear@2
|
129 if(++ctx->cur_pixel_y >= ctx->cur_rect.height) {
|
nuclear@2
|
130 ctx->cur_rect = INVALID_RECT;
|
nuclear@2
|
131 return 0;
|
nuclear@2
|
132 }
|
nuclear@2
|
133 }
|
nuclear@2
|
134 }
|
nuclear@2
|
135 return 1;
|
nuclear@2
|
136 }
|
nuclear@2
|
137
|
nuclear@2
|
138 for(int i=0; i<height; i++) {
|
nuclear@2
|
139 for(int j=0; j<width; j++) {
|
nuclear@2
|
140 render_pixel(ctx, j, i);
|
nuclear@2
|
141 }
|
nuclear@2
|
142 }
|
nuclear@2
|
143 return 0;
|
nuclear@2
|
144 }
|
nuclear@2
|
145
|
nuclear@2
|
146 int erb_get_progress(struct erebus *ctx)
|
nuclear@2
|
147 {
|
nuclear@2
|
148 return 0; // TODO
|
nuclear@2
|
149 }
|
nuclear@2
|
150
|
nuclear@2
|
151 int erb_load_scene(struct erebus *ctx, const char *fname)
|
nuclear@2
|
152 {
|
nuclear@4
|
153 delete ctx->scn;
|
nuclear@4
|
154 ctx->scn = new Scene;
|
nuclear@2
|
155
|
nuclear@4
|
156 // XXX for now just create a test scene here
|
nuclear@4
|
157 Sphere *sph = new Sphere;
|
nuclear@4
|
158 SceneNode *sph_node = new SceneNode(sph);
|
nuclear@4
|
159 ctx->scn->add_object(sph);
|
nuclear@4
|
160 ctx->scn->add_node(sph_node);
|
nuclear@4
|
161
|
nuclear@4
|
162 TargetCamera *cam = new TargetCamera(Vector3(0, 0, -10), Vector3(0, 0, 0));
|
nuclear@4
|
163 //ctx->scn->add_object(cam);
|
nuclear@4
|
164 ctx->scn->use_camera(cam);
|
nuclear@4
|
165
|
nuclear@4
|
166 return 0;
|
nuclear@2
|
167 }
|
nuclear@2
|
168
|
nuclear@2
|
169 } // extern "C"
|
nuclear@2
|
170
|
nuclear@2
|
171 float randf(float low, float high)
|
nuclear@2
|
172 {
|
nuclear@2
|
173 std::uniform_real_distribution<float> unirnd(low, high);
|
nuclear@2
|
174 return unirnd(rnd_gen);
|
nuclear@2
|
175 }
|
nuclear@2
|
176
|
nuclear@2
|
177 static void render_pixel(struct erebus *ctx, int x, int y)
|
nuclear@2
|
178 {
|
nuclear@5
|
179 Camera *cam = ctx->scn->get_active_camera();
|
nuclear@5
|
180 if(!cam) return;
|
nuclear@5
|
181
|
nuclear@5
|
182 int xsz = ctx->fbimg.get_width();
|
nuclear@5
|
183 int ysz = ctx->fbimg.get_height();
|
nuclear@5
|
184 float *pix = ctx->fbimg.get_pixels() + (y * xsz + x) * 4;
|
nuclear@5
|
185
|
nuclear@5
|
186 Ray ray = cam->get_primary_ray(x, y, xsz, ysz, 0);
|
nuclear@5
|
187 //Color c = ray_trace(ray, ctx->scn, 0);
|
nuclear@5
|
188 Color c = ray.dir.normalized() * 0.5 + Vector3(0.5, 0.5, 0.5);
|
nuclear@5
|
189 pix[0] = 1.0;//c.x;
|
nuclear@5
|
190 pix[1] = c.y;
|
nuclear@5
|
191 pix[2] = c.z;
|
nuclear@5
|
192 pix[3] = c.w;
|
nuclear@2
|
193 }
|