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 | |
parent | 0dca2c3e51c98dfa9e62cddd32cadbf6c7f71a3d (diff) |
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | example.c | 43 | ||||
-rw-r--r-- | gragl.c | 172 | ||||
-rw-r--r-- | gragl.h | 46 | ||||
-rw-r--r-- | gragl.pc | 9 | ||||
-rw-r--r-- | opengl.c | 138 |
6 files changed, 203 insertions, 218 deletions
@@ -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/ @@ -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); @@ -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(); @@ -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(); -} |