erebus

annotate liberebus/src/erebus.cc @ 5:9621beb22694

huh?
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 24 May 2014 02:20:44 +0300
parents 93894c232d65
children e2d9bf168a41
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 }