aboutsummaryrefslogtreecommitdiff
path: root/gragl.c
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-11-09 02:17:39 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2023-11-09 02:17:39 +0100
commit87a70d198b1361b6c9601e61fef6b58071bbd0a8 (patch)
tree4984b93437a13d6f9fac8876e9e39cf0a78bbebb /gragl.c
parent0dca2c3e51c98dfa9e62cddd32cadbf6c7f71a3d (diff)
add interactivity and shared libHEADv0.0.1master
Diffstat (limited to 'gragl.c')
-rw-r--r--gragl.c172
1 files changed, 124 insertions, 48 deletions
diff --git a/gragl.c b/gragl.c
index 430b581..c14337d 100644
--- a/gragl.c
+++ b/gragl.c
@@ -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();