aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNPScript <nathan@reinerweb.ch>2022-08-18 17:04:05 +0200
committerNPScript <nathan@reinerweb.ch>2022-08-18 17:04:05 +0200
commit95361c8c2229840a5e05f49622be629cf654371d (patch)
tree280a6d7706b349563959852057e1741f846d5f60
first sketch
-rw-r--r--.gitignore2
-rw-r--r--Makefile21
-rw-r--r--example.c74
-rw-r--r--gragl.c198
-rw-r--r--gragl.h34
-rw-r--r--opengl.c138
6 files changed, 467 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..25064ae
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+example
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..43348e3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CC=gcc
+LDFLAGS=-lGL -lglut -lGLU -lm
+CFLAGS=
+SRC=gragl.c
+OBJ=${SRC:.c=.o}
+
+default_target: all
+
+.c.o:
+ ${CC} ${CFLAGS} -c $<
+
+example: example.c
+ ${CC} -o $@ ${LDFLAGS} example.c ${OBJ}
+
+all: ${OBJ} example
+
+clean:
+ -rm *.o example
+
+run: all
+ ./example
diff --git a/example.c b/example.c
new file mode 100644
index 0000000..af16110
--- /dev/null
+++ b/example.c
@@ -0,0 +1,74 @@
+#include <math.h>
+#include <stdio.h>
+
+#define PI 3.141592653
+
+#include "gragl.h"
+
+Scalar sin_scalar(double x) {
+ Scalar y = {
+ .v = sin(x),
+ .valid = 1
+ };
+
+ return y;
+}
+
+Scalar cos_scalar(double x) {
+ Scalar y = {
+ .v = cos(x),
+ .valid = 1
+ };
+
+ return y;
+}
+
+Scalar tan_scalar(double x) {
+ Scalar y = {
+ .v = tan(x),
+ .valid = 1
+ };
+
+ return y;
+}
+
+Scalar sincos_scalar(double x) {
+ Scalar y = {
+ .v = sin(x) * cos(x) * cos(x) * cos(x) * x,
+ .valid = 1
+ };
+
+ return y;
+}
+
+int main() {
+ Plot2d sin_plot;
+ sin_plot.func = sin_scalar;
+ sin_plot.from = -1;
+ sin_plot.to = 5;
+ sin_plot.step = 0.001;
+
+ Plot2d cos_plot;
+ cos_plot.func = cos_scalar;
+ cos_plot.from = -1;
+ cos_plot.to = 5;
+ cos_plot.step = 0.001;
+
+ Plot2d tan_plot;
+ tan_plot.func = tan_scalar;
+ tan_plot.from = -1;
+ tan_plot.to = 5;
+ tan_plot.step = 0.001;
+
+ Plot2d sincos_plot;
+ sincos_plot.func = sincos_scalar;
+ sincos_plot.from = 0;
+ sincos_plot.to = 100;
+ sincos_plot.step = 0.01;
+
+ Plot2dGroup * group = create_plot2d_group(4, sin_plot, cos_plot, tan_plot, sincos_plot);
+ plot(group);
+ free_plot2d_group(group);
+
+ return 0;
+}
diff --git a/gragl.c b/gragl.c
new file mode 100644
index 0000000..430b581
--- /dev/null
+++ b/gragl.c
@@ -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);
+}
diff --git a/gragl.h b/gragl.h
new file mode 100644
index 0000000..6c6c8a7
--- /dev/null
+++ b/gragl.h
@@ -0,0 +1,34 @@
+#ifndef GRAGL_H
+#define GRAGL_H
+
+typedef struct {
+ double x;
+ double y;
+} Point2d;
+
+typedef struct {
+ double v;
+ char valid;
+} Scalar;
+
+typedef struct {
+ unsigned width;
+ unsigned height;
+ Scalar (*func)(double);
+ unsigned n_func;
+ double from;
+ double to;
+ double step;
+} Plot2d;
+
+typedef struct {
+ Plot2d * plots;
+ unsigned n;
+ unsigned padding;
+} Plot2dGroup;
+
+Plot2dGroup * create_plot2d_group(int num_args, ...);
+void free_plot2d_group(Plot2dGroup *);
+void plot(Plot2dGroup *);
+
+#endif
diff --git a/opengl.c b/opengl.c
new file mode 100644
index 0000000..2b0b70c
--- /dev/null
+++ b/opengl.c
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <math.h>
+
+#include <GL/freeglut.h>
+
+void draw_axis() {
+ glColor3f(1, 1, 1);
+ 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() {
+ glColor3f(0.2, 0.2, 0.2);
+
+ glBegin(GL_LINES);
+
+ for (int i = -10; i < 10; ++i) {
+ glVertex2f(i, -10);
+ glVertex2f(i, 10);
+ }
+
+ for (int i = -10; i < 10; ++i) {
+ glVertex2f(-10, i);
+ glVertex2f(10, i);
+ }
+
+ glEnd();
+
+ glColor3f(0.5, 0.5, 0.5);
+
+ glBegin(GL_LINES);
+
+ glVertex2f(-10, 0);
+ glVertex2f(10, 0);
+
+ glVertex2f(0, -10);
+ glVertex2f(0, 10);
+
+ glEnd();
+}
+
+void draw_function(double from, double to, double step, double(*fun)(double)) {
+ glColor3f(0.9f, 0.5f, 0.2f);
+ glLineWidth(2);
+ glBegin(GL_LINES);
+
+ for (float i = from; i < to; i += step) {
+ double current = fun(i);
+ double next = fun(i + step);
+
+ glVertex2f(i, current);
+ glVertex2f(i + step, next);
+ }
+
+ glEnd();
+}
+
+double tp(double x, double a, double b, double c, double d) {
+ return a * x * x * x + b * x * x + c * x + d;
+}
+
+double example_function(double x) {
+ return tp(x, 1, 5, 5, -1);
+}
+
+static void display(void) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+ draw_grid();
+ draw_axis();
+ draw_function(-10, 10, 0.01, &example_function);
+
+ glutSwapBuffers();
+}
+
+static void keyboard(unsigned char key, int x, int y) {
+ printf("Pressed %c key\n", key);
+ if(key == 'q') {
+ exit(0);
+ }
+}
+
+void enableMultisample(int msaa) {
+ if (msaa) {
+ glEnable(GL_MULTISAMPLE);
+ glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
+
+ // detect current settings
+ GLint iMultiSample = 0;
+ GLint iNumSamples = 0;
+ glGetIntegerv(GL_SAMPLE_BUFFERS, &iMultiSample);
+ glGetIntegerv(GL_SAMPLES, &iNumSamples);
+ printf("MSAA on, GL_SAMPLE_BUFFERS = %d, GL_SAMPLES = %d\n", iMultiSample, iNumSamples);
+ } else {
+ glDisable(GL_MULTISAMPLE);
+ printf("MSAA off\n");
+ }
+}
+
+int main(int argc, char **argv) {
+ glutInit(&argc, argv);
+ glutInitWindowSize(600, 600);
+ glutSetOption(GLUT_MULTISAMPLE, 8);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
+ glutCreateWindow("cme");
+
+ enableMultisample(1);
+
+ printf("OpenGL version = %s\n", glGetString(GL_VERSION));
+
+ glutDisplayFunc(display);
+ glutKeyboardFunc(keyboard);
+
+ glScalef(0.1, 0.1, 0.1);
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+
+
+ glutMainLoop();
+}