From 9325a7cb6faf9b7616658f172636b4d90fe5b144 Mon Sep 17 00:00:00 2001 From: Adrien 'neox' Bourmault Date: Tue, 19 Dec 2023 21:46:51 +0100 Subject: [PATCH] WIP: total rewrite graphic stack allocation --- include/arrows.h | 45 -- include/base.h | 12 + include/displays.h | 83 --- include/graphics.h | 157 ++++-- include/grid.h | 49 -- include/shaders_study.h | 110 ---- src/graphics/arrows.c | 226 +++++++- src/graphics/displays.c | 4 - src/graphics/draw.c | 186 +++++++ src/graphics/graphics.c | 726 +++---------------------- src/graphics/grid.c | 132 ++--- src/graphics/init.c | 175 ++++++ src/{ => graphics}/shaders/shader.frag | 0 src/{ => graphics}/shaders/shader.vert | 0 src/ui/graphics.c | 2 + 15 files changed, 851 insertions(+), 1056 deletions(-) delete mode 100644 include/arrows.h delete mode 100644 include/displays.h delete mode 100644 include/grid.h delete mode 100644 include/shaders_study.h create mode 100644 src/graphics/draw.c create mode 100644 src/graphics/init.c rename src/{ => graphics}/shaders/shader.frag (100%) rename src/{ => graphics}/shaders/shader.vert (100%) diff --git a/include/arrows.h b/include/arrows.h deleted file mode 100644 index 2b54c9f..0000000 --- a/include/arrows.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Gem-graph OpenGL experiments - * - * Desc: OpenGL utils header - * - * Copyright (C) 2023 Jean Sirmai - * Copyright (C) 2023 Adrien Bourmault - * - * This file is part of Gem-graph. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#pragma once -#include -#include -#include - -/* - * Structure describing an arrow - */ -typedef struct arrow_t { - GLuint load; - GLuint site; - GLuint x; - GLuint y; - GLuint z; -}; - -int draw_one_arrow_vertex (int space_X, int space_Y, int space_Z, - int weight, int site, int x, int y, int z, int print); - -int draw_one_arrow_line(int offset_vertex, int print); - diff --git a/include/base.h b/include/base.h index 3b7a243..1d4dcb6 100644 --- a/include/base.h +++ b/include/base.h @@ -37,6 +37,7 @@ #include #define G_APPLICATION_DEFAULT_FLAGS 0 +// Graphical axis enum { X_AXIS, @@ -46,6 +47,17 @@ enum N_AXIS }; +// Gem-graph modes +enum +{ + HOME_MODE, + RUN_MODE, + EDIT_MODE, + PRESENTATION_MODE, + + N_MODE +}; + /* * Read a file from filename into a provided buffer * diff --git a/include/displays.h b/include/displays.h deleted file mode 100644 index a9c15c6..0000000 --- a/include/displays.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Gem-graph OpenGL experiments - * - * Desc: GL functions - * - * Copyright (C) 2023 Adrien Bourmault - * Copyright (C) 2023 Jean Sirmai - * - * This file is part of Gem-graph. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include - - -/* - * Prints the arrows[] array - * - * For each arrow the following parameters are displayed : - * - rank in the array - * - weight (or load) - * - coordinates in space (site, x, y, z) - */ -void show_arrows_array_head(int one_batch_size, long nb_batches_specified, int verbose); -void show_one_arrow_in_array(struct arrow_t *arrows, int i); -void show_empty_arrows_array(); -void show_arrows_array (struct arrow_t *arrows, int arrows_nb, int x, int y, int z); -void print_arrows_array (struct arrow_t *arrows, int arrows_nb, int invoked_by); -void print_user_action(struct arrow_t *arrows, int arrows_nb, int address, int requested_weight, - int current_weight, int site, int x, int y, int z); -void print_user_choices(struct arrow_t *arrows, int max_arrows_nb, int arrows_nb, - int space_size_x, int space_size_y, int space_size_z, - int show_array, int show_space_design); -void print_evolution (struct arrow_t *arrows, int arrows_nb, int modified, int deleted, int show_array); -/* - * Prints the initial user choices : - * - space dimension size and appearance (grids) - * - arrows[] array - * NB The space may be empty or saturated with arrows or any value in between - * To assert : Only one arrow per possible coordinates with a load max equal to ? - */ -void show_user_choices(long copy_nb_arrows_specified, - int space_size_x, int space_size_y, int space_size_z, - int prefer, int arbitrary, int one_batch_size); - - -/* - * Prints the result of the function set_arrow() - * and indicates the reasons of the choice (call) this function makes (see this function) - */ -void show_user_action(struct arrow_t *arrows, int arrows_nb, int address, int requested_weight, - int current_weight, int site, int x, int y, int z); - - - -/* - * Prints vertex and lines buffers_states (sizes) at major one_batch_sizes and at the end of a session. - * Major one_batch_sizes are creation of grids and creation of arrows - * Arithmetic verification is provided at each one_batch_size - */ -void show_buffers_states(int space_X, int space_Y, int space_Z, - long nb_batches_specified, int one_batch_size, - int offset_after_grids, int buffer_vertex_size, - int buffer_lines_size_after_cubes, int buffer_lines_size); - -void print_vertex_and_lines_buffers (struct arrow_t *arrows_ptr, int arrows_nb, - GLfloat *buffer_vertex_origin, long buffer_vertex_0_arrow, - GLfloat *buffer_lines_origin, long buffer_lines_0_arrow, - int address, int requested_weight, int current_weight, int site, int x, int y, int z); - diff --git a/include/graphics.h b/include/graphics.h index b234bad..6e23bff 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -31,12 +31,19 @@ #include #include +#define VERTEX_SHADER_FILE "src/graphics/shaders/shader.vert" +#define FRAG_SHADER_FILE "src/graphics/shaders/shader.frag" + /* * Structure describing a gl_area and its parameters, used to create a table * of Gem-graph client current gl_areas */ -struct gl_area_entry { - char name[16]; +struct graphic_stack_t { + + int id; + int mode; + void *glarea; + GLuint vao; // init_buffers GLuint position_buffer; // shutdown, draw GLuint color_buffer; // shutdown, draw @@ -44,17 +51,30 @@ struct gl_area_entry { GLuint m; // init_shaders, draw GLuint v; // init_shaders, draw GLuint p; // init_shaders, draw + + struct arrow_t *arrows_ptr; + long arrows_nb; + + GLfloat *buffer_vertex_origin; + GLfloat *buffer_colors_origin; + GLuint *buffer_lines_origin; + GLuint *buffer_plans_origin; + + long buffer_vertex_size; + long buffer_colors_size; + long buffer_lines_size; + long buffer_plans_size; + + long buffer_vertex_0_arrow; + long buffer_colors_0_arrow; + long buffer_lines_0_arrow; + long buffer_plans_0_arrow; }; /* - * Find gl_area_entry from a gl_area ptr - * - * @param gl_area, ptr to the gl_area widget - * - * - * @return entry ptr + * Dynamic array of ptrs to dynamically allocated gl_area_entry */ -struct gl_area_entry *graphics_find_glarea_from_ptr(const char *name); +extern struct graphic_stack_t *graphic_stack; /* * Initializes a gl_area @@ -63,7 +83,7 @@ struct gl_area_entry *graphics_find_glarea_from_ptr(const char *name); * * @return true if initialized */ -bool graphics_init(const char *gl_area); +int graphics_init(void *glarea); /* * Draws the current buffer to a gl_area @@ -72,7 +92,7 @@ bool graphics_init(const char *gl_area); * * @return void */ -void graphics_draw(const void *gl_area); +void graphics_draw(const int stack_id); /* * Shutdowns a gl_area @@ -81,7 +101,7 @@ void graphics_draw(const void *gl_area); * * @return true if success */ -bool graphics_shutdown(const void *gl_area); +bool graphics_shutdown(const int stack_id); /* * Initializes the shaders of a gl_area and link them to a program @@ -90,14 +110,14 @@ bool graphics_shutdown(const void *gl_area); * * @return true if initialized */ -bool graphics_init_shaders(const void *gl_area); +bool graphics_init_shaders(const int stack_id); /* Initializes the buffer of a gl_area * Calls according to the user preferences * @param gl_area, ptr to the gl_area widget * @return void */ -void graphics_init_buffers(const void *gl_area); +void graphics_init_buffers(const int stack_id); /* * Draws a vertex (x, y, z) @@ -107,7 +127,10 @@ void graphics_init_buffers(const void *gl_area); * * @return void */ -void graphics_draw_vertex (GLfloat x, GLfloat y, GLfloat z, int console); +void graphics_draw_vertex (const int stack_id, + GLfloat x, + GLfloat y, + GLfloat z); /* * Draws the color (r, g, b) associated to a vertex @@ -117,7 +140,7 @@ void graphics_draw_vertex (GLfloat x, GLfloat y, GLfloat z, int console); * * @return void */ -void graphics_draw_color (GLfloat r, GLfloat g, GLfloat b, int console); +void graphics_draw_color (const int stack_id, GLfloat r, GLfloat g, GLfloat b); /* * Writes values to describe a line from a to b into the line buffer @@ -126,7 +149,7 @@ void graphics_draw_color (GLfloat r, GLfloat g, GLfloat b, int console); * * @return void */ -void graphics_draw_line (GLuint a, GLuint b, int console); +void graphics_draw_line (const int stack_id, GLuint a, GLuint b); /* * Writes values to describe an (a,b,c) plan (triangle) into the plan buffer @@ -135,7 +158,7 @@ void graphics_draw_line (GLuint a, GLuint b, int console); * * @return void */ -void graphics_draw_plan (GLuint a, GLuint b, GLuint c, int console); +void graphics_draw_plan (const int stack_id, GLuint a, GLuint b, GLuint c); /* * Initializes an identity matrix @@ -206,7 +229,7 @@ static inline void compute_mvp(float *res, float phi, float theta, float psi) * * @return shader id */ -static inline GLuint create_shader(int type, const char *src) +static inline GLuint create_shader(const int stack_id, int type, const char *src) { GLuint shader; int status; @@ -240,31 +263,75 @@ static inline GLuint create_shader(int type, const char *src) return shader; } -/* - * Find the gl_area_entry size - * - * @param void - * - * @return size of array - */ -extern struct gl_area_entry **gl_area_array; -static inline short gl_area_size(void) -{ - struct gl_area_entry **cur; - short size; - - // Check uninitialized and quit - if (gl_area_array == NULL) return 0; - - cur = gl_area_array; - while(*cur) { - cur++; - size++; - } - - return size; -} - /*** TEST ***/ -void main_test_graphics (void); +void main_test_graphics (const int stack_id); + +/* + * Structure describing an arrow + */ +struct arrow_t { + GLuint load; + GLuint site; + GLuint x; + GLuint y; + GLuint z; +}; + +int draw_one_arrow_vertex (const int stack_id, + int space_X, + int space_Y, + int space_Z, + int weight, + int site, + int x, + int y, + int z); + +int draw_one_arrow_line(const int stack_id, + int offset_vertex); + +/* + * Writes grid ridges to vertex and color buffers + * + * @param coords long (x,y,z), step_x, step_y, step_z + * + * @return void + */ +int draw_space_ridges_vertex (const int stack_id, + long offset_vertex, + long x, + long y, + long z); + +int draw_space_ridges_lines (const int stack_id); + +/* + * Writes grid lines on space faces + * + * @param coords long (x,y,z) + * + * @return void + */ +long draw_grids_on_space_faces_vertex (const int stack_id, + long x, + long y, + long z); + +long draw_grids_on_space_faces_lines (const int stack_id, + long offset_vertex, + long x, + long y, + long z); + +int set_arrow (int stack_id, + int arrows_nb, + int space_X, + int space_Y, + int space_Z, + int requested_weight, + int site, + int arrow_x, + int arrow_y, + int arrow_z); + diff --git a/include/grid.h b/include/grid.h deleted file mode 100644 index 78c94ea..0000000 --- a/include/grid.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Gem-graph OpenGL experiments - * - * Desc: OpenGL utils header - * - * Copyright (C) 2023 Adrien Bourmault - * Copyright (C) 2023 Jean Sirmai - * - * This file is part of Gem-graph. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#pragma once -#include -#include -#include - -/* - * Writes grid ridges to vertex and color buffers - * - * @param coords long (x,y,z), step_x, step_y, step_z - * - * @return void - */ -int draw_space_ridges_vertex (long offset_vertex, long x, long y, long z, int console); -int draw_space_ridges_lines (int console); - -/* - * Writes grid lines on space faces - * - * @param coords long (x,y,z) - * - * @return void - */ -long draw_grids_on_space_faces_vertex (long x, long y, long z, int console); -long draw_grids_on_space_faces_lines (long offset_vertex, long x, long y, long z, int console); - diff --git a/include/shaders_study.h b/include/shaders_study.h deleted file mode 100644 index 7e85d82..0000000 --- a/include/shaders_study.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Gem-graph OpenGL experiments - * - * Desc: OpenGL utils header - * - * Copyright (C) 2023 Jean Sirmai - * - * This file is part of Gem-graph. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#pragma once -#include "base.h" -#include -#include -#include -#include -#include - -/* - * Initializes the shaders of a gl_area and link them to a program - * - * @param gl_area, ptr to the gl_area widget - * - * @return true if initialized - */ -bool graphics_init_shaders(const void *gl_area); - -/* - * Created and compile a shader - * - * @param type, shader type - * src, source code of shader - * - * @return shader id - */ -static inline GLuint create_shader(int type, const char *src) -{ - GLuint shader; - int status; - - shader = glCreateShader(type); - glShaderSource(shader, 1, &src, NULL); - glCompileShader(shader); - - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if(status == GL_FALSE) { - int log_len; - char *buffer; - - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len); - - buffer = g_malloc(log_len + 1); - assert (buffer); - glGetShaderInfoLog(shader, log_len, NULL, buffer); - - g_warning("Compile failure in %s shader:\n%s", - type == GL_VERTEX_SHADER ? "vertex" : "fragment", - buffer); - - g_free(buffer); - - glDeleteShader(shader); - - return 0; - } - - return shader; -} - -/* - * Find the gl_area_entry size - * - * @param void - * - * @return size of array - */ -// extern struct gl_area_entry **gl_area_array; -// static inline short gl_area_size(void) -// { -// struct gl_area_entry **cur; -// short size; - - // Check uninitialized and quit -// if (gl_area_array == NULL) return 0; - -// cur = gl_area_array; -// while(*cur) { -// cur++; -// size++; -// } - -// return size; -// } - -/*** TEST ***/ - -// void main_test_graphics (void); diff --git a/src/graphics/arrows.c b/src/graphics/arrows.c index dd55e9d..f5fa798 100644 --- a/src/graphics/arrows.c +++ b/src/graphics/arrows.c @@ -33,8 +33,15 @@ * Z - Z = NORTH - SOUTH = bleu - jaune */ -int draw_one_arrow_vertex (int space_X_int, int space_Y_int, int space_Z_int, - int weight, int site, int arrow_x, int arrow_y, int arrow_z, int console) +int draw_one_arrow_vertex (const int stack_id, + int space_X_int, + int space_Y_int, + int space_Z_int, + int weight, + int site, + int arrow_x, + int arrow_y, + int arrow_z) { float max = fmax(space_X_int, space_Y_int); @@ -46,8 +53,8 @@ int draw_one_arrow_vertex (int space_X_int, int space_Y_int, int space_Z_int, vy = (2 * j / space_Y_int - 1) * space_Y_int / max + (1 / max), vz = (2 * k / space_Z_int - 1) * space_Z_int / max + (1 / max); - graphics_draw_vertex(vx, vy, vz, console); - graphics_draw_color(0.4f, 0.4f, 0.4f, console); + graphics_draw_vertex(stack_id, vx, vy, vz); + graphics_draw_color(stack_id, 0.4f, 0.4f, 0.4f); // réduit légèrement les longueurs des flèches // pour qu'elles s'arrêtent avant les faces des cubes @@ -55,28 +62,28 @@ int draw_one_arrow_vertex (int space_X_int, int space_Y_int, int space_Z_int, switch(site){ case EAST: - graphics_draw_vertex (vx - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vy, vz, console); - graphics_draw_color (1.0f, 0.0f, 0.0f, console); + graphics_draw_vertex (stack_id, vx - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vy, vz); + graphics_draw_color (stack_id, 1.0f, 0.0f, 0.0f); break; case WEST: - graphics_draw_vertex (vx - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vy, vz, console); - graphics_draw_color (0.0f, 1.0f, 1.0f, console); + graphics_draw_vertex (stack_id, vx - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vy, vz); + graphics_draw_color (stack_id, 0.0f, 1.0f, 1.0f); break; case ZENITH: - graphics_draw_vertex (vx, vy - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vz, console); - graphics_draw_color(0.0f, 0.6f, 0.1f, console); + graphics_draw_vertex (stack_id, vx, vy - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vz); + graphics_draw_color(stack_id, 0.0f, 0.6f, 0.1f); break; case NADIR: - graphics_draw_vertex (vx, vy - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vz, console); - graphics_draw_color(0.6f, 0.1f, 0.7f, console); + graphics_draw_vertex (stack_id, vx, vy - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vz); + graphics_draw_color(stack_id, 0.6f, 0.1f, 0.7f); break; case SOUTH: - graphics_draw_vertex (vx, vy, vz - (site % 2 + 1) * (1 / max) + (site % 2 + 1) * arrow_tip_padding, console); - graphics_draw_color(0.05f, 0.4f, 1.0f, console); + graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 + 1) * (1 / max) + (site % 2 + 1) * arrow_tip_padding); + graphics_draw_color(stack_id, 0.05f, 0.4f, 1.0f); break; case NORTH: - graphics_draw_vertex (vx, vy, vz - (site % 2 - 2) * (1 / max) + (site % 2 - 2) * arrow_tip_padding, console); - graphics_draw_color(1.0f, 1.0f, 0.0f, console); + graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 - 2) * (1 / max) + (site % 2 - 2) * arrow_tip_padding); + graphics_draw_color(stack_id, 1.0f, 1.0f, 0.0f); break; default: break; } @@ -85,8 +92,191 @@ int draw_one_arrow_vertex (int space_X_int, int space_Y_int, int space_Z_int, } -int draw_one_arrow_line(int offset_vertex, int print) +int draw_one_arrow_line(const int stack_id, int offset_vertex) { - graphics_draw_line (offset_vertex + 0, offset_vertex + 1, print); + graphics_draw_line (stack_id, offset_vertex + 0, offset_vertex + 1); return 2; } + + +/* + * Depends on set_arrow() + * Exchanges current and required site values + * when the address of the arrow to be set is already occupied + */ +static int rewrite_arrow (const int stack_id, + int address, + int load, + int site, + int x, + int y, + int z) +{ + printf("WARNING in rewrite_arrow() <> address or address / 5 ? (et pourquoi ?)\n"); + graphic_stack[stack_id].arrows_ptr[address].load = load; + return 1; +} + +/* + * Depends on set_arrow() + * Creates the arrow to be set with the required load at the required address + */ +static inline int create_arrow (int stack_id, + int arrows_nb, + int space_X, + int space_Y, + int space_Z, + int load, + int site, + int x, + int y, + int z) +{ + void *newptr = g_realloc(graphic_stack[stack_id].arrows_ptr, (arrows_nb + 1) * sizeof(struct arrow_t)); + + if (newptr) + graphic_stack[stack_id].arrows_ptr = newptr; + else + perror("In create arrow, can't allocate new arrow buffer !\n"); + + graphic_stack[stack_id].arrows_ptr[arrows_nb].load = load; + graphic_stack[stack_id].arrows_ptr[arrows_nb].site = site; + graphic_stack[stack_id].arrows_ptr[arrows_nb].x = x; + graphic_stack[stack_id].arrows_ptr[arrows_nb].y = y; + graphic_stack[stack_id].arrows_ptr[arrows_nb].z = z; + + draw_one_arrow_vertex(stack_id, space_X, space_Y, space_Z, load, site, x, y, z); + draw_one_arrow_line (stack_id, graphic_stack[stack_id].buffer_vertex_size / 3 - 2); + + arrows_nb ++; + + return arrows_nb; +} + +/* + * Depends on set_arrow() + * Erases the arrow at the required address + */ +static inline int erase_arrow (const int stack_id, + int arrows_nb, + int arrow_address_in_list, + GLuint site, + GLint x, + GLint y, + GLint z) +{ + if (arrows_nb == 0) assert (graphic_stack[stack_id].buffer_lines_size == + graphic_stack[stack_id].buffer_lines_0_arrow); + if (arrows_nb == 0) { + graphic_stack[stack_id].buffer_lines_size = + graphic_stack[stack_id].buffer_lines_0_arrow; + return 0; + } + + assert (arrows_nb); + arrows_nb --; + + if (arrow_address_in_list < arrows_nb) + { + graphic_stack[stack_id].arrows_ptr[arrow_address_in_list].load = + graphic_stack[stack_id].arrows_ptr[arrows_nb].load; + graphic_stack[stack_id].arrows_ptr[arrow_address_in_list].site = + graphic_stack[stack_id].arrows_ptr[arrows_nb].site; + graphic_stack[stack_id].arrows_ptr[arrow_address_in_list].x = + graphic_stack[stack_id].arrows_ptr[arrows_nb].x; + graphic_stack[stack_id].arrows_ptr[arrow_address_in_list].y = + graphic_stack[stack_id].arrows_ptr[arrows_nb].y; + graphic_stack[stack_id].arrows_ptr[arrow_address_in_list].z = + graphic_stack[stack_id].arrows_ptr[arrows_nb].z; + } + + for (long i = 0; i < 6; i++) + graphic_stack[stack_id].buffer_vertex_origin [graphic_stack[stack_id].buffer_vertex_0_arrow + arrow_address_in_list * 6 + i] + = graphic_stack[stack_id].buffer_vertex_origin [graphic_stack[stack_id].buffer_vertex_size - 6 + i]; + + for (long i = 0; i < 6; i++) + graphic_stack[stack_id].buffer_colors_origin [graphic_stack[stack_id].buffer_colors_0_arrow + arrow_address_in_list * 6 + i] + = graphic_stack[stack_id].buffer_colors_origin [graphic_stack[stack_id].buffer_colors_size - 6 + i]; + + graphic_stack[stack_id].buffer_vertex_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_vertex() + graphic_stack[stack_id].buffer_colors_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_colors() + graphic_stack[stack_id].buffer_lines_size -= 2; // <<< l'inverse de ce qui est fait dans : graphics_draw_line() + + void *new_arrows_vertex_ptr = g_realloc(graphic_stack[stack_id].buffer_vertex_origin, graphic_stack[stack_id].buffer_vertex_size * sizeof(GLfloat)); + if (new_arrows_vertex_ptr) graphic_stack[stack_id].buffer_vertex_origin = new_arrows_vertex_ptr; + else perror("In graphics.erase_arrow(), can't re_allocate for arrows vertex buffer.\n"); + + void *new_arrows_colors_ptr = g_realloc(graphic_stack[stack_id].buffer_colors_origin, graphic_stack[stack_id].buffer_colors_size * sizeof(GLfloat)); + if (new_arrows_colors_ptr) graphic_stack[stack_id].buffer_colors_origin = new_arrows_colors_ptr; + else perror("In graphics.erase_arrow(), can't re_allocate for arrows colors buffer.\n"); + + /* Il ne faut pas réécrire ce qui suit: ces lignes dessinent maintenant à partir d'autres vertex */ + /* void *new_arrows_lines_ptr = g_realloc(graphic_stack[stack_id].buffer_lines_origin, graphic_stack[stack_id].buffer_lines_size * sizeof(GLfloat)); */ + /* if (new_arrows_lines_ptr) graphic_stack[stack_id].buffer_lines_origin = new_arrows_lines_ptr; */ + /* else perror("In graphics.erase_arrow(), can't re_allocate for arrows lines buffer.\n"); */ + + return arrows_nb; +} + + + +/* + * Creates or deletes an arrow or modify the load of an existing one + * Acts both by writing the list of arrows : (struct arrow_t *arrows_ptr, int arrows_nb) + * and by drawing in the global space + * + * @param arrows_ptr and arrows_nb before operation, + * required load and address (site, x, y, z) + * + * IF there is no arrow at the required address, + * AND IF the load is > 0, an arrow will be created. + * + * IF there is an arrow at the required address + * AND IF the load is = 0, the existing arrow will be deleted. + * + * IF there is an arrow at the required address + * AND IF the load is > 0, the load of the existing arrow will be modified. + * + * May not call any of these three functions IF : + * - Current_weight of an arrow located at the requested address == requested_weight + * - No arrow was found at the requested addres AND current_weight == requested_weight + * + * @return arrows_nb after operation + */ +int set_arrow (int stack_id, + int arrows_nb, + int space_X, + int space_Y, + int space_Z, + int requested_weight, + int site, + int arrow_x, + int arrow_y, + int arrow_z) +{ + int address = -1, current_weight = -1; + + for (int i = 0; i < arrows_nb; i++) + if ((site == graphic_stack[stack_id].arrows_ptr[i].site) + && (arrow_x == graphic_stack[stack_id].arrows_ptr[i].x) + && (arrow_y == graphic_stack[stack_id].arrows_ptr[i].y) + && (arrow_z == graphic_stack[stack_id].arrows_ptr[i].z)) + { + address = i; + current_weight = graphic_stack[stack_id].arrows_ptr[i].load; + break; + } + assert (address <= arrows_nb); + + if (address == -1 && requested_weight > 0) + return create_arrow (stack_id, arrows_nb, space_X, space_Y, space_Z, requested_weight, site, arrow_x, arrow_y, arrow_z); + if (address >= 0 && requested_weight == 0) // address >= 0 if and only if arrows_nb > 0 + return erase_arrow(stack_id, arrows_nb, address, site, arrow_x, arrow_y, arrow_z); + if (address >= 0 && current_weight != requested_weight) { + rewrite_arrow(stack_id, address, requested_weight, site, arrow_x, arrow_y, arrow_z); + return arrows_nb; + } + + return arrows_nb; +} + diff --git a/src/graphics/displays.c b/src/graphics/displays.c index bdf58f4..fee294c 100644 --- a/src/graphics/displays.c +++ b/src/graphics/displays.c @@ -25,10 +25,6 @@ #include #include #include "../../include/graphics.h" -#include "../../include/arrows.h" -#include "../../include/displays.h" - - /* Prints the arrows[] array * diff --git a/src/graphics/draw.c b/src/graphics/draw.c new file mode 100644 index 0000000..be18de8 --- /dev/null +++ b/src/graphics/draw.c @@ -0,0 +1,186 @@ +/* + * Gem-graph OpenGL experiments + * + * Desc: GL functions + * + * Copyright (C) 2023 Adrien Bourmault + * Copyright (C) 2023 Jean Sirmai + * + * This file is part of Gem-graph. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* + * Writes values to describe a vertex at (x,y,z) intoq the vertex buffer + * + * @param coords GLfloat(x,y,z) + * + * @return void + */ + +#include +#include +#include "../../include/base.h" +#include "../../include/ui.h" +#include "../../include/graphics.h" + +void graphics_draw_vertex (const int stack_id, + GLfloat x, + GLfloat y, + GLfloat z) +{ + graphic_stack[stack_id].buffer_vertex_origin = g_realloc (graphic_stack[stack_id].buffer_vertex_origin, + (graphic_stack[stack_id].buffer_vertex_size + 3) * sizeof(GLfloat)); + + assert (graphic_stack[stack_id].buffer_vertex_origin); + + graphic_stack[stack_id].buffer_vertex_origin[graphic_stack[stack_id].buffer_vertex_size + 0] = x; + graphic_stack[stack_id].buffer_vertex_origin[graphic_stack[stack_id].buffer_vertex_size + 1] = y; + graphic_stack[stack_id].buffer_vertex_origin[graphic_stack[stack_id].buffer_vertex_size + 2] = z; + + graphic_stack[stack_id].buffer_vertex_size += 3; +} + +/* + * Writes values to describe a color (r,g,b) into the color buffer + * + * @param color GLfloat(r,g,b) + * + * @return void + */ +void graphics_draw_color (const int stack_id, + GLfloat r, + GLfloat g, + GLfloat b) +{ + graphic_stack[stack_id].buffer_colors_origin = g_realloc (graphic_stack[stack_id].buffer_colors_origin, + (graphic_stack[stack_id].buffer_colors_size + 3) * sizeof(GLfloat)); + + assert (graphic_stack[stack_id].buffer_colors_origin); + + graphic_stack[stack_id].buffer_colors_origin[graphic_stack[stack_id].buffer_colors_size + 0] = r; + graphic_stack[stack_id].buffer_colors_origin[graphic_stack[stack_id].buffer_colors_size + 1] = g; + graphic_stack[stack_id].buffer_colors_origin[graphic_stack[stack_id].buffer_colors_size + 2] = b; + + graphic_stack[stack_id].buffer_colors_size += 3; +} + +/* + * Writes values to describe a line from a to b into the line buffer + * + * @param coords GLuint (a,b) + * + * @return void + */ +void graphics_draw_line (const int stack_id, + GLuint a, + GLuint b) +{ + graphic_stack[stack_id].buffer_lines_origin = g_realloc (graphic_stack[stack_id].buffer_lines_origin, + (graphic_stack[stack_id].buffer_lines_size + 2) * sizeof(GLuint)); + + assert (graphic_stack[stack_id].buffer_lines_origin); + + graphic_stack[stack_id].buffer_lines_origin[graphic_stack[stack_id].buffer_lines_size + 0] = a; + graphic_stack[stack_id].buffer_lines_origin[graphic_stack[stack_id].buffer_lines_size + 1] = b; + + graphic_stack[stack_id].buffer_lines_size += 2; +} + +/* + * Writes values to describe an (a,b,c) plan (triangle) into the plan buffer + * + * @param coords GLuint (a,b,c) + * + * @return void + */ +void graphics_draw_plan (const int stack_id, + GLuint a, + GLuint b, + GLuint c) +{ + graphic_stack[stack_id].buffer_plans_origin = g_realloc (graphic_stack[stack_id].buffer_plans_origin, + (graphic_stack[stack_id].buffer_plans_size + 3) * sizeof(GLuint)); + + assert (graphic_stack[stack_id].buffer_plans_origin); + + graphic_stack[stack_id].buffer_plans_origin[graphic_stack[stack_id].buffer_plans_size + 0] = a; + graphic_stack[stack_id].buffer_plans_origin[graphic_stack[stack_id].buffer_plans_size + 1] = b; + graphic_stack[stack_id].buffer_plans_origin[graphic_stack[stack_id].buffer_plans_size + 2] = c; + + graphic_stack[stack_id].buffer_plans_size += 3; +} + +/* + * Draws the current buffer to a gl_area + * + * @param gl_area, ptr to the gl_area widget + * + * @return void + */ +void graphics_draw(const int stack_id) +{ + float m[16]; + float v[16]; + float p[16]; + + // XXX TODO get stack from stack_id + + /* Compute the model view projection matrix using the + * rotation angles specified through the GtkRange widgets + */ + compute_mvp(p, + rotation_angles[X_AXIS], + rotation_angles[Y_AXIS], + rotation_angles[Z_AXIS]); + compute_i(m); + compute_i(v); + + /* Use our shaders */ + glUseProgram(graphic_stack[stack_id].program); + +// if (pref_show_space_design_mix_colors == 0) + glClearColor(0, 0, 0, 0.4f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* Update the "mvp" matrix we use in the shader */ + glUniformMatrix4fv(graphic_stack[stack_id].m, 1, GL_FALSE, &m[0]); + glUniformMatrix4fv(graphic_stack[stack_id].v, 1, GL_FALSE, &v[0]); + glUniformMatrix4fv(graphic_stack[stack_id].p, 1, GL_FALSE, &p[0]); + + /* Use the vertices in our buffer */ + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, graphic_stack[stack_id].position_buffer); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,(void*)0); + + // couleurs + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, graphic_stack[stack_id].color_buffer); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0,(void*)0); + + //glEnable(GL_DEPTH_TEST); + + glDrawElements(GL_LINES, graphic_stack[stack_id].buffer_lines_size, GL_UNSIGNED_INT, graphic_stack[stack_id].buffer_lines_origin); + glDrawElements(GL_TRIANGLES, graphic_stack[stack_id].buffer_plans_size, GL_UNSIGNED_INT, graphic_stack[stack_id].buffer_plans_origin); + + /* We finished using the buffers and program */ + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glUseProgram(0); + + glFlush(); +} diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index 7bcde2a..4f64f66 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -28,38 +28,12 @@ #include "../../include/base.h" #include "../../include/ui.h" #include "../../include/graphics.h" -#include "../../include/arrows.h" -#include "../../include/grid.h" -// #include TODO - -#define VERTEX_SHADER_FILE "src/shaders/shader.vert" -#define FRAG_SHADER_FILE "src/shaders/shader.frag" - - - -static struct arrow_t *arrows_ptr; - -GLfloat *buffer_vertex_origin = NULL; -GLfloat *buffer_colors_origin = NULL; -GLuint *buffer_lines_origin = NULL; -GLuint *buffer_plans_origin = NULL; - -volatile long buffer_vertex_size = 0; -volatile long buffer_colors_size = 0; -volatile long buffer_lines_size = 0; -volatile long buffer_plans_size = 0; - -volatile long buffer_vertex_0_arrow = 0; -volatile long buffer_colors_0_arrow = 0; -volatile long buffer_lines_0_arrow = 0; -volatile long buffer_plans_0_arrow = 0; #define TEST 0 -/* - * Dynamic array of ptrs to dynamically allocated gl_area_entry - */ -struct gl_area_entry **gl_area_array = NULL; +size_t graphic_stack_size = 0; +int *free_stack_slot = NULL; +size_t free_stack_slot_size = 0; /* * Prints verbose human-readable debug messages @@ -123,396 +97,54 @@ static void graphics_debug_callback(GLenum source, GLenum type, GLuint id, /* -------------------------------------------------------------------------- */ /* - * Writes values to describe a vertex at (x,y,z) intoq the vertex buffer - * - * @param coords GLfloat(x,y,z) - * - * @return void - */ -void graphics_draw_vertex (GLfloat x, GLfloat y, GLfloat z, int console) -{ - buffer_vertex_origin = g_realloc (buffer_vertex_origin, - (buffer_vertex_size + 3) * sizeof(GLfloat)); - - assert (buffer_vertex_origin); - - buffer_vertex_origin[buffer_vertex_size + 0] = x; - buffer_vertex_origin[buffer_vertex_size + 1] = y; - buffer_vertex_origin[buffer_vertex_size + 2] = z; - - if (console) printf("In graphics_draw_vertex() buffer_vertex_size => [%2ld] [%2ld > %2ld] (%6.3f,%6.3f,%6.3f)\n",\ - buffer_vertex_size / 3, buffer_vertex_size + 0, buffer_vertex_size + 2, x, y, z); - - buffer_vertex_size += 3; -} - -/* - * Writes values to describe a color (r,g,b) into the color buffer - * - * @param color GLfloat(r,g,b) - * - * @return void - */ -void graphics_draw_color (GLfloat r, GLfloat g, GLfloat b, int console) -{ - buffer_colors_origin = g_realloc (buffer_colors_origin, - (buffer_colors_size + 3) * sizeof(GLfloat)); - - assert (buffer_colors_origin); - - buffer_colors_origin[buffer_colors_size + 0] = r; - buffer_colors_origin[buffer_colors_size + 1] = g; - buffer_colors_origin[buffer_colors_size + 2] = b; - - buffer_colors_size += 3; -} - -/* - * Writes values to describe a line from a to b into the line buffer - * - * @param coords GLuint (a,b) - * - * @return void - */ -void graphics_draw_line (GLuint a, GLuint b, int console) -{ - buffer_lines_origin = g_realloc (buffer_lines_origin, - (buffer_lines_size + 2) * sizeof(GLuint)); - - assert (buffer_lines_origin); - - buffer_lines_origin[buffer_lines_size + 0] = a; - buffer_lines_origin[buffer_lines_size + 1] = b; - - if (console) printf("In graphics_draw_line() buffer_lines_size => [%2ld] [%2ld > %2ld] (%3u > %3u )\n",\ - buffer_lines_size / 2, buffer_lines_size + 0, buffer_lines_size + 1, a, b); - - buffer_lines_size += 2; -} - -/* - * Writes values to describe an (a,b,c) plan (triangle) into the plan buffer - * - * @param coords GLuint (a,b,c) - * - * @return void - */ -void graphics_draw_plan (GLuint a, GLuint b, GLuint c, int console) -{ - buffer_plans_origin = g_realloc (buffer_plans_origin, - (buffer_plans_size + 3) * sizeof(GLuint)); - - assert (buffer_plans_origin); - - buffer_plans_origin[buffer_plans_size + 0] = a; - buffer_plans_origin[buffer_plans_size + 1] = b; - buffer_plans_origin[buffer_plans_size + 2] = c; - - buffer_plans_size += 3; -} - -/* Initializes the buffer of a gl_area - * Calls according to the user preferences - * @param gl_area, ptr to the gl_area widget - * @return void - */ -void graphics_init_buffers(const void *gl_area) -{ - struct gl_area_entry *entry; - entry = graphics_find_glarea_from_ptr(gl_area); - - //XXX - main_test_graphics (); - - GLuint vao, vertex_buffer, color_buffer; - - glGenBuffers(1, &vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, buffer_vertex_size * sizeof(buffer_vertex_origin[0]), buffer_vertex_origin, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - - // colors - glGenBuffers(1, &color_buffer); - glBindBuffer(GL_ARRAY_BUFFER, color_buffer); - glBufferData(GL_ARRAY_BUFFER, buffer_colors_size * sizeof(buffer_colors_origin[0]), buffer_colors_origin, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // We only use one VAO, so we always keep it bound - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - if(entry != NULL) { - entry->vao = vao; - entry->position_buffer = vertex_buffer; - entry->color_buffer = color_buffer; - } -} - -/* - * Initializes the shaders of a gl_area and link them to a program + * Initializes graphical stack * * @param gl_area, ptr to the gl_area widget * - * @return true if initialized + * @return id if initialized */ -bool graphics_init_shaders(const void *gl_area) +int graphics_init(void *glarea) { - char *vertex_shader; - char *fragment_shader; - struct gl_area_entry *entry; - int status; - GLuint vertex, fragment; - GLuint program = 0; - GLuint m = 0; - GLuint v = 0; - GLuint p = 0; + int cur_id = 0; - entry = graphics_find_glarea_from_ptr(gl_area); + if (glarea == NULL) + return 0; - if (entry == NULL) { - errno = EFAULT; - perror("gl_area_array entry not found"); - return false; + if (graphic_stack == NULL) { + graphic_stack = g_malloc(sizeof(struct graphic_stack_t)); + graphic_stack_size = 1; + } else { + // Check if there are free slots + if (free_stack_slot_size) { + // We get the last free slot registered + cur_id = free_stack_slot[free_stack_slot_size-1]; + // Unregister it (ofc) + free_stack_slot = g_realloc(free_stack_slot, + free_stack_slot_size-- * + sizeof(int)); + } else { + cur_id = graphic_stack_size; + graphic_stack = g_realloc(graphic_stack, + ++graphic_stack_size * + sizeof(struct graphic_stack_t)); + } } - // Load vertex shader file - vertex_shader = read_file(VERTEX_SHADER_FILE); - if (vertex_shader == NULL) - return false; - vertex = create_shader(GL_VERTEX_SHADER, vertex_shader); - - if(vertex == 0) { - entry->program = 0; - g_free(vertex_shader); - return false; - } - - // Load fragment shader file - fragment_shader = read_file(FRAG_SHADER_FILE); - if (fragment_shader == NULL) - return false; - fragment = create_shader(GL_FRAGMENT_SHADER, fragment_shader); - - if(fragment == 0) { - glDeleteShader(vertex); - entry->program = 0; - g_free(vertex_shader); - g_free(fragment_shader); - return false; - } - - // Link shaders to program - program = glCreateProgram(); - glAttachShader(program, vertex); - glAttachShader(program, fragment); - - glLinkProgram(program); - - glGetProgramiv(program, GL_LINK_STATUS, &status); - - if(status == GL_FALSE) { - int log_len; - char *buffer; - - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); - - buffer = g_malloc(log_len + 1); - assert(buffer); - glGetProgramInfoLog(program, log_len, NULL, buffer); - - g_warning("Linking failure:\n%s", buffer); - - g_free(buffer); - - glDeleteProgram(program); - program = 0; - - glDeleteShader(vertex); - glDeleteShader(fragment); - - g_free(vertex_shader); - g_free(fragment_shader); - - return false; - } - - /* Get the location of the "mvp" uniform */ - m = glGetUniformLocation(program, "model_matrix"); - v = glGetUniformLocation(program, "view_matrix"); - p = glGetUniformLocation(program, "projection_matrix"); - - glDetachShader(program, vertex); - glDetachShader(program, fragment); - - glDeleteShader(vertex); - glDeleteShader(fragment); - - entry->program = program; - entry->m = m; - entry->v = v; - entry->p = p; - - g_free(vertex_shader); - g_free(fragment_shader); - - return true; -} - -/* - * Draws the current buffer to a gl_area - * - * @param gl_area, ptr to the gl_area widget - * - * @return void - */ -void graphics_draw(const void *gl_area) -{ - float m[16]; - float v[16]; - float p[16]; - struct gl_area_entry *entry; - - entry = graphics_find_glarea_from_ptr(gl_area); - - if (entry == NULL) { - errno = EFAULT; - perror("gl_area_array entry not found"); - return; - } - - /* Compute the model view projection matrix using the - * rotation angles specified through the GtkRange widgets - */ - compute_mvp(p, - rotation_angles[X_AXIS], - rotation_angles[Y_AXIS], - rotation_angles[Z_AXIS]); - compute_i(m); - compute_i(v); - - /* Use our shaders */ - glUseProgram(entry->program); - -// if (pref_show_space_design_mix_colors == 0) - glClearColor(0, 0, 0, 0.4f); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - /* Update the "mvp" matrix we use in the shader */ - glUniformMatrix4fv(entry->m, 1, GL_FALSE, &m[0]); - glUniformMatrix4fv(entry->v, 1, GL_FALSE, &v[0]); - glUniformMatrix4fv(entry->p, 1, GL_FALSE, &p[0]); - - /* Use the vertices in our buffer */ - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, entry->position_buffer); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,(void*)0); - - // couleurs - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, entry->color_buffer); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0,(void*)0); - - //glEnable(GL_DEPTH_TEST); - - glDrawElements(GL_LINES, buffer_lines_size, GL_UNSIGNED_INT, buffer_lines_origin); - glDrawElements(GL_TRIANGLES, buffer_plans_size, GL_UNSIGNED_INT, buffer_plans_origin); - - /* We finished using the buffers and program */ - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glUseProgram(0); - - glFlush(); -} -/* -------------------------------------------------------------------------- */ - -/* - * Find gl_area_entry from a gl_area ptr - * - * @param gl_area, ptr to the gl_area widget - * - * - * @return entry ptr - */ -struct gl_area_entry *graphics_find_glarea_from_ptr(const char *name) -{ - struct gl_area_entry **cur; - - // Check uninitialized and quit - if (gl_area_array == NULL) return NULL; - - // Seek in array - cur = gl_area_array; - while(*cur) { - if (strncmp((*cur)->name, name, sizeof((*cur)->name)) == 0) return *cur; - cur++; - } - - // Nothing found - return NULL; -} - -/* - * Initializes a gl_area - * - * @param gl_area, ptr to the gl_area widget - * - * @return true if initialized - */ -bool graphics_init(const char *gl_area) -{ - short array_size; + graphic_stack[cur_id].id = cur_id; + graphic_stack[cur_id].glarea = glarea; glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glEnable(GL_MULTISAMPLE); - // Check if not already initialized - if (graphics_find_glarea_from_ptr(gl_area)) { - errno = EEXIST; - perror("gl_area_array already exists"); - return false; - } + if (!graphics_init_shaders(cur_id)) + return 0; - // Get actual array size - array_size = gl_area_size(); - - // If it does not exist, allocs it - if (gl_area_array == NULL) { - gl_area_array = g_malloc0(sizeof(struct gl_area_entry *) * 2); - assert(gl_area_array); - - // If it does exist, g_reallocs it - } else { - gl_area_array = g_realloc(gl_area_array, - (array_size + 1) - * sizeof(struct gl_area_entry *)); - assert (gl_area_array); - if (gl_area_array == NULL) { - perror("Not enough memory to allocate gl_area_array"); - return false; - } - - explicit_bzero(gl_area_array + array_size * sizeof(struct gl_area_entry *), - sizeof(struct gl_area_entry *)); - } - - // Alloc new entry - gl_area_array[array_size] = g_malloc0(sizeof(struct gl_area_entry)); - assert(gl_area_array[array_size]); - - strcpy(gl_area_array[array_size]->name, gl_area); - - if (!graphics_init_shaders(gl_area)) return false; - - graphics_init_buffers(gl_area); + graphics_init_buffers(cur_id); glDebugMessageCallback(graphics_debug_callback, NULL); - return true; + return cur_id; } /* @@ -522,215 +154,42 @@ bool graphics_init(const char *gl_area) * * @return true if success */ -bool graphics_shutdown(const void *gl_area) +bool graphics_shutdown(const int id) { - struct gl_area_entry *entry; + struct graphic_stack_t stack; - entry = graphics_find_glarea_from_ptr(gl_area); - - if (entry == NULL) { - errno = EFAULT; - perror("gl_area_array entry not found"); + if (id == 0 || + id >= graphic_stack_size || + graphic_stack_size == 0 || + graphic_stack == NULL) return false; + + stack = graphic_stack[id]; + + glDeleteBuffers(1, &stack.position_buffer); + glDeleteBuffers(1, &stack.color_buffer); + glDeleteProgram(stack.program); + + g_free(stack.buffer_vertex_origin); + g_free(stack.buffer_colors_origin); + g_free(stack.buffer_lines_origin); + g_free(stack.buffer_plans_origin); + + if (graphic_stack_size == 1) { + free(graphic_stack); + graphic_stack = NULL; + graphic_stack_size = 0; + } else { + memset(&graphic_stack[id], 0, sizeof(struct graphic_stack_t)); + free_stack_slot = g_realloc(free_stack_slot, + ++free_stack_slot_size * + sizeof(int)); + free_stack_slot[free_stack_slot_size-1] = id; } - glDeleteBuffers(1, &entry->position_buffer); - glDeleteBuffers(1, &entry->color_buffer); - glDeleteProgram(entry->program); - - // Liberate - g_free(entry); - - entry = NULL; - - gl_area_array = g_realloc(gl_area_array, - (gl_area_size()) - * sizeof(struct gl_area_entry *)); - assert (gl_area_array || !gl_area_size()); - - g_free(buffer_vertex_origin); - g_free(buffer_colors_origin); - g_free(buffer_lines_origin); - g_free(buffer_plans_origin); return true; } - -/* - * Depends on set_arrow() - * Exchanges current and required site values - * when the address of the arrow to be set is already occupied - */ -static int rewrite_arrow (int arrows_nb, int address, int load, int site, int x, int y, int z, int console) -{ - printf("WARNING in rewrite_arrow() <> address or address / 5 ? (et pourquoi ?)\n"); - arrows_ptr[address].load = load; - - if (console) print_arrows_array (arrows_ptr, arrows_nb, 2); - - return arrows_nb; -} - -/* - * Depends on set_arrow() - * Creates the arrow to be set with the required load at the required address - */ -static inline int create_arrow (int arrows_nb, - int space_X, int space_Y, int space_Z, - int load, int site, int x, int y, int z, - int console) -{ - void *newptr = g_realloc(arrows_ptr, (arrows_nb + 1) * sizeof(struct arrow_t)); - - if (newptr) - arrows_ptr = newptr; - else - perror("In create arrow, can't allocate new arrow buffer !\n"); - - arrows_ptr[arrows_nb].load = load; - arrows_ptr[arrows_nb].site = site; - arrows_ptr[arrows_nb].x = x; - arrows_ptr[arrows_nb].y = y; - arrows_ptr[arrows_nb].z = z; - - draw_one_arrow_vertex(space_X, space_Y, space_Z, load, site, x, y, z, console); - draw_one_arrow_line (buffer_vertex_size / 3 - 2, console); - - arrows_nb ++; - - if (console) print_arrows_array (arrows_ptr, arrows_nb, 1); - - return arrows_nb; -} - -/* - * Depends on set_arrow() - * Erases the arrow at the required address - */ -static inline int erase_arrow (int arrows_nb, int arrow_address_in_list, - GLuint site, GLint x, GLint y, GLint z, - int console) -{ - if (arrows_nb == 0) assert (buffer_lines_size == buffer_lines_0_arrow); // ? - if (arrows_nb == 0) {buffer_lines_size = buffer_lines_0_arrow; return 0;} - - if (console) print_arrows_array (arrows_ptr, arrows_nb, 7); - - assert (arrows_nb); - arrows_nb --; - - if (arrow_address_in_list < arrows_nb) - { - int mem = arrows_ptr[arrow_address_in_list].site; - - arrows_ptr[arrow_address_in_list].load = arrows_ptr[arrows_nb].load; - arrows_ptr[arrow_address_in_list].site = arrows_ptr[arrows_nb].site; - arrows_ptr[arrow_address_in_list].x = arrows_ptr[arrows_nb].x; - arrows_ptr[arrow_address_in_list].y = arrows_ptr[arrows_nb].y; - arrows_ptr[arrow_address_in_list].z = arrows_ptr[arrows_nb].z; - - - if (console) printf("in erase_arrow() : arrows_nb decreases from %d to %d. the erased arrow was at address : %d\n\ - : arrows_ptr[%d].site (value: %d) was replaced by arrows_ptr[%d].site (value: %d)\n",\ - arrows_nb + 1, arrows_nb, arrow_address_in_list, arrow_address_in_list, mem, arrows_nb, arrows_ptr[arrows_nb].site); - } - - for (long i = 0; i < 6; i++) - buffer_vertex_origin [buffer_vertex_0_arrow + arrow_address_in_list * 6 + i] - = buffer_vertex_origin [buffer_vertex_size - 6 + i]; - - for (long i = 0; i < 6; i++) - buffer_colors_origin [buffer_colors_0_arrow + arrow_address_in_list * 6 + i] - = buffer_colors_origin [buffer_colors_size - 6 + i]; - - buffer_vertex_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_vertex() - buffer_colors_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_colors() - buffer_lines_size -= 2; // <<< l'inverse de ce qui est fait dans : graphics_draw_line() - - void *new_arrows_vertex_ptr = g_realloc(buffer_vertex_origin, buffer_vertex_size * sizeof(GLfloat)); - if (new_arrows_vertex_ptr) buffer_vertex_origin = new_arrows_vertex_ptr; - else perror("In graphics.erase_arrow(), can't re_allocate for arrows vertex buffer.\n"); - - void *new_arrows_colors_ptr = g_realloc(buffer_colors_origin, buffer_colors_size * sizeof(GLfloat)); - if (new_arrows_colors_ptr) buffer_colors_origin = new_arrows_colors_ptr; - else perror("In graphics.erase_arrow(), can't re_allocate for arrows colors buffer.\n"); - - /* Il ne faut pas réécrire ce qui suit: ces lignes dessinent maintenant à partir d'autres vertex */ - /* void *new_arrows_lines_ptr = g_realloc(buffer_lines_origin, buffer_lines_size * sizeof(GLfloat)); */ - /* if (new_arrows_lines_ptr) buffer_lines_origin = new_arrows_lines_ptr; */ - /* else perror("In graphics.erase_arrow(), can't re_allocate for arrows lines buffer.\n"); */ - - if (console) print_arrows_array (arrows_ptr, arrows_nb, 0); - if (console) printf("\n"); - - return arrows_nb; -} - - - -/* - * Creates or deletes an arrow or modify the load of an existing one - * Acts both by writing the list of arrows : (struct arrow_t *arrows_ptr, int arrows_nb) - * and by drawing in the global space - * - * @param arrows_ptr and arrows_nb before operation, - * required load and address (site, x, y, z) - * - * IF there is no arrow at the required address, - * AND IF the load is > 0, an arrow will be created. - * - * IF there is an arrow at the required address - * AND IF the load is = 0, the existing arrow will be deleted. - * - * IF there is an arrow at the required address - * AND IF the load is > 0, the load of the existing arrow will be modified. - * - * May not call any of these three functions IF : - * - Current_weight of an arrow located at the requested address == requested_weight - * - No arrow was found at the requested addres AND current_weight == requested_weight - * - * @return arrows_nb after operation - */ -static inline int set_arrow (struct arrow_t *arrows_ptr, int arrows_nb, int space_X, int space_Y, int space_Z, - int requested_weight, int site, int arrow_x, int arrow_y, int arrow_z, int console) -{ - int address = -1, current_weight = -1; - - if (console) printf("in set_arrow (begin) arrows_nb = %d requested site: %d > ", arrows_nb, site); - /* if (console) for (int i = 0; i < arrows_nb; i++) {printf(" [%d] = %d ", i, arrows_ptr[i].site); if (site == arrows_ptr[i].site) break;} */ - - for (int i = 0; i < arrows_nb; i++) - if ((site == arrows_ptr[i].site) - && (arrow_x == arrows_ptr[i].x) - && (arrow_y == arrows_ptr[i].y) - && (arrow_z == arrows_ptr[i].z)) - { - address = i; - current_weight = arrows_ptr[i].load; - break; - } - assert (address <= arrows_nb); - - if (console) { - if (address == -1 && requested_weight > 0) printf(" >> create_arrow() at site %d\n", site); - if (address >= 0 && requested_weight == 0) printf(" >> erase_arrow() at site %d\n", site); - if (address >= 0 && current_weight != requested_weight) printf(" >> rewrite_arrow() at site %d\n", site); - if (address == -1 && requested_weight == 0) printf(" >> no operation\n"); - } - if (address == -1 && requested_weight > 0) - return create_arrow (arrows_nb, space_X, space_Y, space_Z, requested_weight, site, arrow_x, arrow_y, arrow_z, console); - if (address >= 0 && requested_weight == 0) // address >= 0 if and only if arrows_nb > 0 - return erase_arrow (arrows_nb, address, site, arrow_x, arrow_y, arrow_z, console); - if (address >= 0 && current_weight != requested_weight) - return rewrite_arrow (arrows_nb, address, requested_weight, site, arrow_x, arrow_y, arrow_z, console); - if (address >= 0 && current_weight == requested_weight && console) print_arrows_array(arrows_ptr, arrows_nb, 3); - if (address == -1 && requested_weight == 0 && console) print_arrows_array(arrows_ptr, arrows_nb, 4); - - return arrows_nb; -} - - - /* TODO * #pragma omp parallel schedule(static, 12) * void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {} @@ -750,7 +209,7 @@ static inline int set_arrow (struct arrow_t *arrows_ptr, int arrows_nb, int spac * Attention, les vertex centraux de chaque unité d'espace (cube) * peuvent être redondants (max 6) */ -void main_test_graphics (void) +void main_test_graphics (const int stack_id) { /*------------------------------------------------------------------------*/ @@ -760,7 +219,10 @@ void main_test_graphics (void) srand(time(NULL)); int rand(void); void srand(unsigned int seed); - int randomize = 10, console = 0, arrows_nb = 0, space_X = 1, space_Y = 1, space_Z = 1; + int randomize = 10, console = 0, space_X = 1, space_Y = 1, space_Z = 1; + + graphic_stack[stack_id].arrows_nb = 0; + if (randomize) { space_X = 1 + rand() % randomize; space_Y = 1 + rand() % randomize; @@ -776,14 +238,19 @@ void main_test_graphics (void) /*------------------------------------------------------------------------*/ - draw_space_ridges_vertex (buffer_vertex_size, space_X, space_Y, space_Z, console); + draw_space_ridges_vertex (graphic_stack[stack_id].buffer_vertex_size, + space_X, space_Y, space_Z, console); draw_space_ridges_lines (console); draw_grids_on_space_faces_vertex (space_X, space_Y, space_Z, console); - draw_grids_on_space_faces_lines (buffer_lines_size, space_X, space_Y, space_Z, console); + draw_grids_on_space_faces_lines (graphic_stack[stack_id].buffer_lines_size, + space_X, space_Y, space_Z, console); - buffer_vertex_0_arrow = buffer_vertex_size; - buffer_colors_0_arrow = buffer_colors_size; - buffer_lines_0_arrow = buffer_lines_size; + graphic_stack[stack_id].buffer_vertex_0_arrow = + graphic_stack[stack_id].buffer_vertex_size; + graphic_stack[stack_id].buffer_colors_0_arrow = + graphic_stack[stack_id].buffer_colors_size; + graphic_stack[stack_id].buffer_lines_0_arrow = + graphic_stack[stack_id].buffer_lines_size; /*------------------------------------------------------------------------*/ @@ -795,45 +262,22 @@ void main_test_graphics (void) if (randomize) for (int i = 0; i < specified_arrows_nb; i++) { - arrows_nb = set_arrow (arrows_ptr, arrows_nb, space_X, space_Y, space_Z, + graphic_stack[stack_id].arrows_nb = + set_arrow (stack_id, graphic_stack[stack_id].arrows_nb, space_X, space_Y, space_Z, 1, // load rand() % 6, // site rand() % space_X, // x rand() % space_Y, // y - rand() % space_Z, // z - console); + rand() % space_Z); // z + if (i > 0 && i % 1000 == 0) printf("|"); if (i > 0 && i % 100000 == 0) printf("\n"); } else for (int i = 0; i < 6; i++) - arrows_nb = set_arrow (arrows_ptr, arrows_nb, 1, 1, 1, 1, i, 0, 0, 0, console); - - int max_arrows_nb = arrows_nb; - - /* if (randomize) for (int i = 0; i < 6; i++) */ - /* arrows_nb = set_arrow (arrows_ptr, arrows_nb, space_X, space_Y, space_Z, */ - /* rand() % 1, // load */ - /* rand() % 6, // site */ - /* rand() % space_X, // x */ - /* rand() % space_Y, // y */ - /* rand() % space_Z, // z */ - /* console); */ - /* else for (int i = 0; i < 6; i++) */ - /* arrows_nb = set_arrow (arrows_ptr, arrows_nb, 1, 1, 1, 0, i, 0, 0, 0, 0); */ - - /* int angle = 9; */ - /* if (space_X > angle && space_Y > angle && space_Z > angle) for (int i = 0; i < angle; i++) */ - /* for (int u = 0; u < angle; u++) for (int v = 0; v < angle; v++) for (int w = 0; w < angle; w++) */ - /* if (u + v + w < angle * 3) */ - /* arrows_nb = set_arrow (arrows_ptr, arrows_nb, 1, 1, 1, 0, i, u, v, w, 0); */ - - /* if (space_X > angle && space_Y > angle && space_Z > angle) */ - /* printf("+ effacement des flèches dans l'angle-origine\ */ - /* <=> contrôle graphique de la fonction erase_arrow()\n"); */ - - if (1) print_user_choices(arrows_ptr, max_arrows_nb, arrows_nb, space_X, space_Y, space_Z, 0, 0); - + graphic_stack[stack_id].arrows_nb = + set_arrow (stack_id, graphic_stack[stack_id].arrows_nb, 1, 1, 1, 1, i, 0, 0, 0); + int max_arrows_nb = graphic_stack[stack_id].arrows_nb; /*--------------------------------------------------------------------------------*/ @@ -843,6 +287,8 @@ void main_test_graphics (void) /*--------------------------------------------------------------------------------*/ - free(arrows_ptr); arrows_ptr = NULL; arrows_nb = 0; + free(graphic_stack[stack_id].arrows_ptr); + graphic_stack[stack_id].arrows_ptr = NULL; + graphic_stack[stack_id].arrows_nb = 0; } diff --git a/src/graphics/grid.c b/src/graphics/grid.c index 9ff5474..e0fad55 100644 --- a/src/graphics/grid.c +++ b/src/graphics/grid.c @@ -22,131 +22,139 @@ * along with this program. If not, see . */ +#include +#include #include "../../include/base.h" +#include "../../include/ui.h" #include "../../include/graphics.h" -int draw_space_ridges_vertex (long offset_vertex, long x, long y, long z, int console) +int draw_space_ridges_vertex (const int stack_id, + long offset_vertex, + long x, + long y, + long z) { GLfloat max = fmax(x, y); max = fmax(max, z); - graphics_draw_vertex (offset_vertex - x / max, offset_vertex - y / max, - z / max, console); + graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, - z / max); - graphics_draw_vertex (offset_vertex + x / max, offset_vertex - y / max, - z / max, console); - graphics_draw_vertex (offset_vertex - x / max, offset_vertex + y / max, - z / max, console); - graphics_draw_vertex (offset_vertex - x / max, offset_vertex - y / max, + z / max, console); + graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, - z / max); + graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, - z / max); + graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, + z / max); - graphics_draw_vertex (offset_vertex + x / max, offset_vertex + y / max, - z / max, console); - graphics_draw_vertex (offset_vertex + x / max, offset_vertex - y / max, + z / max, console); - graphics_draw_vertex (offset_vertex - x / max, offset_vertex + y / max, + z / max, console); + graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex + y / max, - z / max); + graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, + z / max); + graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, + z / max); - graphics_draw_vertex (offset_vertex + x / max, + y / max, + z / max, console); + graphics_draw_vertex (stack_id, offset_vertex + x / max, + y / max, + z / max); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); - graphics_draw_color (0.8f, 0.6f, 0.5f, console); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); + graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f); return 8; } -int draw_space_ridges_lines (int console) +int draw_space_ridges_lines (const int stack_id) { - graphics_draw_line ( 0, 1, console); graphics_draw_line ( 7, 4, console); - graphics_draw_line ( 0, 2, console); graphics_draw_line ( 7, 5, console); - graphics_draw_line ( 0, 3, console); graphics_draw_line ( 7, 6, console); + graphics_draw_line (stack_id, 0, 1); graphics_draw_line (stack_id, 7, 4); + graphics_draw_line (stack_id, 0, 2); graphics_draw_line (stack_id, 7, 5); + graphics_draw_line (stack_id, 0, 3); graphics_draw_line (stack_id, 7, 6); - graphics_draw_line ( 1, 4, console); graphics_draw_line ( 2, 4, console); - graphics_draw_line ( 1, 5, console); graphics_draw_line ( 3, 5, console); - graphics_draw_line ( 2, 6, console); graphics_draw_line ( 3, 6, console); + graphics_draw_line (stack_id, 1, 4); graphics_draw_line (stack_id, 2, 4); + graphics_draw_line (stack_id, 1, 5); graphics_draw_line (stack_id, 3, 5); + graphics_draw_line (stack_id, 2, 6); graphics_draw_line (stack_id, 3, 6); return 12; } -long draw_grids_on_space_faces_vertex (long x, long y, long z, int console) +long draw_grids_on_space_faces_vertex (const int stack_id, + long x, + long y, + long z) { float i, max = fmax(x, y); max = fmax(max, z); for (i = 1; i < x; i++) { - graphics_draw_vertex ((2 * i / x - 1) * x / max, - y / max, - z / max, console); - graphics_draw_vertex ((2 * i / x - 1) * x / max, - y / max, z / max, console); - graphics_draw_vertex ((2 * i / x - 1) * x / max, y / max, z / max, console); - graphics_draw_vertex ((2 * i / x - 1) * x / max, y / max, - z / max, console); + graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, - z / max); + graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, z / max); + graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, z / max); + graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, - z / max); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); } /* offset_vertex += (x - 1) * 4; */ /* offset_colors += (x - 1) * 4; */ for (i = 1; i < y; i++) { - graphics_draw_vertex (- x / max, (2 * i / y - 1) * y / max, - z / max, console); - graphics_draw_vertex (- x / max, (2 * i / y - 1) * y / max, z / max, console); - graphics_draw_vertex ( x / max, (2 * i / y - 1) * y / max, z / max, console); - graphics_draw_vertex ( x / max, (2 * i / y - 1) * y / max, - z / max, console); + graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, - z / max); + graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, z / max); + graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, z / max); + graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, - z / max); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); } /* offset_vertex += (y - 1) * 4; */ /* offset_colors += (y - 1) * 4; */ for (i = 1; i < z; i++) { - graphics_draw_vertex (- x / max, - y / max, (2 * i / z - 1) * z / max, console); - graphics_draw_vertex (- x / max, y / max, (2 * i / z - 1) * z / max, console); - graphics_draw_vertex ( x / max, y / max, (2 * i / z - 1) * z / max, console); - graphics_draw_vertex ( x / max, - y / max, (2 * i / z - 1) * z / max, console); + graphics_draw_vertex (stack_id, - x / max, - y / max, (2 * i / z - 1) * z / max); + graphics_draw_vertex (stack_id, - x / max, y / max, (2 * i / z - 1) * z / max); + graphics_draw_vertex (stack_id, x / max, y / max, (2 * i / z - 1) * z / max); + graphics_draw_vertex (stack_id, x / max, - y / max, (2 * i / z - 1) * z / max); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); - graphics_draw_color (0.55f, 0.55f, 0.55f, console); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); + graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f); } return (x + y + z - 3) * 3; } -long draw_grids_on_space_faces_lines (long offset_vertex, long x, long y, long z, int console) +long draw_grids_on_space_faces_lines (const int stack_id, + long offset_vertex, + long x, + long y, + long z) { offset_vertex = offset_vertex / 3; for (int i = 0; i < x - 1; i ++) { - /* graphics_draw_line (offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1, console); */ - graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); - graphics_draw_line (offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3, console); - /* graphics_draw_line (offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0, console); */ + graphics_draw_line (stack_id, offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2); + graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3); } offset_vertex += (x - 1) * 4; for (int i = 0; i < y - 1; i ++) { - /* graphics_draw_line (offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1, console); */ - /* graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); */ - graphics_draw_line (offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3, console); - graphics_draw_line (offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0, console); + graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3); + graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0); } offset_vertex += (y - 1) * 4; for (int i = 0; i < z - 1; i ++) { - graphics_draw_line (offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1, console); - /* graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); */ - /* graphics_draw_line (offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3, console); */ - graphics_draw_line (offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0, console); + graphics_draw_line (stack_id, offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1); + graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0); } return (x + y + z - 3) * 4; diff --git a/src/graphics/init.c b/src/graphics/init.c new file mode 100644 index 0000000..d7ceb0f --- /dev/null +++ b/src/graphics/init.c @@ -0,0 +1,175 @@ +/* + * Gem-graph OpenGL experiments + * + * Desc: GL functions + * + * Copyright (C) 2023 Arthur Menges + * Copyright (C) 2023 Adrien Bourmault + * + * This file is part of Gem-graph. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* -------------------------------------------------------------------------- */ + +#include +#include +#include "../../include/base.h" +#include "../../include/ui.h" +#include "../../include/graphics.h" + +/* Initializes the buffer of a gl_area + * Calls according to the user preferences + * @param gl_area, ptr to the gl_area widget + * @return void + */ +void graphics_init_buffers(const int stack_id) +{ + + // XXX TODO get stack from stack_id + + //XXX + main_test_graphics (stack_id); + + GLuint vao, vertex_buffer, color_buffer; + + glGenBuffers(1, &vertex_buffer); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + glBufferData(GL_ARRAY_BUFFER, + graphic_stack[stack_id].buffer_vertex_size * + sizeof(graphic_stack[stack_id].buffer_vertex_origin[0]), + graphic_stack[stack_id].buffer_vertex_origin, + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + + // colors + glGenBuffers(1, &color_buffer); + glBindBuffer(GL_ARRAY_BUFFER, color_buffer); + glBufferData(GL_ARRAY_BUFFER, graphic_stack[stack_id].buffer_colors_size * + sizeof(graphic_stack[stack_id].buffer_colors_origin[0]), + graphic_stack[stack_id].buffer_colors_origin, + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // We only use one VAO, so we always keep it bound + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + graphic_stack[stack_id].vao = vao; + graphic_stack[stack_id].position_buffer = vertex_buffer; + graphic_stack[stack_id].color_buffer = color_buffer; +} + +/* + * Initializes the shaders of a gl_area and link them to a program + * + * @param gl_area, ptr to the gl_area widget + * + * @return true if initialized + */ +bool graphics_init_shaders(const int stack_id) +{ + char *vertex_shader; + char *fragment_shader; + int status; + GLuint vertex, fragment; + GLuint program = 0; + GLuint m = 0; + GLuint v = 0; + GLuint p = 0; + + // Load vertex shader file + vertex_shader = read_file(VERTEX_SHADER_FILE); + if (vertex_shader == NULL) + return false; + vertex = create_shader(stack_id, GL_VERTEX_SHADER, vertex_shader); + + if(vertex == 0) { + graphic_stack[stack_id].program = 0; + g_free(vertex_shader); + return false; + } + + // Load fragment shader file + fragment_shader = read_file(FRAG_SHADER_FILE); + if (fragment_shader == NULL) + return false; + fragment = create_shader(stack_id, GL_FRAGMENT_SHADER, fragment_shader); + + if(fragment == 0) { + glDeleteShader(vertex); + graphic_stack[stack_id].program = 0; + g_free(vertex_shader); + g_free(fragment_shader); + return false; + } + + // Link shaders to program + program = glCreateProgram(); + glAttachShader(program, vertex); + glAttachShader(program, fragment); + + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + + if(status == GL_FALSE) { + int log_len; + char *buffer; + + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); + + buffer = g_malloc(log_len + 1); + assert(buffer); + glGetProgramInfoLog(program, log_len, NULL, buffer); + + g_warning("Linking failure:\n%s", buffer); + + g_free(buffer); + + glDeleteProgram(program); + program = 0; + + glDeleteShader(vertex); + glDeleteShader(fragment); + + g_free(vertex_shader); + g_free(fragment_shader); + + return false; + } + + /* Get the location of the "mvp" uniform */ + m = glGetUniformLocation(program, "model_matrix"); + v = glGetUniformLocation(program, "view_matrix"); + p = glGetUniformLocation(program, "projection_matrix"); + + glDetachShader(program, vertex); + glDetachShader(program, fragment); + + glDeleteShader(vertex); + glDeleteShader(fragment); + + graphic_stack[stack_id].program = program; + graphic_stack[stack_id].m = m; + graphic_stack[stack_id].v = v; + graphic_stack[stack_id].p = p; + + g_free(vertex_shader); + g_free(fragment_shader); + + return true; +} diff --git a/src/shaders/shader.frag b/src/graphics/shaders/shader.frag similarity index 100% rename from src/shaders/shader.frag rename to src/graphics/shaders/shader.frag diff --git a/src/shaders/shader.vert b/src/graphics/shaders/shader.vert similarity index 100% rename from src/shaders/shader.vert rename to src/graphics/shaders/shader.vert diff --git a/src/ui/graphics.c b/src/ui/graphics.c index 7ca212f..d47a0df 100644 --- a/src/ui/graphics.c +++ b/src/ui/graphics.c @@ -27,11 +27,13 @@ #include "../../include/base.h" #include "../../include/ui.h" +#include "../../include/graphics.h" float rotation_angles[N_AXIS] = { 0.0 }; // Rotation angles on each axis GtkWidget *gl_area = NULL; +struct graphic_stack_t *graphic_stack = NULL; static inline GtkWidget *create_axis_slider(int axis) {