# HG changeset patch # User John Tsiombikas # Date 1288072149 -10800 # Node ID 87b6a11c920b215768949c5e49191b45d560292b # Parent 03022062c46417782a6e3f24296624ec53a3f754 added gui stuff diff -r 03022062c464 -r 87b6a11c920b src/gui.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui.cc Tue Oct 26 08:49:09 2010 +0300 @@ -0,0 +1,295 @@ +#include + +#ifndef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include "gui.h" +#include "utktext.h" +#include "sdr.h" + +#define TEXT_PT_SIZE 18 + +void huecb(utk::Event *ev, void *cls); +static void cbfunc(utk::Event *ev, void *cls); + +void utk_color(int r, int g, int b, int a); +void utk_clip(int x1, int y1, int x2, int y2); +void utk_image(int x, int y, const void *pix, int xsz, int ysz); + +void utk_rect(int x1, int y1, int x2, int y2); +void utk_line(int x1, int y1, int x2, int y2, int width); + +void utk_text(int x, int y, const char *txt, int sz); +int utk_text_spacing(); +int utk_text_width(const char *txt, int sz); + + +int xsz, ysz; +static utk::Container *utkroot; +static float max_descent; +utk::Window *win_seed, *win_material; + + +extern unsigned int sdr; +extern Vector4 seed; +extern int iter; +extern float err_thres; +extern float reflectivity; +extern Vector3 color; + +int gui_init(int width, int height) +{ + xsz = width; + ysz = height; + + if(!CreateFont("georgia.ttf", TEXT_PT_SIZE)) { + fprintf(stderr, "failed to load font\n"); + return -1; + } + max_descent = GetMaxDescent(); + + utk::gfx::color = utk_color; + utk::gfx::clip = utk_clip; + utk::gfx::image = utk_image; + utk::gfx::rect = utk_rect; + utk::gfx::line = utk_line; + utk::gfx::text = utk_text; + utk::gfx::text_spacing = utk_text_spacing; + utk::gfx::text_width = utk_text_width; + + utkroot = utk::init(xsz, ysz); + + win_seed = utk::create_window(utkroot, 5, 25, 220, 175, "julia parameters"); + win_seed->set_alpha(128); + win_seed->show(); + + utk::VBox *vbox = utk::create_vbox(win_seed); + utk::HBox *hbox; + + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "seed x"); + utk::create_slider(hbox, -1.0, 1.0, cbfunc, (void*)0)->set_value(seed.x); + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "seed y"); + utk::create_slider(hbox, -1.0, 1.0, cbfunc, (void*)1)->set_value(seed.y); + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "seed z"); + utk::create_slider(hbox, -1.0, 1.0, cbfunc, (void*)2)->set_value(seed.z); + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "seed w"); + utk::create_slider(hbox, -1.0, 1.0, cbfunc, (void*)3)->set_value(seed.w); + + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "iterations"); + utk::Slider *iter_slider = utk::create_slider(hbox, 0, 32, cbfunc, (void*)5); + iter_slider->set_value(iter); + iter_slider->set_vis_decimal(0); + + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "max error"); + utk::Slider *err_slider = utk::create_slider(hbox, 0, 0.075, cbfunc, (void*)6); + err_slider->set_value(err_thres); + err_slider->set_vis_decimal(4); + + win_material = utk::create_window(utkroot, 250, 25, 220, 210, "material"); + win_material->set_alpha(128); + win_material->show(); + ((utk::WinFrame*)win_material->get_parent())->set_shade(true); + + vbox = utk::create_vbox(win_material); + + utk::ColorBox *colbox = new utk::ColorBox; + vbox->add_child(colbox); + utk::HueBox *huebox = new utk::HueBox; + vbox->add_child(huebox); + huebox->set_callback(utk::EVENT_MODIFY, huecb, colbox); + + float hue, sat, val; + utk::rgb_to_hsv(color.x, color.y, color.z, &hue, &sat, &val); + colbox->set_color_hsv(hue, sat, val); + huebox->set_h(hue); + + hbox = utk::create_hbox(vbox); + utk::create_label(hbox, "reflectivity"); + utk::create_slider(hbox, 0, 1.0, cbfunc, (void*)4)->set_value(reflectivity); + + return 0; +} + +void gui_draw() +{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + utk::draw(); + + glPopAttrib(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +void gui_set_visible(bool vis) +{ + if(vis) { + win_seed->show(); + win_material->show(); + } else { + win_seed->hide(); + win_material->hide(); + } +} + +void huecb(utk::Event *ev, void *cls) +{ + utk::HueBox *huebox = (utk::HueBox*)ev->widget; + utk::ColorBox *colbox = (utk::ColorBox*)cls; + + colbox->set_h(huebox->get_h()); +} + +void cbfunc(utk::Event *ev, void *cls) +{ + int id = (int)(intptr_t)cls; + + switch(id) { + case 0: + case 1: + case 2: + case 3: + { + utk::Slider *slider = (utk::Slider*)ev->widget; + + seed[id] = slider->get_value(); + set_uniform_float4(sdr, "seed", seed.x, seed.y, seed.z, seed.w); + glutPostRedisplay(); + } + break; + + case 4: + { + utk::Slider *slider = (utk::Slider*)ev->widget; + + reflectivity = slider->get_value(); + set_uniform_float(sdr, "reflectivity", reflectivity); + glutPostRedisplay(); + } + break; + + case 5: + { + utk::Slider *slider = (utk::Slider*)ev->widget; + + iter = (int)slider->get_value(); + set_uniform_int(sdr, "iter", iter); + glutPostRedisplay(); + } + break; + + case 6: + { + utk::Slider *slider = (utk::Slider*)ev->widget; + + err_thres = slider->get_value(); + set_uniform_float(sdr, "err_thres", err_thres); + glutPostRedisplay(); + } + break; + + default: + fprintf(stderr, "unhandled callback (id: %d)\n", id); + break; + } +} + + +#define CONVX(x) (2.0 * (float)(x) / (float)xsz - 1.0) +#define CONVY(y) (1.0 - 2.0 * (float)(y) / (float)ysz) + +void utk_color(int r, int g, int b, int a) +{ + glColor4ub(r, g, b, a); + SetTextColor(Color(r / 255.0, g / 255.0, b / 255.0, a / 255.0)); +} + +void utk_clip(int x1, int y1, int x2, int y2) +{ + if(x1 == x2 && y1 == y2 && x1 == y1 && x1 == 0) { + glDisable(GL_SCISSOR_TEST); + } else { + glEnable(GL_SCISSOR_TEST); + } + glScissor(x1, ysz - y2, x2 - x1, y2 - y1); +} + +void utk_image(int x, int y, const void *pix, int w, int h) +{ + glPixelZoom(1, -1); + glRasterPos2f(CONVX(x), CONVY(y)); + glDrawPixels(w, h, GL_BGRA, GL_UNSIGNED_BYTE, pix); +} + +void utk_rect(int x1, int y1, int x2, int y2) +{ + glRectf(CONVX(x1), CONVY(y1), CONVX(x2), CONVY(y2)); +} + +void utk_line(int x1, int y1, int x2, int y2, int width) +{ + glPushAttrib(GL_LINE_BIT); + + glLineWidth((float)width); + glBegin(GL_LINES); + glVertex2f(CONVX(x1), CONVY(y1)); + glVertex2f(CONVX(x2), CONVY(y2)); + glEnd(); + + glPopAttrib(); +} + +void utk_text(int x, int y, const char *txt, int sz) +{ + float fx = (float)x / (float)xsz; + float fy = (float)y / (float)ysz; + + SetTextPos(Vector2(fx, fy - max_descent)); + //SetTextPos(Vector2(0.25, 0.25)); + SetTextSize((float)sz / (float)TEXT_PT_SIZE); + PrintString(txt); +} + +int utk_text_spacing() +{ + return (int)(GetLineAdvance() * (float)ysz); +} + +int utk_text_width(const char *txt, int sz) +{ + float prev_sz = GetTextSize(); + SetTextSize((float)sz / (float)TEXT_PT_SIZE); + + int width = (int)(GetTextWidth(txt) * (float)xsz); + + SetTextSize(prev_sz); + return width; +} + diff -r 03022062c464 -r 87b6a11c920b src/gui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui.h Tue Oct 26 08:49:09 2010 +0300 @@ -0,0 +1,10 @@ +#ifndef GUI_H_ +#define GUI_H_ + +#include + +int gui_init(int xsz, int ysz); +void gui_draw(); +void gui_set_visible(bool vis); + +#endif diff -r 03022062c464 -r 87b6a11c920b src/utktext.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/utktext.cc Tue Oct 26 08:49:09 2010 +0300 @@ -0,0 +1,444 @@ +#include +#include +#define GL_GLEXT_PROTOTYPES +#if defined(__APPLE__) && defined(__MACH__) +#include +#else +#include +#endif +#include +#include FT_FREETYPE_H +#include +#include "utktext.h" +#include "utk_common.h" + +#ifndef GL_BGRA +#define GL_BGRA 0x80E1 +#endif + +#ifndef GL_ABGR +#define GL_ABGR 0x8000 +#endif + +#ifdef UTK_BIG_ENDIAN +#define PIXFMT GL_ABGR +#else +#define PIXFMT GL_BGRA +#endif + +#define MAX_CHARS 128 +#define MAX_IMG_WIDTH 1024 +#define SIZE_PIXELS(x) ((x) / 64) + +struct Font { + unsigned int tex_id; + float scale; // this compensates if a higher res font is loaded in its stead, with a new CreateFont + float line_adv; // vertical advance to go to the next line + struct { + Vector2 pos, size; // glyph position (from origin) and size in normalized coords [0, 1] + float advance; // advance in normalized coords + Vector2 tc_pos, tc_sz; // tex coord box pos/size + } glyphs[MAX_CHARS]; +}; + +static void BlitFontGlyph(Font *fnt, int x, int y, FT_GlyphSlot glyph, unsigned int *img, int xsz, int ysz); +static void CleanUp(); + +static FT_Library ft; +static Vector2 text_pos; +static float text_size = 1.0; +static Color text_color; +static Font *act_fnt; + +#if !defined(GLIBC) && !defined(__GLIBC__) +float log2(float x) { + float res = 0.0; + while(x > 1.0) { + x /= 2.0; + res += 1.0; + } + return res; +} +#endif // _MSC_VER + + +static inline int NextPow2(int x) +{ + float lg2 = log2((float)x); + return (int)pow(2.0f, (int)ceil(lg2)); +} + + +unsigned int CreateFont(const char *fname, int font_size) +{ + if(!ft) { + if(FT_Init_FreeType(&ft) != 0) { + fprintf(stderr, "failed to initialize freetype\n"); + return 0; + } + atexit(CleanUp); + } + + FT_Face face; + if(FT_New_Face(ft, fname, 0, &face) != 0) { + fprintf(stderr, "failed to load font: %s\n", fname); + return 0; + } + + FT_Set_Pixel_Sizes(face, 0, font_size); + + Font *fnt = new Font; + int max_width = MAX_CHARS * SIZE_PIXELS(face->bbox.xMax - face->bbox.xMin); + int foo_xsz = MAX_IMG_WIDTH; + int foo_ysz = SIZE_PIXELS(face->bbox.yMax - face->bbox.yMin) * max_width / foo_xsz; + + int tex_xsz = NextPow2(foo_xsz); + int tex_ysz = NextPow2(foo_ysz); + + unsigned int *img; + img = new unsigned int[tex_xsz * tex_ysz]; + memset(img, 0, tex_xsz * tex_ysz * sizeof *img); + + extern int xsz, ysz; + int vport_xsz = xsz, vport_ysz = ysz; + + int max_glyph_y = 0; + int max_glyph_x = 0; + for(int i=0; iglyph->metrics.width); + int height = SIZE_PIXELS(face->glyph->metrics.height); + + if(height > max_glyph_y) { + max_glyph_y = height; + } + + if(width > max_glyph_x) { + max_glyph_x = width; + } + } + + int gx = 0, gy = 0; + for(int i=0; iglyph; + + int gwidth = SIZE_PIXELS(g->metrics.width); + int gheight = SIZE_PIXELS(g->metrics.height); + + if(gx > MAX_IMG_WIDTH - gwidth) { + gx = 0; + gy += max_glyph_y; + } + + BlitFontGlyph(fnt, gx, gy, g, img, tex_xsz, tex_ysz); + fnt->scale = 1.0; + fnt->line_adv = (float)SIZE_PIXELS(g->metrics.vertAdvance) / (float)vport_ysz; + fnt->glyphs[i].tc_pos.x = (float)gx / (float)tex_xsz; + fnt->glyphs[i].tc_pos.y = (float)gy / (float)tex_ysz; + fnt->glyphs[i].tc_sz.x = (float)gwidth / (float)tex_xsz; + fnt->glyphs[i].tc_sz.y = (float)gheight / (float)tex_ysz; + fnt->glyphs[i].size.x = (float)gwidth / (float)vport_xsz; + fnt->glyphs[i].size.y = (float)gheight / (float)vport_ysz; + fnt->glyphs[i].pos.x = (float)SIZE_PIXELS(g->metrics.horiBearingX) / (float)vport_xsz; + fnt->glyphs[i].pos.y = -(float)SIZE_PIXELS(g->metrics.horiBearingY) / (float)vport_ysz; + fnt->glyphs[i].advance = (float)SIZE_PIXELS(g->metrics.horiAdvance) / (float)vport_xsz; + + gx += gwidth; + } + + FT_Done_Face(face); + + glGenTextures(1, &fnt->tex_id); + glBindTexture(GL_TEXTURE_2D, fnt->tex_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + 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, 4, tex_xsz, tex_ysz, 0, PIXFMT, GL_UNSIGNED_BYTE, img); + +#ifdef DUMP_FONT_IMG + FILE *fp; + unsigned int *ptr = img; + + if((fp = fopen("fnt.ppm", "wb"))) { + fprintf(fp, "P6\n%d %d\n255\n", tex_xsz, tex_ysz); + + for(int i=0; i> 24) & 0xff, fp); + fputc((*ptr >> 24) & 0xff, fp); + fputc((*ptr >> 24) & 0xff, fp); + ptr++; + } + fclose(fp); + } +#endif + + delete [] img; + + act_fnt = fnt; + + return 1; +} + +void DeleteFont(unsigned int fid) +{ +} + +unsigned int GetFont(const char *fname, int sz) +{ + return 1; +} + +bool BindFont(unsigned int fid) +{ + return true; +} + +void SetTextPos(const Vector2 &pos) +{ + text_pos = pos; +} + +Vector2 GetTextPos() +{ + return text_pos; +} + +void TextLineAdvance(int adv) +{ + text_pos.y += (float)adv * act_fnt->line_adv; +} + +void TextCRet() +{ + text_pos.x = 0.0; +} + +void SetTextSize(float sz) +{ + text_size = sz; +} + +float GetTextSize() +{ + return text_size; +} + +void SetTextColor(const Color &col) +{ + text_color = col; +} + +Color GetTextColor() +{ + return text_color; +} + +static void ImOverlay(const Vector2 &v1, const Vector2 &v2, const Color &col, unsigned int tex) +{ + float l = v1.x * 2.0f - 1.0f; + float r = v2.x * 2.0f - 1.0f; + float u = -v1.y * 2.0f + 1.0f; + float d = -v2.y * 2.0f + 1.0f; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glBindTexture(GL_TEXTURE_2D, tex); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + + glBegin(GL_QUADS); + glColor4f(col.r, col.g, col.b, col.a); + glTexCoord2f(0, 0); + glVertex2f(l, u); + glTexCoord2f(1, 0); + glVertex2f(r, u); + glTexCoord2f(1, 1); + glVertex2f(r, d); + glTexCoord2f(0, 1); + glVertex2f(l, d); + glEnd(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + +float PrintChar(char c) +{ + // get texture coordinates for the glyph, and construct the texture matrix + float tx = act_fnt->glyphs[(int)c].tc_pos.x; + float ty = act_fnt->glyphs[(int)c].tc_pos.y; + float sx = act_fnt->glyphs[(int)c].tc_sz.x; + float sy = act_fnt->glyphs[(int)c].tc_sz.y; + + float mat[] = { + sx, 0, tx, 0, + 0, sy, ty, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadMatrixf(mat); + + Vector2 pos = text_pos + act_fnt->glyphs[(int)c].pos * act_fnt->scale; + ImOverlay(pos, pos + act_fnt->glyphs[(int)c].size * act_fnt->scale, text_color, act_fnt->tex_id); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + + return act_fnt->glyphs[(int)c].advance * act_fnt->scale; +} + +// this function contains the preamble of all block text drawing functions (i.e. not printchar above) +static void PreDraw() +{ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + /*glLoadTransposeMatrixf(OrthoProj(2, 2, 0, 10).m);*/ + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glLoadIdentity(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, act_fnt->tex_id); + + glBegin(GL_QUADS); + glColor4f(text_color.r, text_color.g, text_color.b, text_color.a); +} + +static void PostDraw() +{ + glEnd(); + + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_TEXTURE); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); +} + +float PrintString(const char *str, bool standalone) +{ + if(standalone) PreDraw(); + + float start_x = text_pos.x; + while(*str) { + float tx = act_fnt->glyphs[(int)*str].tc_pos.x; + float ty = act_fnt->glyphs[(int)*str].tc_pos.y; + float sx = act_fnt->glyphs[(int)*str].tc_sz.x; + float sy = act_fnt->glyphs[(int)*str].tc_sz.y; + + Vector2 tc1 = Vector2(tx, ty); + Vector2 tc2 = Vector2(tx + sx, ty + sy); + + Vector2 v1 = text_pos + act_fnt->glyphs[(int)*str].pos * act_fnt->scale * text_size; + Vector2 v2 = v1 + act_fnt->glyphs[(int)*str].size * act_fnt->scale * text_size; + float l = v1.x * 2.0f - 1.0f; + float r = v2.x * 2.0f - 1.0f; + float u = -v1.y * 2.0f + 1.0f; + float d = -v2.y * 2.0f + 1.0f; + + glTexCoord2f(tc1.x, tc1.y); + glVertex2f(l, u); + glTexCoord2f(tc2.x, tc1.y); + glVertex2f(r, u); + glTexCoord2f(tc2.x, tc2.y); + glVertex2f(r, d); + glTexCoord2f(tc1.x, tc2.y); + glVertex2f(l, d); + + text_pos.x += act_fnt->glyphs[(int)*str++].advance * act_fnt->scale * text_size; + } + + if(standalone) PostDraw(); + return text_pos.x - start_x; +} + +void PrintStringLines(const char **str, int lines) +{ + PreDraw(); + + while(lines-- > 0) { + PrintString(*str++, false); + TextLineAdvance(); + TextCRet(); + } + + PostDraw(); +} + +static void BlitFontGlyph(Font *fnt, int x, int y, FT_GlyphSlot glyph, unsigned int *img, int xsz, int ysz) +{ + if(glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) { + fprintf(stderr, "BlitFontGlyph: unsupported pixel mode: %d\n", glyph->bitmap.pixel_mode); + return; + } + + unsigned int *dest = img + y * xsz + x; + unsigned char *src = glyph->bitmap.buffer; + + for(int j=0; jbitmap.rows; j++) { + for(int i=0; ibitmap.width; i++) { + dest[i] = 0x00ffffff | ((unsigned int)src[i] << 24); + } + dest += xsz; + src += glyph->bitmap.pitch; + } +} + +static void CleanUp() +{ + FT_Done_FreeType(ft); +} + +float GetMaxDescent() +{ + Font *fnt = act_fnt; + + float max_descent = 0.0f; + + for(int i=0; iglyphs[i].pos.y + fnt->glyphs[i].size.y; + if(isprint(i) && des > max_descent) { + max_descent = des; + } + } + + return max_descent; +} + +float GetLineAdvance() +{ + return act_fnt->line_adv; +} + +float GetTextWidth(const char *str) +{ + float width = 0; + while(*str) { + width += act_fnt->glyphs[(int)*str++].advance * act_fnt->scale * text_size; + } + return width; +} diff -r 03022062c464 -r 87b6a11c920b src/utktext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/utktext.h Tue Oct 26 08:49:09 2010 +0300 @@ -0,0 +1,45 @@ +#ifndef TEXT_H +#define TEXT_H + +#if defined(WIN32) || defined(__WIN32__) +#include +#endif + +#include + +class Color { +public: + float r, g, b, a; + + Color() {r = g = b = a = 1.0f;} + Color(float r, float g, float b, float a = 1.0f) {this->r = r; this->g = g; this->b = b; this->a = a;} +}; + + +unsigned int CreateFont(const char *fname, int font_size); +void DeleteFont(unsigned int fid); +unsigned int GetFont(const char *fname, int sz); +bool BindFont(unsigned int fid); + + +void SetTextPos(const Vector2 &pos); +Vector2 GetTextPos(); + +void TextLineAdvance(int adv = 1); +void TextCRet(); + +void SetTextSize(float sz); +float GetTextSize(); + +void SetTextColor(const Color &col); +Color GetTextColor(); + +float PrintChar(char c); +float PrintString(const char *text, bool standalone = true); +void PrintStringLines(const char **str, int lines); + +float GetMaxDescent(); +float GetLineAdvance(); +float GetTextWidth(const char *str); + +#endif // TEXT_H