erebus

view liberebus/src/erebus.cc @ 4:93894c232d65

more changes across the board
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 29 Apr 2014 07:38:40 +0300
parents 474a0244f57d
children 9621beb22694
line source
1 #include <string.h>
2 #include <limits.h>
3 #include <chrono>
4 #include <random>
5 #include "erebus.h"
6 #include "vmath/vector.h"
7 #include "image.h"
8 #include "scene.h"
9 #include "geomobj.h"
11 using namespace std::chrono;
13 struct Rect {
14 int x, y, width, height;
16 bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; }
17 bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; }
18 };
20 #define INVALID_RECT Rect{0, 0, 0, 0}
22 struct erebus {
23 Scene *scn;
25 Image<float> fbimg;
26 Vector4 options[ERB_NUM_OPTIONS];
28 // render state
29 long cur_time;
30 int cur_pixel_x, cur_pixel_y;
31 Rect cur_rect;
32 };
34 static void render_pixel(struct erebus *ctx, int x, int y);
36 static std::mt19937 rnd_gen;
38 extern "C" {
40 struct erebus *erb_init(void)
41 {
42 struct erebus *ctx;
43 try {
44 ctx = new struct erebus;
45 }
46 catch(...) {
47 return 0;
48 }
50 ctx->scn = 0;
51 ctx->cur_time = 0;
52 ctx->cur_rect = INVALID_RECT;
53 return ctx;
54 }
56 void erb_destroy(struct erebus *ctx)
57 {
58 delete ctx;
59 }
61 void erb_setopti(struct erebus *ctx, enum erb_option opt, int val)
62 {
63 ctx->options[opt].x = val;
64 }
65 void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val)
66 {
67 ctx->options[opt].x = val;
68 }
69 void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec)
70 {
71 for(int i=0; i<4; i++) {
72 ctx->options[opt][i] = vec[i];
73 }
74 }
76 int erb_getopti(struct erebus *ctx, enum erb_option opt)
77 {
78 return ctx->options[opt].x;
79 }
80 float erb_getoptf(struct erebus *ctx, enum erb_option opt)
81 {
82 return ctx->options[opt].x;
83 }
84 float *erb_getoptfv(struct erebus *ctx, enum erb_option opt)
85 {
86 return &ctx->options[opt].x;
87 }
89 float *erb_get_framebuffer(struct erebus *ctx)
90 {
91 return ctx->fbimg.get_pixels();
92 }
94 void erb_begin_frame(struct erebus *ctx, long ms)
95 {
96 ctx->cur_time = ms;
98 int xsz = ctx->options[ERB_OPT_WIDTH].x;
99 int ysz = ctx->options[ERB_OPT_HEIGHT].x;
101 ctx->fbimg.create(xsz, ysz);
102 }
104 int erb_render(struct erebus *ctx, long timeout)
105 {
106 return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout);
107 }
109 int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout)
110 {
111 if(!width || !height) return -1;
113 Rect rect{x, y, width, height};
114 if(ctx->cur_rect != rect) {
115 ctx->cur_rect = rect;
116 ctx->cur_pixel_x = x;
117 ctx->cur_pixel_y = y;
118 }
120 ctx->scn->update();
122 if(timeout > 0) {
123 auto start_time = steady_clock::now();
124 while(duration_cast<milliseconds>(steady_clock::now() - start_time).count() < timeout) {
125 render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y);
127 if(++ctx->cur_pixel_x >= ctx->cur_rect.width) {
128 if(++ctx->cur_pixel_y >= ctx->cur_rect.height) {
129 ctx->cur_rect = INVALID_RECT;
130 return 0;
131 }
132 }
133 }
134 return 1;
135 }
137 for(int i=0; i<height; i++) {
138 for(int j=0; j<width; j++) {
139 render_pixel(ctx, j, i);
140 }
141 }
142 return 0;
143 }
145 int erb_get_progress(struct erebus *ctx)
146 {
147 return 0; // TODO
148 }
150 int erb_load_scene(struct erebus *ctx, const char *fname)
151 {
152 delete ctx->scn;
153 ctx->scn = new Scene;
155 // XXX for now just create a test scene here
156 Sphere *sph = new Sphere;
157 SceneNode *sph_node = new SceneNode(sph);
158 ctx->scn->add_object(sph);
159 ctx->scn->add_node(sph_node);
161 TargetCamera *cam = new TargetCamera(Vector3(0, 0, -10), Vector3(0, 0, 0));
162 //ctx->scn->add_object(cam);
163 ctx->scn->use_camera(cam);
165 return 0;
166 }
168 } // extern "C"
170 float randf(float low, float high)
171 {
172 std::uniform_real_distribution<float> unirnd(low, high);
173 return unirnd(rnd_gen);
174 }
176 static void render_pixel(struct erebus *ctx, int x, int y)
177 {
178 float *pix = ctx->fbimg.get_pixels() + (y * ctx->fbimg.get_width() + x) * 4;
179 pix[0] = pix[1] = pix[2] = 0.0f;
180 pix[3] = 1.0f;
181 }