diff options
| author | NPScript <nathan@reinerweb.ch> | 2022-08-18 17:04:05 +0200 |
|---|---|---|
| committer | NPScript <nathan@reinerweb.ch> | 2022-08-18 17:04:05 +0200 |
| commit | 95361c8c2229840a5e05f49622be629cf654371d (patch) | |
| tree | 280a6d7706b349563959852057e1741f846d5f60 /gragl.c | |
first sketch
Diffstat (limited to 'gragl.c')
| -rw-r--r-- | gragl.c | 198 |
1 files changed, 198 insertions, 0 deletions
@@ -0,0 +1,198 @@ +#include <stdarg.h> +#include <GL/freeglut.h> +#include <memory.h> +#include <stdio.h> +#include <math.h> + +#include "gragl.h" + +#define SUBWINDOWS 64 + +Plot2dGroup * target = NULL; + +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); + glBegin(GL_LINES); + + for (double i = from; i < to; i += step) { + Scalar current = fun(i); + Scalar next = fun(i + step); + + if (current.valid) { + glVertex2f(i, current.v); + glVertex2f(i + step, next.v); + } + } + + glEnd(); +} + +void draw_axis() { + glColor3f(1, 1, 1); + glLineWidth(2); + glBegin(GL_LINES); + + glVertex2f(0, 0); + glVertex2f(1, 0); + glVertex2f(0, 0); + glVertex2f(0, 1); + + glVertex2f(1, 0); + glVertex2f(0.9, 0.1); + glVertex2f(1, 0); + glVertex2f(0.9, -0.1); + + glVertex2f(0, 1); + glVertex2f(0.1, 0.9); + glVertex2f(0, 1); + glVertex2f(-0.1, 0.9); + + glEnd(); +} + +void draw_grid(double from, double to) { + 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 = -yl; i < yl; ++i) { + glVertex2f(from, i); + glVertex2f(to, i); + } + + glEnd(); + + glColor3f(0.5, 0.5, 0.5); + glBegin(GL_LINES); + glVertex2f(from, 0); + glVertex2f(to, 0); + + glVertex2f(0, yl); + glVertex2f(0, -yl); + glEnd(); + + glColor3f(0.7, 0.7, 0.7); + glBegin(GL_LINE_LOOP); + glVertex2f(from, yl); + glVertex2f(to, yl); + glVertex2f(to, -yl); + glVertex2f(from, -yl); + glEnd(); +} + +static void update() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + int window = glutGetWindow(); + int plot_id = 0; + + while (subwindows[plot_id] != window) ++plot_id; + + Plot2d * plot = &(target->plots[plot_id]); + + 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); + + glTranslatef(-translate, 0, 0); + glScalef(1/zoom, 1/zoom, 1/zoom); + + glutSwapBuffers(); +} + +static void parent_update() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glutSwapBuffers(); + + int width = glutGet(GLUT_WINDOW_WIDTH); + int height = glutGet(GLUT_WINDOW_HEIGHT); + int min = width > height ? height : width; + + unsigned n_plots = ((unsigned)sqrt(target->n)); + + int plot_dim = min / (int)n_plots - (int)target->padding / 4; + + plot_dim = plot < 0 ? 1 : plot_dim; + + for (unsigned i = 0; i < SUBWINDOWS && subwindows[i] > 0; ++i) { + glutSetWindow(subwindows[i]); + glutReshapeWindow( + plot_dim - target->padding / 2, + plot_dim - target->padding / 2 + ); + glutPositionWindow( + (i % n_plots) * plot_dim + target->padding / 2, + (i / n_plots) * plot_dim + target->padding / 2 + ); + } +} + +void plot(Plot2dGroup * group) { + target = group; + + char * arg[1] = { "" }; + int argc = 1; + + glutInit(&argc, arg); + glutInitWindowSize(500, 500); + glutSetOption(GLUT_MULTISAMPLE, 8); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + int parent = glutCreateWindow("GRAGL"); + + for (int i = 0; i < group->n; ++i) { + int id = glutCreateSubWindow(parent, 1, 1, 1, 1); + subwindows[i] = id; + glutSetWindow(id); + glutDisplayFunc(update); + } + + glutSetWindow(parent); + glutDisplayFunc(parent_update); + + enable_multi_sample(); + + glutMainLoop(); +} + +Plot2dGroup * create_plot2d_group(int num_args, ...) { + Plot2dGroup * group = (Plot2dGroup*)malloc(sizeof(Plot2dGroup)); + group->plots = (Plot2d*)malloc(sizeof(Plot2d) * num_args); + + group->n = num_args; + group->padding = 20; + + va_list ap; + va_start(ap, num_args); + + for (int i = 0; i < num_args; ++i) { + group->plots[i] = va_arg(ap, Plot2d); + } + va_end(ap); + + return group; +} + +void free_plot2d_group(Plot2dGroup * group) { + free(group->plots); + free(group); +} |