diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-11-09 02:17:39 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-11-09 02:17:39 +0100 |
| commit | 87a70d198b1361b6c9601e61fef6b58071bbd0a8 (patch) | |
| tree | 4984b93437a13d6f9fac8876e9e39cf0a78bbebb /gragl.c | |
| parent | 0dca2c3e51c98dfa9e62cddd32cadbf6c7f71a3d (diff) | |
Diffstat (limited to 'gragl.c')
| -rw-r--r-- | gragl.c | 172 |
1 files changed, 124 insertions, 48 deletions
@@ -1,102 +1,114 @@ +#include <GL/freeglut_std.h> +#include <GL/gl.h> +#include <float.h> #include <stdarg.h> #include <GL/freeglut.h> #include <memory.h> #include <stdio.h> #include <math.h> +#include <sys/param.h> #include "gragl.h" #define SUBWINDOWS 64 -Plot2dGroup * target = NULL; +static Plot2dGroup * target = NULL; +static struct { + int last_x; + int last_y; + int state; +} mouse; -int subwindows[SUBWINDOWS]; +static int subwindows[SUBWINDOWS]; static void enable_multi_sample() { glEnable(GL_MULTISAMPLE); glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); } -static void draw_function(double from, double to, double step, Scalar(*fun)(double)) { - glColor3f(0.9f, 0.5f, 0.2f); - glLineWidth(2); +static void draw_function(double x, double y, double size, double step, Function * function) { + glColor3fv(function->color); + glLineWidth(function->width); glBegin(GL_LINES); - for (double i = from; i < to; i += step) { - Scalar current = fun(i); - Scalar next = fun(i + step); + for (double i = 0; i < size; i += step) { + Scalar current = function->func(i - x); + Scalar next = function->func(i + step - x); if (current.valid) { - glVertex2f(i, current.v); - glVertex2f(i + step, next.v); + glVertex2f(i, current.v + y); + glVertex2f(i + step, next.v + y); } } glEnd(); } -void draw_axis() { - glColor3f(1, 1, 1); +void draw_axis(double x, double y) { + glColor3fv(COLOR_WHITE); glLineWidth(2); glBegin(GL_LINES); - glVertex2f(0, 0); - glVertex2f(1, 0); - glVertex2f(0, 0); - glVertex2f(0, 1); + glVertex2f(x, y); + glVertex2f(x + 1, y); + glVertex2f(x, y); + glVertex2f(x, y + 1); - glVertex2f(1, 0); - glVertex2f(0.9, 0.1); - glVertex2f(1, 0); - glVertex2f(0.9, -0.1); + glVertex2f(x + 1, y); + glVertex2f(x + 0.9, y + 0.1); + glVertex2f(x + 1, y + 0); + glVertex2f(x + 0.9, y - 0.1); - glVertex2f(0, 1); - glVertex2f(0.1, 0.9); - glVertex2f(0, 1); - glVertex2f(-0.1, 0.9); + glVertex2f(x, y + 1); + glVertex2f(x + 0.1, y + 0.9); + glVertex2f(x, y + 1); + glVertex2f(x - 0.1, y + 0.9); glEnd(); } -void draw_grid(double from, double to) { +void draw_grid(double x, double y, double size) { glColor3f(0.2, 0.2, 0.2); - double yl = (from + to) / 2 + 1; - glLineWidth(2); glBegin(GL_LINES); - for (double i = from; i < to; ++i) { - glVertex2f(i, yl); - glVertex2f(i, -yl); + for (double i = 0; i < size; ++i) { + double xpos = fmod(x + i, size); + if (xpos < 0) xpos += size; + glVertex2f(xpos, -size / 2); + glVertex2f(xpos, size / 2); } - for (double i = -yl; i < yl; ++i) { - glVertex2f(from, i); - glVertex2f(to, i); + for (double i = 0; i < size; ++i) { + double ypos = fmod(y + i, size); + if (ypos < 0) ypos += size; + glVertex2f(0, ypos - size / 2); + glVertex2f(size, ypos - size / 2); } glEnd(); glColor3f(0.5, 0.5, 0.5); glBegin(GL_LINES); - glVertex2f(from, 0); - glVertex2f(to, 0); + glVertex2f(0, y); + glVertex2f(size, y); - glVertex2f(0, yl); - glVertex2f(0, -yl); + glVertex2f(x, -size / 2); + glVertex2f(x, size / 2); glEnd(); glColor3f(0.7, 0.7, 0.7); glBegin(GL_LINE_LOOP); - glVertex2f(from, yl); - glVertex2f(to, yl); - glVertex2f(to, -yl); - glVertex2f(from, -yl); + glVertex2f(0, -size / 2); + glVertex2f(size, -size / 2); + glVertex2f(size, size / 2); + glVertex2f(0, size / 2); glEnd(); } static void update() { + glClearColor(COLOR_BLACK[0], COLOR_BLACK[1], COLOR_BLACK[2], COLOR_BLACK[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); int window = glutGetWindow(); int plot_id = 0; @@ -104,15 +116,21 @@ static void update() { while (subwindows[plot_id] != window) ++plot_id; Plot2d * plot = &(target->plots[plot_id]); + plot->width = glutGet(GLUT_WINDOW_WIDTH); + plot->height = glutGet(GLUT_WINDOW_HEIGHT); + + double translate = -(plot->rsize / 2); + double zoom = 2 / (plot->rsize); - double translate = -((plot->to + plot->from) / 2); - double zoom = 2 / (plot->to - plot->from); glScalef(zoom, zoom, zoom); glTranslatef(translate, 0, 0); - draw_grid(plot->from, plot->to); - draw_axis(); - draw_function(plot->from, plot->to, plot->step, plot->func); + draw_grid(plot->x, plot->y, plot->rsize); + draw_axis(plot->x, plot->y); + + for (Function *f = plot->function; f < plot->function + plot->nfuncs; ++f) { + draw_function(plot->x, plot->y, plot->rsize, plot->step, f); + } glTranslatef(-translate, 0, 0); glScalef(1/zoom, 1/zoom, 1/zoom); @@ -121,6 +139,7 @@ static void update() { } static void parent_update() { + glClearColor(COLOR_DARKER[0], COLOR_DARKER[1], COLOR_DARKER[2], COLOR_DARKER[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSwapBuffers(); @@ -131,6 +150,8 @@ static void parent_update() { unsigned n_plots = ((unsigned)sqrt(target->n)); int plot_dim = min / (int)n_plots - (int)target->padding / 4; + int padding_x = (width - plot_dim * n_plots) / 2; + int padding_y = (height - plot_dim * n_plots) / 2; plot_dim = plot < 0 ? 1 : plot_dim; @@ -141,12 +162,63 @@ static void parent_update() { plot_dim - target->padding / 2 ); glutPositionWindow( - (i % n_plots) * plot_dim + target->padding / 2, - (i / n_plots) * plot_dim + target->padding / 2 + padding_x + (i % n_plots) * plot_dim + target->padding / 2, + padding_y + (i / n_plots) * plot_dim + target->padding / 2 ); } } + +static void mouse_wheel(int wheel, int direction, int x, int y) { + int window = glutGetWindow(); + int plot_id = 0; + while (subwindows[plot_id] != window) ++plot_id; + Plot2d *plot = target->plots + plot_id; + + + plot->rsize += direction * MAX(log(plot->rsize), 0.00001); + + glutPostRedisplay(); +} + + +static void mouse_move(int x, int y) { + int window = glutGetWindow(); + int plot_id = 0; + while (subwindows[plot_id] != window) ++plot_id; + Plot2d *plot = target->plots + plot_id; + + double delta_x = x - mouse.last_x; + double delta_y = y - mouse.last_y; + + plot->x += delta_x / plot->width * plot->rsize; + plot->y -= delta_y / plot->width * plot->rsize; + + mouse.last_x = x; + mouse.last_y = y; + + glutPostRedisplay(); +} + + +static void mouse_button(int button, int state, int x, int y) { + mouse.state = state; + mouse.last_x = x; + mouse.last_y = y; + + if (state) { + glutSetCursor(GLUT_CURSOR_INHERIT); + } else { + glutSetCursor(GLUT_CURSOR_INFO); + } +} + + +static void resize(int width, int height) { + glutReshapeWindow(MAX(width, 10), MAX(width, 10)); +} + + void plot(Plot2dGroup * group) { target = group; @@ -164,10 +236,14 @@ void plot(Plot2dGroup * group) { subwindows[i] = id; glutSetWindow(id); glutDisplayFunc(update); + glutMouseFunc(mouse_button); + glutMotionFunc(mouse_move); + glutMouseWheelFunc(mouse_wheel); } glutSetWindow(parent); glutDisplayFunc(parent_update); + glutReshapeFunc(resize); enable_multi_sample(); |