nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "erebus.h" nuclear@0: #include "vmath/vector.h" nuclear@0: #include "image.h" nuclear@0: nuclear@0: using namespace std::chrono; nuclear@0: nuclear@0: struct Rect { nuclear@0: int x, y, width, height; nuclear@0: nuclear@0: bool operator ==(const Rect &r) { return memcmp(this, &r, sizeof r) == 0; } nuclear@0: bool operator !=(const Rect &r) { return memcmp(this, &r, sizeof r) != 0; } nuclear@0: }; nuclear@0: nuclear@0: #define INVALID_RECT Rect{0, 0, 0, 0} nuclear@0: nuclear@0: struct erebus { nuclear@0: Image fbimg; nuclear@0: Vector4 options[ERB_NUM_OPTIONS]; nuclear@0: nuclear@0: // render state nuclear@0: long cur_time; nuclear@0: int cur_pixel_x, cur_pixel_y; nuclear@0: Rect cur_rect; nuclear@0: }; nuclear@0: nuclear@0: static void render_pixel(struct erebus *ctx, int x, int y); nuclear@0: nuclear@0: static std::mt19937 rnd_gen; nuclear@0: nuclear@0: extern "C" { nuclear@0: nuclear@0: struct erebus *erb_init(void) nuclear@0: { nuclear@0: struct erebus *ctx; nuclear@0: try { nuclear@0: ctx = new struct erebus; nuclear@0: } nuclear@0: catch(...) { nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: ctx->cur_time = 0; nuclear@0: ctx->cur_rect = INVALID_RECT; nuclear@0: return ctx; nuclear@0: } nuclear@0: nuclear@0: void erb_destroy(struct erebus *ctx) nuclear@0: { nuclear@0: delete ctx; nuclear@0: } nuclear@0: nuclear@0: void erb_setopti(struct erebus *ctx, enum erb_option opt, int val) nuclear@0: { nuclear@0: ctx->options[opt].x; nuclear@0: } nuclear@0: void erb_setoptf(struct erebus *ctx, enum erb_option opt, float val) nuclear@0: { nuclear@0: ctx->options[opt].x = val; nuclear@0: } nuclear@0: void erb_setoptfv(struct erebus *ctx, enum erb_option opt, float *vec) nuclear@0: { nuclear@0: for(int i=0; i<4; i++) { nuclear@0: ctx->options[opt][i] = vec[i]; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: int erb_getopti(struct erebus *ctx, enum erb_option opt) nuclear@0: { nuclear@0: return ctx->options[opt].x; nuclear@0: } nuclear@0: float erb_getoptf(struct erebus *ctx, enum erb_option opt) nuclear@0: { nuclear@0: return ctx->options[opt].x; nuclear@0: } nuclear@0: float *erb_getoptfv(struct erebus *ctx, enum erb_option opt) nuclear@0: { nuclear@0: return &ctx->options[opt].x; nuclear@0: } nuclear@0: nuclear@0: float *erb_get_framebuffer(struct erebus *ctx) nuclear@0: { nuclear@0: return ctx->fbimg.get_pixels(); nuclear@0: } nuclear@0: nuclear@0: void erb_begin_frame(struct erebus *ctx, long ms) nuclear@0: { nuclear@0: ctx->cur_time = ms; nuclear@0: } nuclear@0: nuclear@0: int erb_render(struct erebus *ctx, long timeout) nuclear@0: { nuclear@0: return erb_render_rect(ctx, 0, 0, ctx->fbimg.get_width(), ctx->fbimg.get_height(), timeout); nuclear@0: } nuclear@0: nuclear@0: int erb_render_rect(struct erebus *ctx, int x, int y, int width, int height, long timeout) nuclear@0: { nuclear@0: if(!width || !height) return -1; nuclear@0: nuclear@0: Rect rect{x, y, width, height}; nuclear@0: if(ctx->cur_rect != rect) { nuclear@0: ctx->cur_rect = rect; nuclear@0: ctx->cur_pixel_x = x; nuclear@0: ctx->cur_pixel_y = y; nuclear@0: } nuclear@0: nuclear@0: if(timeout > 0) { nuclear@0: auto start_time = monotonic_clock::now(); nuclear@0: while(duration_cast(monotonic_clock::now() - start_time).count() < timeout) { nuclear@0: render_pixel(ctx, ctx->cur_pixel_x, ctx->cur_pixel_y); nuclear@0: nuclear@0: if(++ctx->cur_pixel_x >= ctx->cur_rect.width) { nuclear@0: if(++ctx->cur_pixel_y >= ctx->cur_rect.height) { nuclear@0: ctx->cur_rect = INVALID_RECT; nuclear@0: return 0; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: for(int i=0; iscene; nuclear@0: //ctx->scene = new Scene; nuclear@0: nuclear@0: return false; // TODO nuclear@0: } nuclear@0: nuclear@0: } // extern "C" nuclear@0: nuclear@0: float randf(float low, float high) nuclear@0: { nuclear@0: std::uniform_real_distribution unirnd(low, high); nuclear@0: return unirnd(rnd_gen); nuclear@0: } nuclear@0: nuclear@0: static void render_pixel(struct erebus *ctx, int x, int y) nuclear@0: { nuclear@0: float *pix = ctx->fbimg.get_pixels() + (y * ctx->fbimg.get_width() + x) * 4; nuclear@0: pix[0] = pix[1] = pix[2] = 0.0f; nuclear@0: pix[3] = 1.0f; nuclear@0: }