From 95361c8c2229840a5e05f49622be629cf654371d Mon Sep 17 00:00:00 2001 From: NPScript Date: Thu, 18 Aug 2022 17:04:05 +0200 Subject: first sketch --- .gitignore | 2 + Makefile | 21 +++++++ example.c | 74 +++++++++++++++++++++++ gragl.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gragl.h | 34 +++++++++++ opengl.c | 138 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 467 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 example.c create mode 100644 gragl.c create mode 100644 gragl.h create mode 100644 opengl.c 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 +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#include + +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(); +} -- cgit v1.2.3-70-g09d2