# HG changeset patch # User John Tsiombikas # Date 1402392536 -10800 # Node ID 2e817711d0f6260f31c9408316669bb941b1bbb2 # Parent 9d6368850fe15e1a6539684a374c06e88057eaa4 console: proper input line windowing and clipping diff -r 9d6368850fe1 -r 2e817711d0f6 liberebus/src/geomobj.cc --- a/liberebus/src/geomobj.cc Tue Jun 10 10:53:19 2014 +0300 +++ b/liberebus/src/geomobj.cc Tue Jun 10 12:28:56 2014 +0300 @@ -1,6 +1,8 @@ #include #include +#include #include "geomobj.h" +#include "erebus_impl.h" static LambertRefl lambert; @@ -19,6 +21,11 @@ return false; } +Vector3 GeomObject::gen_surface_point() const +{ + return Vector3(0, 0, 0); +} + Vector3 GeomObject::calc_normal(const RayHit &hit) const { // when you look at singularities, the singularities always look back at you :) @@ -64,6 +71,11 @@ return true; } +Vector3 Sphere::gen_surface_point() const +{ + return sphrand(1.0); +} + Vector3 Sphere::calc_normal(const RayHit &hit) const { Vector3 pt = hit.local_ray.origin + hit.local_ray.dir * hit.dist; @@ -143,7 +155,27 @@ return true; } return false; +} +#define SIGN(x) (x >= 0.0 ? 1.0 : -1.0) + +Vector3 Box::gen_surface_point() const +{ + Vector3 rnd{randf(-1, 1), randf(-1, 1), randf(-1, 1)}; + float absrnd[3]; + + absrnd[0] = fabs(rnd.x); + absrnd[1] = fabs(rnd.y); + absrnd[2] = fabs(rnd.z); + + int major = 0; + for(int i=1; i<3; i++) { + if(absrnd[i] > absrnd[major]) { + major = i; + } + } + rnd[major] = SIGN(rnd[major]); + return rnd; } #define BOX_EXT 0.499999 @@ -176,6 +208,15 @@ return false; } +Vector3 Triangle::gen_surface_point() const +{ + float bu = randf(); + float bv = randf(); + float bw = 1.0 - (bu + bv); + + return v[0] * bu + v[1] * bv + v[2] * bw; +} + // --- class Mesh --- bool Mesh::intersect(const Ray &ray, RayHit *hit) const @@ -200,3 +241,9 @@ } return false; } + +Vector3 Mesh::gen_surface_point() const +{ + // this needs some precalculation... + return Vector3(0, 0, 0); // TODO +} diff -r 9d6368850fe1 -r 2e817711d0f6 liberebus/src/geomobj.h --- a/liberebus/src/geomobj.h Tue Jun 10 10:53:19 2014 +0300 +++ b/liberebus/src/geomobj.h Tue Jun 10 12:28:56 2014 +0300 @@ -17,6 +17,8 @@ bool intersect(const Ray &ray, RayHit *hit = 0) const override; + virtual Vector3 gen_surface_point() const; + virtual Vector3 calc_normal(const RayHit &hit) const; virtual Vector3 calc_tangent(const RayHit &hit) const; virtual Vector2 calc_texcoords(const RayHit &hit) const; @@ -26,6 +28,8 @@ public: bool intersect(const Ray &ray, RayHit *hit = 0) const override; + Vector3 gen_surface_point() const override; + Vector3 calc_normal(const RayHit &hit) const override; Vector3 calc_tangent(const RayHit &hit) const override; Vector2 calc_texcoords(const RayHit &hit) const override; @@ -35,6 +39,8 @@ public: bool intersect(const Ray &ray, RayHit *hit = 0) const override; + Vector3 gen_surface_point() const override; + Vector3 calc_normal(const RayHit &hit) const override; Vector3 calc_tangent(const RayHit &hit) const override; Vector2 calc_texcoords(const RayHit &hit) const override; @@ -48,6 +54,8 @@ Vector2 vtex[3]; bool intersect(const Ray &ray, RayHit *hit = 0) const override; + + Vector3 gen_surface_point() const override; }; class Mesh : public GeomObject { @@ -62,6 +70,8 @@ void end(); bool intersect(const Ray &ray, RayHit *hit = 0) const override; + + Vector3 gen_surface_point() const override; }; #endif // GEOMOBJ_H_ diff -r 9d6368850fe1 -r 2e817711d0f6 liberebus/src/scene.h --- a/liberebus/src/scene.h Tue Jun 10 10:53:19 2014 +0300 +++ b/liberebus/src/scene.h Tue Jun 10 12:28:56 2014 +0300 @@ -3,6 +3,7 @@ #include #include +#include #include "snode.h" #include "camera.h" #include "color.h" @@ -15,6 +16,11 @@ Environment(); }; +struct ObjectInstance { + Object *obj; + SceneNode *node; +}; + class Scene { private: Environment env; diff -r 9d6368850fe1 -r 2e817711d0f6 src/console.cc --- a/src/console.cc Tue Jun 10 10:53:19 2014 +0300 +++ b/src/console.cc Tue Jun 10 12:28:56 2014 +0300 @@ -8,6 +8,7 @@ #include "console.h" Console::Console() + : prompt("> ") { visible = false; nlines = 16; @@ -23,6 +24,28 @@ font_size = 0; cursor = 0; + input_win = 0; +} + +void Console::set_cursor(int x) +{ + if(x < 0 || x > (int)input.size()) { + return; + } + cursor = x; + + int max_chars = ncolumns - (int)prompt.size() - 1; + + if(cursor < input_win) { + input_win = cursor; + } else if(cursor > input_win + max_chars) { + input_win = std::max(cursor - max_chars, 0); + } +} + +int Console::get_cursor() const +{ + return cursor; } void Console::set_font(dtx_font *font, int sz) @@ -107,20 +130,19 @@ switch(c) { case '\n': case '\r': - if(!input.empty() && cmd_handler) { - cmd_handler(input.c_str()); - } - if(echo) { puts(input.c_str()); putchar('\n'); } + if(!input.empty() && cmd_handler) { + cmd_handler(input.c_str()); + } hist.push_back(std::move(input)); // move the input string into the history buffer if((int)hist.size() > max_hist_lines) { hist.pop_front(); } - cursor = 0; + set_cursor(0); must_redraw = true; break; @@ -132,11 +154,11 @@ if(!input.empty()) { if(cursor == (int)input.size()) { input.pop_back(); - --cursor; + set_cursor(get_cursor() - 1); must_redraw = true; } else if(cursor > 0) { input.erase(cursor - 1, 1); - --cursor; + set_cursor(get_cursor() - 1); must_redraw = true; } } @@ -144,25 +166,25 @@ case KEY_LEFT: if(cursor > 0) { - --cursor; + set_cursor(get_cursor() - 1); must_redraw = true; } break; case KEY_RIGHT: if(cursor < (int)input.size()) { - ++cursor; + set_cursor(get_cursor() + 1); must_redraw = true; } break; case KEY_HOME: - cursor = 0; + set_cursor(0); must_redraw = true; break; case KEY_END: - cursor = input.size(); + set_cursor(input.size()); must_redraw = true; break; @@ -178,7 +200,7 @@ } else { input.insert(cursor, 1, c); } - ++cursor; + set_cursor(get_cursor() + 1); must_redraw = true; } } @@ -202,7 +224,7 @@ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - glTranslatef(0, vp[3] - vp[1], 0); + glTranslatef(0, vp[3], 0); std::string buflines; @@ -215,18 +237,22 @@ const std::string &line = *it++; buflines += line + std::string("\n"); - max_width = std::max(max_width, dtx_string_width(line.c_str())); + //max_width = std::max(max_width, dtx_string_width(line.c_str())); } // draw the output box float line_height = dtx_line_height(); float outbox_height = nlines * line_height; + float console_height = outbox_height + line_height * 1.5; glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_SCISSOR_TEST); + glScissor(0, vp[3] - console_height, max_width, console_height); + glBegin(GL_QUADS); glColor4f(0.1, 0.2, 0.5, 0.7); glVertex2f(0, -outbox_height); @@ -235,8 +261,8 @@ glVertex2f(0, 0); glColor4f(0.5, 0.2, 0.1, 0.7); - glVertex2f(0, -(outbox_height + line_height * 1.5)); - glVertex2f(max_width, -(outbox_height + line_height * 1.5)); + glVertex2f(0, -console_height); + glVertex2f(max_width, -console_height); glVertex2f(max_width, -outbox_height); glVertex2f(0, -outbox_height); glEnd(); @@ -251,11 +277,11 @@ // draw the input line glTranslatef(0, -outbox_height - line_height, 0); - std::string inpline = std::string("> ") + input; + std::string inpline = prompt + input.substr(input_win); dtx_string(inpline.c_str()); glDisable(GL_TEXTURE_2D); - float cursor_x = dtx_char_pos(inpline.c_str(), cursor + 2); + float cursor_x = dtx_char_pos(inpline.c_str(), cursor - input_win + prompt.size()); glBegin(GL_QUADS); glColor4f(1, 1, 1, 0.7); glVertex2f(cursor_x, 0); diff -r 9d6368850fe1 -r 2e817711d0f6 src/console.h --- a/src/console.h Tue Jun 10 10:53:19 2014 +0300 +++ b/src/console.h Tue Jun 10 12:28:56 2014 +0300 @@ -17,8 +17,10 @@ int inpq_front, inpq_back; int keybuf[INPUTQ_SIZE]; + std::string prompt; std::string input; // current input line int cursor; + int input_win; // first character to show in the input "window" // input history int max_hist_lines; @@ -34,6 +36,9 @@ int font_size; dtx_font *font; + void set_cursor(int x); + int get_cursor() const; + public: enum { KEY_LEFT = 256, diff -r 9d6368850fe1 -r 2e817711d0f6 src/main.cc --- a/src/main.cc Tue Jun 10 10:53:19 2014 +0300 +++ b/src/main.cc Tue Jun 10 12:28:56 2014 +0300 @@ -148,8 +148,7 @@ static void begin_frame(long tm) { - printf("rendering frame (t=%ld) ... ", tm); - fflush(stdout); + printf("rendering frame (t=%ld) ...\n", tm); render_pending = true; glutIdleFunc(idle); @@ -167,7 +166,7 @@ long msec, sec, min, hr, days; msec = full_msec; - printf("done in "); + con.printf("done in "); if((sec = msec / 1000) > 0) { msec %= 1000; if((min = sec / 60) > 0) { @@ -176,15 +175,15 @@ min %= 60; if((days = hr / 24) > 0) { hr %= 24; - printf("%ld days ", days); + con.printf("%ld days ", days); } - printf("%ld hours ", hr); + con.printf("%ld hours ", hr); } - printf("%ld min ", min); + con.printf("%ld min ", min); } - printf("%ld sec ", sec); + con.printf("%ld sec ", sec); } - printf("%ld ms (%ld total msec)\n", msec, full_msec); + con.printf("%ld ms (%ld total msec)\n", msec, full_msec); render_pending = false; glutIdleFunc(0); @@ -194,44 +193,51 @@ { static unsigned char *defpix; + if(render_pending) { + erb_end_frame(erb); + } + win_width = xsz; win_height = ysz; width = xsz / opt_imgscale; height = ysz / opt_imgscale; - if(width <= rtex_width && height <= rtex_height) { - return; - } - rtex_width = next_pow2(width); - rtex_height = next_pow2(height); + if(width > rtex_width || height > rtex_height) { + rtex_width = next_pow2(width); + rtex_height = next_pow2(height); - printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height); + printf("resizing framebuffer texture: %dx%d\n", rtex_width, rtex_height); - if(!rtex) { - glGenTextures(1, &rtex); + if(!rtex) { + glGenTextures(1, &rtex); + } + + delete [] defpix; + defpix = new unsigned char[rtex_width * rtex_height * 4]; + unsigned char *ptr = defpix; + for(int i=0; i> 4) & 1) == ((j >> 4) & 1); + + int val = chess ? 64 : 48; + + *ptr++ = val; + *ptr++ = val; + *ptr++ = val; + *ptr++ = 255; + } + } + + glBindTexture(GL_TEXTURE_2D, rtex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix); } - delete [] defpix; - defpix = new unsigned char[rtex_width * rtex_height * 4]; - unsigned char *ptr = defpix; - for(int i=0; i> 4) & 1) == ((j >> 4) & 1); - - int val = chess ? 64 : 48; - - *ptr++ = val; - *ptr++ = val; - *ptr++ = val; - *ptr++ = 255; - } + if(render_pending) { + begin_frame(0); } - - glBindTexture(GL_TEXTURE_2D, rtex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, rtex_width, rtex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, defpix); } static void update_rect(int x, int y, int xsz, int ysz, float *pixels) @@ -613,6 +619,14 @@ } begin_frame(tm); + } else if(strcmp(args[0], "samples") == 0) { + if(args[1] && (opt_samples = atoi(args[1]))) { + erb_setopti(erb, ERB_OPT_MAX_SAMPLES, opt_samples); + con.printf("max samples is now %d\n", opt_samples); + } else { + con.printf("invalid samples command: %s\n", line); + } + } else if(strcmp(args[0], "load") == 0) { for(int i=1; i sets the maximum number of samples per pixel\n"); + con.printf("iter sets the maximum number of ray bounces\n"); + con.printf("load loads a scene file\n"); + con.printf("add adds another object to the scene. For valid object commands see test/scene\n"); + } else { con.printf("unrecognized command: %s\n", args[0]); }