aboutsummaryrefslogtreecommitdiff
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
parent0dca2c3e51c98dfa9e62cddd32cadbf6c7f71a3d (diff)
add interactivity and shared libHEADv0.0.1master
-rw-r--r--Makefile13
-rw-r--r--example.c43
-rw-r--r--gragl.c172
-rw-r--r--gragl.h46
-rw-r--r--gragl.pc9
-rw-r--r--opengl.c138
6 files changed, 203 insertions, 218 deletions
diff --git a/Makefile b/Makefile
index 43348e3..3a83189 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
+PREFIX=/usr
CC=gcc
LDFLAGS=-lGL -lglut -lGLU -lm
CFLAGS=
@@ -9,13 +10,21 @@ default_target: all
.c.o:
${CC} ${CFLAGS} -c $<
-example: example.c
+example: example.c ${OBJ}
${CC} -o $@ ${LDFLAGS} example.c ${OBJ}
all: ${OBJ} example
clean:
- -rm *.o example
+ -rm *.o example libgragl.so
run: all
./example
+
+libgragl.so: ${OBJ}
+ gcc -shared ${OBJ} -o $@
+
+install: libgragl.so
+ install libgragl.so ${PREFIX}/lib/
+ install gragl.h ${PREFIX}/include/
+ install gragl.pc ${PREFIX}/share/pkgconfig/
diff --git a/example.c b/example.c
index af16110..ca9afa2 100644
--- a/example.c
+++ b/example.c
@@ -42,31 +42,24 @@ Scalar sincos_scalar(double x) {
}
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);
+ Function group1[] = {
+ FUNC_AUTO(sin_scalar),
+ FUNC_AUTO(cos_scalar),
+ };
+
+ Function group2[] = {
+ FUNC_AUTO(tan_scalar),
+ };
+
+ Function group3[] = {
+ FUNC_AUTO(sincos_scalar),
+ };
+
+ Plot2d plot1 = PLOT_AUTO(group1);
+ Plot2d plot2 = PLOT_AUTO(group2);
+ Plot2d plot3 = PLOT_AUTO(group3);
+
+ Plot2dGroup * group = create_plot2d_group(4, plot1, plot2, plot3);
plot(group);
free_plot2d_group(group);
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();
diff --git a/gragl.h b/gragl.h
index 6c6c8a7..b0082cb 100644
--- a/gragl.h
+++ b/gragl.h
@@ -1,6 +1,35 @@
#ifndef GRAGL_H
#define GRAGL_H
+#include <stdint.h>
+
+typedef float ConstColor[];
+typedef float *Color;
+
+#define PLOT_AUTO(plot) { .function = plot, .nfuncs = sizeof(plot) / sizeof(Function), .x = 3, .y = 0, .rsize = 5, .step = 0.001 }
+#define FUNC_AUTO(f) { .func = f, .color = AUTO_COLORS[(auto_color_index = (auto_color_index + 1) % 5)], .width = 3 }
+
+static ConstColor COLOR_RED = { 0.800f, 0.140f, 0.120f, 1.0f };
+static ConstColor COLOR_GREEN = { 0.596f, 0.592f, 0.102f, 1.0f };
+static ConstColor COLOR_YELLOW = { 0.843f, 0.600f, 0.129f, 1.0f };
+static ConstColor COLOR_BLUE = { 0.271f, 0.522f, 0.533f, 1.0f };
+static ConstColor COLOR_PURPLE = { 0.694f, 0.384f, 0.525f, 1.0f };
+static ConstColor COLOR_AQUA = { 0.408f, 0.616f, 0.416f, 1.0f };
+static ConstColor COLOR_BLACK = { 0.157f, 0.157f, 0.157f, 1.0f };
+static ConstColor COLOR_DARKER = { 0.114f, 0.125f, 0.129f, 1.0f };
+static ConstColor COLOR_WHITE = { 0.922f, 0.859f, 0.698f, 1.0f };
+static ConstColor COLOR_GRAY = { 0.659f, 0.600f, 0.518f, 1.0f };
+
+static unsigned auto_color_index = 0;
+static Color AUTO_COLORS[] = {
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_YELLOW,
+ COLOR_BLUE,
+ COLOR_PURPLE,
+ COLOR_AQUA
+};
+
typedef struct {
double x;
double y;
@@ -8,17 +37,24 @@ typedef struct {
typedef struct {
double v;
- char valid;
+ uint8_t valid;
} Scalar;
typedef struct {
+ Scalar (*func)(double);
+ Color color;
+ double width;
+} Function;
+
+typedef struct {
unsigned width;
unsigned height;
- Scalar (*func)(double);
- unsigned n_func;
- double from;
- double to;
+ double x;
+ double y;
+ double rsize;
double step;
+ Function *function;
+ unsigned nfuncs;
} Plot2d;
typedef struct {
diff --git a/gragl.pc b/gragl.pc
new file mode 100644
index 0000000..6608d33
--- /dev/null
+++ b/gragl.pc
@@ -0,0 +1,9 @@
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: GraGL
+Description: Math Function Rendering Engine
+Version: 0.0.1
+Libs: -lGL -lGLU -lglut -lm -lgragl
diff --git a/opengl.c b/opengl.c
deleted file mode 100644
index 2b0b70c..0000000
--- a/opengl.c
+++ /dev/null
@@ -1,138 +0,0 @@
-#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();
-}