From f87ce844a6cb17ca5eaa8fd6d138786e495fcff5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 26 Apr 2016 23:51:15 +0100 Subject: [PATCH] Basic State Rendering --- README.md | 2 +- gb_gl.h | 192 +++++++++++++++++++++++++++++++++++++++++++++++------- gb_math.h | 44 ++++++------- 3 files changed, 192 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index fa27f58..a18394d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ library | latest version | category | languages | description ----------------|----------------|----------|-----------|------------- **gb.h** | 0.04 | misc | C, C++ | A C helper library for C & C++ **gb_math.h** | 0.05 | math | C, C++ | A C/C++ vector math library geared towards game development -**gb_gl.h** | 0.02 | graphics | C, C++ | A C/C++ OpenGL Helper Library +**gb_gl.h** | 0.03 | graphics | C, C++ | A C/C++ OpenGL Helper Library **gb_string.h** | 0.94 | strings | C, C++ | A better string library for C & C++ (this is built into gb.h too with custom allocator support!) **gb_ini.h** | 0.92 | misc | C, C++ | A simple ini file loader library for C & C++ diff --git a/gb_gl.h b/gb_gl.h index eac081d..b41fbdf 100644 --- a/gb_gl.h +++ b/gb_gl.h @@ -1,4 +1,4 @@ -/* gb.h - v0.02 - OpenGL Helper Library - public domain +/* gb.h - v0.03 - OpenGL Helper Library - public domain - no warranty implied; use at your own risk This is a single header file with a bunch of useful stuff @@ -34,6 +34,7 @@ Conventions used: Version History: + 0.03 - Basic State Rendering 0.02 - Font Caching and Rendering 0.01 - Initial Version @@ -553,11 +554,10 @@ GBGL_DEF f32 gbgl_get_string_width (gbglFont *font #ifndef GBGL_FONT_CHAR_LIST #define GBGL_FONT_CHAR_LIST \ - "チーズ"\ - "Āā㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľŁłŃńŅņņŇňʼnŊŋ"\ - "ŌōōŎŏŐőŒœŕŖŗŘřŚśŜŝŞşŠšŢţŤťŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽža!ö"\ + "Āā㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľŁł"\ + "ŃńŅņņŇňʼnŊŋŌōōŎŏŐőŒœŕŖŗŘřŚśŜŝŞşŠšŢţŤťŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽža!ö"\ "\"#$%%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"\ - "Šš?ŒœŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõøùúûüýþÿ®™"\ + "ŠšŒœŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõøùúûüýþÿ®™£"\ " \t\r\n" #endif @@ -617,10 +617,25 @@ GBGL_DEF void gbgl_bs_draw_quad_outline(gbglBasicState *bs, gbColour col, f32 thickness); GBGL_DEF void gbgl_bs_draw_line(gbglBasicState *bs, gbVec2 p0, gbVec2 p1, gbColour col, f32 thickness); + +GBGL_DEF void gbgl_bs_draw_elliptical_arc(gbglBasicState *bs, gbVec2 p, f32 radius_a, f32 radius_b, f32 min_angle, f32 max_angle, gbColour col); +GBGL_DEF void gbgl_bs_draw_elliptical_arc_outline(gbglBasicState *bs, gbVec2 p, f32 radius_a, f32 radius_b, + f32 min_angle, f32 max_angle, gbColour col, f32 thickness); + GBGL_DEF void gbgl_bs_draw_circle(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col); GBGL_DEF void gbgl_bs_draw_circle_outline(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col, f32 thickness); +// Corners Flags: +// 1 - Bottom Left +// 2 - Bottom Right +// 4 - Top Right +// 8 - Top Left +// NOTE(bill): Apple, please don't sue me! +GBGL_DEF void gbgl_bs_draw_rounded_rect_corners(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, u32 corners); +GBGL_DEF void gbgl_bs_draw_rounded_rect(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col); + + GBGL_DEF isize gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *str, isize len); GBGL_DEF isize gbgl_bs_draw_string (gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *fmt, ...); GBGL_DEF isize gbgl_bs_draw_string_va(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *fmt, va_list va); @@ -2125,7 +2140,8 @@ gbgl_bs_draw_line(gbglBasicState *bs, gbVec2 p0, gbVec2 p1, gbColour col, f32 th } void -gbgl_bs_draw_circle(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col) +gbgl_bs_draw_elliptical_arc(gbglBasicState *bs, gbVec2 p, f32 radius_a, f32 radius_b, + f32 min_angle, f32 max_angle, gbColour col) { isize i; @@ -2134,11 +2150,11 @@ gbgl_bs_draw_circle(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col) for (i = 0; i < 31; i++) { f32 t = cast(f32)i / 30.0f; - f32 theta = t * GB_MATH_TAU; + f32 theta = gb_lerp(min_angle, max_angle, t); f32 c = gb_cos(theta); f32 s = gb_sin(theta); - bs->vertices[i+1].x = p.x + c*radius; - bs->vertices[i+1].y = p.y + s*radius; + bs->vertices[i+1].x = p.x + c*radius_a; + bs->vertices[i+1].y = p.y + s*radius_b; } gbgl__bs_setup_ortho_colour_state(bs, 32, col); @@ -2146,17 +2162,18 @@ gbgl_bs_draw_circle(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col) } void -gbgl_bs_draw_circle_outline(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col, f32 thickness) +gbgl_bs_draw_elliptical_arc_outline(gbglBasicState *bs, gbVec2 p, f32 radius_a, f32 radius_b, + f32 min_angle, f32 max_angle, gbColour col, f32 thickness) { isize i; for (i = 0; i < 32; i++) { f32 t = cast(f32)i / 31.0f; - f32 theta = t * GB_MATH_TAU; + f32 theta = gb_lerp(min_angle, max_angle, t); f32 c = gb_cos(theta); f32 s = gb_sin(theta); - bs->vertices[i].x = p.x + c*radius; - bs->vertices[i].y = p.y + s*radius; + bs->vertices[i+1].x = p.x + c*radius_a; + bs->vertices[i+1].y = p.y + s*radius_b; } gbgl__bs_setup_ortho_colour_state(bs, 32, col); @@ -2164,13 +2181,141 @@ gbgl_bs_draw_circle_outline(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour c glDrawArrays(GL_LINE_LOOP, 0, 32); } + + +gb_inline void +gbgl_bs_draw_circle(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col) +{ + gbgl_bs_draw_elliptical_arc(bs, p, radius, radius, 0, GB_MATH_TAU, col); +} + +gb_inline void +gbgl_bs_draw_circle_outline(gbglBasicState *bs, gbVec2 p, f32 radius, gbColour col, f32 thickness) +{ + gbgl_bs_draw_elliptical_arc_outline(bs, p, radius, radius, 0, GB_MATH_TAU, col, thickness); +} + +void +gbgl_bs_draw_rounded_rect_corners(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col, u32 corners) +{ + if ((2.0f*roundness > gb_abs(dim.x)) || + (2.0f*roundness > gb_abs(dim.y))) { + roundness = 0.5f*gb_min(gb_abs(dim.x), gb_abs(dim.y)); + } + + if (roundness == 0 || corners == 0) { + gbgl_bs_draw_rect(bs, pos, dim, col); + } else { + isize i, vc = 0; + + bs->vertices[0].x = pos.x + 0.5f*dim.x; + bs->vertices[0].y = pos.y + 0.5f*dim.y; + vc++; + + if (corners & 1) { + for (i = 0; i < 6; i++) { + f32 t = cast(f32)i / 5.0f; + f32 theta = gb_lerp(0.5f*GB_MATH_TAU, 0.75f*GB_MATH_TAU, t); + f32 c = gb_cos(theta); + f32 s = gb_sin(theta); + bs->vertices[vc].x = pos.x + roundness + c*roundness; + bs->vertices[vc].y = pos.y + roundness + s*roundness; + vc++; + } + } else { + bs->vertices[vc].x = pos.x; + bs->vertices[vc].y = pos.y + roundness; + bs->vertices[vc+1].x = pos.x; + bs->vertices[vc+1].y = pos.y; + bs->vertices[vc+2].x = pos.x + roundness; + bs->vertices[vc+2].y = pos.y; + vc += 3; + } + + if (corners & 2) { + for (i = 0; i < 6; i++) { + f32 t = cast(f32)i / 5.0f; + f32 theta = gb_lerp(0.75f*GB_MATH_TAU, 1.00f*GB_MATH_TAU, t); + f32 c = gb_cos(theta); + f32 s = gb_sin(theta); + bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness; + bs->vertices[vc].y = pos.y + roundness + s*roundness; + vc++; + } + } else { + bs->vertices[vc].x = pos.x + dim.x - roundness; + bs->vertices[vc].y = pos.y; + bs->vertices[vc+1].x = pos.x + dim.x; + bs->vertices[vc+1].y = pos.y; + bs->vertices[vc+2].x = pos.x + dim.x; + bs->vertices[vc+2].y = pos.y + roundness; + vc += 3; + } + + + if (corners & 4) { + for (i = 0; i < 6; i++) { + f32 t = cast(f32)i / 5.0f; + f32 theta = gb_lerp(0.00f*GB_MATH_TAU, 0.25f*GB_MATH_TAU, t); + f32 c = gb_cos(theta); + f32 s = gb_sin(theta); + bs->vertices[vc].x = pos.x + dim.x - roundness + c*roundness; + bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness; + vc++; + } + } else { + bs->vertices[vc].x = pos.x + dim.x; + bs->vertices[vc].y = pos.y + dim.y - roundness; + bs->vertices[vc+1].x = pos.x + dim.x; + bs->vertices[vc+1].y = pos.y + dim.y; + bs->vertices[vc+2].x = pos.x + dim.x - roundness; + bs->vertices[vc+2].y = pos.y + dim.y; + vc += 3; + } + + if (corners & 8) { + for (i = 0; i < 6; i++) { + f32 t = cast(f32)i / 5.0f; + f32 theta = gb_lerp(0.25f*GB_MATH_TAU, 0.50f*GB_MATH_TAU, t); + f32 c = gb_cos(theta); + f32 s = gb_sin(theta); + bs->vertices[vc].x = pos.x + roundness + c*roundness; + bs->vertices[vc].y = pos.y + dim.y - roundness + s*roundness; + vc++; + } + } else { + bs->vertices[vc].x = pos.x + roundness; + bs->vertices[vc].y = pos.y + dim.y; + bs->vertices[vc+1].x = pos.x; + bs->vertices[vc+1].y = pos.y + dim.y; + bs->vertices[vc+2].x = pos.x; + bs->vertices[vc+2].y = pos.y + dim.y - roundness; + vc += 3; + } + + bs->vertices[vc-1].x = pos.x; + bs->vertices[vc-1].y = pos.y + roundness; + + gbgl__bs_setup_ortho_colour_state(bs, vc, col); + glDrawArrays(GL_TRIANGLE_FAN, 0, vc); + } +} + +gb_inline void +gbgl_bs_draw_rounded_rect(gbglBasicState *bs, gbVec2 pos, gbVec2 dim, f32 roundness, gbColour col) +{ + gbgl_bs_draw_rounded_rect_corners(bs, pos, dim, roundness, col, 1|2|4|8); +} + + + + isize gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColour col, char const *str, isize len) { isize char_count = gb_utf8_strnlen(str, len); - if (char_count <= 0) { - return 0; - } else { + isize line_count = 0; + if (char_count > 0) { char const *ptr = str; f32 sf = 1.0f / cast(f32)font->bitmap_width; @@ -2179,7 +2324,7 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou f32 ox, oy; f32 px, py; - isize line_count = 1, glyph_count = 0, i; + isize glyph_count = 0, i; f32 font_height = font->size; i32 max_width = bs->text_params[GBGL_TEXT_PARAM_MAX_WIDTH].val_i32; f32 max_width32 = cast(f32)max_width; @@ -2195,6 +2340,8 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou x = cast(i32)gb_round(cast(f32)x - width); } + line_count = 1; + ox = x; oy = y; px = ox; @@ -2292,17 +2439,17 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou } - { - isize sampler_handle = 0; + if (glyph_count > 0) { + isize sampler_index = 0; gbgl_use_shader(&bs->font_shader); gbgl_set_uniform_mat4(&bs->font_shader, "u_ortho_mat", &bs->ortho_mat); gbgl_set_uniform_colour(&bs->font_shader, "u_colour", col); GB_ASSERT(bs->text_params[GBGL_TEXT_PARAM_TEXTURE_FILTER].val_i32 < gb_count_of(bs->font_samplers)); if (bs->text_params[GBGL_TEXT_PARAM_TEXTURE_FILTER].val_i32 < gb_count_of(bs->font_samplers)) - sampler_handle = bs->text_params[GBGL_TEXT_PARAM_TEXTURE_FILTER].val_i32; + sampler_index = bs->text_params[GBGL_TEXT_PARAM_TEXTURE_FILTER].val_i32; - gbgl_bind_texture2d(&font->texture, 0, bs->font_samplers[sampler_handle]); + gbgl_bind_texture2d(&font->texture, 0, bs->font_samplers[sampler_index]); gbgl_vbo_copy(bs->font_vbo, bs->font_vertices, gb_size_of(bs->font_vertices[0]) * glyph_count * 4, 0); gbgl_vert_ptr_aa(0, 2, gbglBasicVertex, x); @@ -2316,9 +2463,8 @@ gbgl_bs_draw_substring(gbglBasicState *bs, gbglFont *font, i32 x, i32 y, gbColou glDrawElements(GL_TRIANGLES, glyph_count*6, GL_UNSIGNED_SHORT, NULL); } - - return line_count; } + return line_count; } isize diff --git a/gb_math.h b/gb_math.h index 178043f..a4e69d6 100644 --- a/gb_math.h +++ b/gb_math.h @@ -787,81 +787,81 @@ gb_mod(float x, float y) hx ^= sx; hy &= 0x7fffffff; - // Purge off exception values - if (hy == 0||(hx >= 0x7f800000)|| // Y=0,or x not finite - (hy > 0x7f800000)) // Or y is NaN + // NOTE(bill): Purge off exception values + if (hy == 0||(hx >= 0x7f800000)|| // NOTE(bill): Y=0,or x not finite + (hy > 0x7f800000)) // NOTE(bill): Or y is NaN return (x*y)/(x*y); - if (hx < hy) return x; // |x|<|y| return x - if (hx == hy) return gb__zero[(unsigned int)sx>>31]; // |x|=|y| return x*0 + if (hx < hy) return x; // NOTE(bill): |x|<|y| return x + if (hx == hy) return gb__zero[(unsigned int)sx>>31]; // NOTE(bill): |x|=|y| return x*0 - // Determine ix = ilogb(x) - if (hx < 0x00800000) { // Subnormal x + // NOTE(bill): Determine ix = ilogb(x) + if (hx < 0x00800000) { // NOTE(bill): Subnormal x for (ix = -126, i = (hx<<8); i > 0; i <<= 1) ix -=1; } else { ix = (hx>>23)-127; } - // Determine iy = ilogb(y) - if (hy < 0x00800000) { // Subnormal y + // NOTE(bill): Determine iy = ilogb(y) + if (hy < 0x00800000) { // NOTE(bill): Subnormal y for (iy = -126, i = (hy<<8); i >= 0; i <<=1 ) iy -=1; } else { iy = (hy>>23)-127; } - // Set up {hx,lx}, {hy,ly} and align y to x + // NOTE(bill): Set up {hx, lx}, {hy, ly} and align y to x if (ix >= -126) { hx = 0x00800000|(0x007fffff&hx); - } else { // Subnormal x, shift x to normal + } else { // NOTE(bill): Subnormal x, shift x to normal n = -126-ix; hx = hx<= -126) { hy = 0x00800000|(0x007fffff&hy); - } else { // Subnormal y, shift y to normal + } else { // NOTE(bill): Subnormal y, shift y to normal n = -126-iy; hy = hy<>31]; hx = hz+hz; } } - hz=hx-hy; + hz = hx-hy; if (hz >= 0) hx = hz; - // Convert back to floating value and restore the sign - if (hx == 0) // Return sign(x)*0 + // NOTE(bill): Convert back to floating value and restore the sign + if (hx == 0) // NOTE(bill): Return sign(x)*0 return gb__zero[(unsigned int)sx>>31]; - while (hx < 0x00800000) { // Normalize x + while (hx < 0x00800000) { // NOTE(bill): Normalize x hx = hx+hx; iy -= 1; } - if (iy >= -126) { // Normalize output + if (iy >= -126) { // NOTE(bill): Normalize output int t; hx = ((hx-0x00800000) | ((iy + 127)<<23)); t = hx | sx; x = *(float *)&t; - } else { // Subnormal output + } else { int t; n = -126 - iy; hx >>= n; t = hx | sx; x = *(float *)&t; - x *= 1.0f; // Create necessary signal + x *= 1.0f; } - return x; // Exact output + return x; }