Skip to content

Commit

Permalink
Merge pull request #8 from wojciech-graj/v1.2
Browse files Browse the repository at this point in the history
Release v1.2.0
  • Loading branch information
wojciech-graj authored Feb 9, 2022
2 parents 3268fe2 + e54a1d0 commit e060573
Show file tree
Hide file tree
Showing 4 changed files with 358 additions and 182 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ A terminal-based graphics library for both 2D and 3D graphics.\
Works in all terminals supporting ANSI escape codes.\
Support for Windows and UNIX.\
C99 compliant, with no external dependencies.\
Realtime input reading from terminal for user-interaction.
Realtime input reading from terminal for user-interaction.\
16 Background colors, 16 foreground colors, bold and underline.

## Table of Contents

Expand Down Expand Up @@ -61,9 +62,9 @@ To compile a demo program, run the makefile ```make demo```.

## Documentation

Certain settings can be changed at the top of [lib/termgl.h](lib/termgl.h) prior to compilation, e.g. memory allocation functions, clear screen command, compiler-specific commands.\
Certain settings can be changed at the top of [src/termgl.c](src/termgl.c) prior to compilation, e.g. memory allocation functions, clear screen command, compiler-specific commands.\
The header file [lib/termgl.h](lib/termgl.h) contains brief documentation for all functions and structs.\
Compiler-specific (GCC) macros are used for loop unrolling in the ```itgl_mulmat``` and ```itgl_clip_triangle_plane``` functions.\
Compiler-specific functionality is used, therefore it is recommened to always compile using GCC. If other compilers are used for other sections of code, see Build: Methods 2 & 3.\
The TermGLUtil extension contains functions for reading keyboard input, but requires either Windows of UNIX headers.

### Demo
Expand All @@ -83,10 +84,13 @@ Renders a rotating 3D Utah Teapot.
Renders a star polygon in steps using random colors.
- Colors
- Line rendering
3. Mandelbrot\
3. Color Palette\
Renders a palette of various text colors and styles.
- Colors & Modifiers
4. Mandelbrot\
Renders an infinitely zooming-in Mandelbrot set.
- Point rendering
4. Realtime Keyboard\
5. Realtime Keyboard\
Displays keyboard input in realtime.
- Text rendering
- Realtime keyboard input
136 changes: 96 additions & 40 deletions demodir/termgl_demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,43 @@ Select a Demo:\n\
Renders a rotating 3D Utah Teapot.\n\
2. Star Polygon\n\
Renders a star polygon in steps using random colors.\n\
3. Mandelbrot\n\
3. Color Palette\n\
Renders a palette of various text colors and styles.\n\
4. Mandelbrot\n\
Renders an infinitely zooming-in Mandelbrot set.\n\
4. Realtime Keyboard\n\
5. Realtime Keyboard\n\
Displays keyboard input in realtime.\
";

const uint16_t fg_colors[] = {
TGL_BLACK,
TGL_RED,
TGL_GREEN,
TGL_YELLOW,
TGL_BLUE,
TGL_PURPLE,
TGL_CYAN,
TGL_WHITE,
};
const uint16_t bkg_colors[] = {
TGL_BLACK_BKG,
TGL_RED_BKG,
TGL_GREEN_BKG,
TGL_YELLOW_BKG,
TGL_BLUE_BKG ,
TGL_PURPLE_BKG,
TGL_CYAN_BKG,
TGL_WHITE_BKG,
};

void teapot_intermediate_shader(TGLTriangle *trig, void *data);
uint32_t stl_load(FILE *file, TGLTriangle **triangles);
void sleep_ms(const unsigned long ms);

void demo_mandelbrot(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms);
void demo_teapot(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms);
void demo_keyboard(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms);
void demo_star(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms);
void demo_color(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms);

void teapot_intermediate_shader(TGLTriangle *trig, void *data)
Expand Down Expand Up @@ -104,7 +128,8 @@ void sleep_ms(const unsigned long ms)
void demo_mandelbrot(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
{
TGL *tgl = tgl_init(res_x, res_y, &gradient_full);
tgl_enable(tgl, TGL_OUTPUT_BUFFER);
assert(tgl);
assert(!tgl_enable(tgl, TGL_OUTPUT_BUFFER));

const unsigned frame_max = 90;
const unsigned i_max = 255;
Expand Down Expand Up @@ -140,13 +165,13 @@ void demo_mandelbrot(const unsigned res_x, const unsigned res_y, const unsigned
i++;
}
if (i < i_max) // Set pixel with intensity dependent on i
tgl_point(tgl, pix_x, pix_y, 0.f, i * 255u / i_max, TGL_WHITE);
tgl_point(tgl, pix_x, pix_y, 0.f, i * 255u / i_max, TGL_WHITE | TGL_BOLD);
x += dx;
}
y += dy;
}

tgl_flush(tgl);
assert(!tgl_flush(tgl));
tgl_clear(tgl, TGL_FRAME_BUFFER | TGL_OUTPUT_BUFFER);

if (frame++ < frame_max) {
Expand All @@ -171,9 +196,10 @@ void demo_mandelbrot(const unsigned res_x, const unsigned res_y, const unsigned
void demo_teapot(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
{
TGL *tgl = tgl_init(res_x, res_y, &gradient_min);
tgl3d_init(tgl);
assert(tgl);
assert(!tgl3d_init(tgl));
tgl3d_cull_face(tgl, TGL_BACK | TGL_CCW);
tgl_enable(tgl, TGL_DOUBLE_CHARS | TGL_CULL_FACE | TGL_Z_BUFFER | TGL_OUTPUT_BUFFER);
assert(!tgl_enable(tgl, TGL_DOUBLE_CHARS | TGL_CULL_FACE | TGL_Z_BUFFER | TGL_OUTPUT_BUFFER));
tgl3d_camera(tgl, 1.57f, 0.1f, 5.f);

// Load triangles
Expand Down Expand Up @@ -211,10 +237,10 @@ void demo_teapot(const unsigned res_x, const unsigned res_y, const unsigned fram
memcpy(temp.intensity, trigs[i].intensity, 3);

//Draw to framebuffer
tgl3d_shader(tgl, &temp, TGL_WHITE, true, &temp, &teapot_intermediate_shader);
tgl3d_shader(tgl, &temp, TGL_WHITE | TGL_BOLD, true, &temp, &teapot_intermediate_shader);
}

tgl_flush(tgl);
assert(!tgl_flush(tgl));
tgl_clear(tgl, TGL_FRAME_BUFFER | TGL_Z_BUFFER | TGL_OUTPUT_BUFFER);

n += dn;
Expand All @@ -229,26 +255,29 @@ void demo_teapot(const unsigned res_x, const unsigned res_y, const unsigned fram
void demo_keyboard(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
{
TGL *tgl = tgl_init(res_x, res_y, &gradient_min);
tgl_enable(tgl, TGL_OUTPUT_BUFFER);
assert(tgl);
assert(!tgl_enable(tgl, TGL_OUTPUT_BUFFER));

const size_t bufsize = 16;

char *input_keys = calloc(bufsize, sizeof(char));
input_keys[0] = '\1';

while (1) {
if (tglutil_read(input_keys, bufsize - 1u)) {
TGL_SSIZE_T chars_read = tglutil_read(input_keys, bufsize - 1u);
assert(chars_read >= 0);
if (chars_read) {
tgl_puts(tgl, 0, 0, "Pressed keys:", TGL_WHITE);
tgl_puts(tgl, 14, 0, input_keys, TGL_WHITE);

tgl_flush(tgl);
assert(!tgl_flush(tgl));
tgl_clear(tgl, TGL_FRAME_BUFFER | TGL_OUTPUT_BUFFER);
} else if (input_keys[0]) {
memset(input_keys, 0, bufsize);

tgl_puts(tgl, 0, 0, "Pressed keys: NONE", TGL_WHITE);

tgl_flush(tgl);
assert(!tgl_flush(tgl));
tgl_clear(tgl, TGL_FRAME_BUFFER | TGL_OUTPUT_BUFFER);
}

Expand All @@ -258,33 +287,14 @@ void demo_keyboard(const unsigned res_x, const unsigned res_y, const unsigned fr
tgl_delete(tgl);
}

void demo_color(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
void demo_star(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
{
TGL *tgl = tgl_init(res_x, res_y, &gradient_min);
tgl_enable(tgl, TGL_OUTPUT_BUFFER);
assert(tgl);
assert(!tgl_enable(tgl, TGL_OUTPUT_BUFFER));

const float pi2 = 6.28319f;
const unsigned n = 8, d = 3;
const TGLubyte fg_colors[] = {
TGL_BLACK,
TGL_RED,
TGL_GREEN,
TGL_YELLOW,
TGL_BLUE,
TGL_PURPLE,
TGL_CYAN,
TGL_WHITE,
};
const TGLubyte bkg_colors[] = {
TGL_BLACK_BKG,
TGL_RED_BKG,
TGL_GREEN_BKG,
TGL_YELLOW_BKG,
TGL_BLUE_BKG ,
TGL_PURPLE_BKG,
TGL_CYAN_BKG,
TGL_WHITE_BKG,
};

unsigned half_res_x = res_x / 2u;
unsigned half_res_y = res_y / 2u;
Expand All @@ -305,11 +315,12 @@ void demo_color(const unsigned res_x, const unsigned res_y, const unsigned frame
TGLubyte i0 = rand() % 256;
TGLubyte i1 = rand() % 256;

TGLubyte color = fg_colors[rand() % 8] | bkg_colors[rand() % 8];
uint16_t color = fg_colors[rand() % 8]
| bkg_colors[rand() % 8];

tgl_line(tgl, x0, y0, 0, i0, x1, y1, 0, i1, color);

tgl_flush(tgl);
assert(!tgl_flush(tgl));
// Buffer clear not yet required

vert = next_vert;
Expand All @@ -323,6 +334,48 @@ void demo_color(const unsigned res_x, const unsigned res_y, const unsigned frame
tgl_delete(tgl);
}

void demo_color(const unsigned res_x, const unsigned res_y, const unsigned frametime_ms)
{
(void)frametime_ms;
TGL *tgl = tgl_init(res_x, res_y, &gradient_min);
assert(tgl);
assert(!tgl_enable(tgl, TGL_OUTPUT_BUFFER));

static const uint16_t modifiers[5][2] = {
{0, 0},
{TGL_HIGH_INTENSITY, TGL_HIGH_INTENSITY_BKG},
{TGL_BOLD, 0},
{TGL_BOLD | TGL_HIGH_INTENSITY, TGL_HIGH_INTENSITY_BKG},
{TGL_UNDERLINE, TGL_UNDERLINE},
};

tgl_puts(tgl, 9, 0, "NULL", TGL_WHITE);
tgl_puts(tgl, 9, 2, "TGL_HIGH_INTENSITY", TGL_WHITE);
tgl_puts(tgl, 9, 4, "TGL_BOLD", TGL_WHITE);
tgl_puts(tgl, 9, 6, "TGL_BOLD + TGL_HIGH_INTENSITY", TGL_WHITE);
tgl_puts(tgl, 9, 8, "TGL_UNDERLINE", TGL_WHITE);

unsigned m, c;
for (m = 0; m < 5; m++) {
unsigned y_start = m * 2;
tgl_putchar(tgl, 0, y_start, 'K', TGL_BLACK | TGL_WHITE_BKG | modifiers[m][0]);
tgl_putchar(tgl, 0, y_start + 1, 'K', TGL_WHITE | TGL_BLACK_BKG | modifiers[m][1]);
for (c = 1; c < 8; c++) {
char color = "KRGYBPCW"[c];
tgl_putchar(tgl, c, y_start, color, fg_colors[c] | TGL_BLACK_BKG | modifiers[m][0]);
tgl_putchar(tgl, c, y_start + 1, color, TGL_BLACK | bkg_colors[c] | modifiers[m][1]);
}
}

assert(!tgl_flush(tgl));

tgl_delete(tgl);

/* Wait for user input */
getchar();
getchar();
}

int main(int argc, char **argv)
{
(void)argc;
Expand All @@ -339,15 +392,18 @@ int main(int argc, char **argv)

switch (n) {
case 1u:
demo_teapot(80, 40, 33);
demo_teapot(40, 40, 33);
break;
case 2u:
demo_color(80, 40, 500);
demo_star(80, 40, 500);
break;
case 3u:
demo_mandelbrot(80, 40, 33);
demo_color(40, 10, 0);
break;
case 4u:
demo_mandelbrot(80, 40, 33);
break;
case 5u:
demo_keyboard(80, 5, 200);
break;
default:
Expand Down
Loading

0 comments on commit e060573

Please sign in to comment.