WIP: total rewrite graphic stack allocation

This commit is contained in:
Adrien Bourmault 2023-12-19 21:46:51 +01:00
parent 6a2f3afe89
commit 9325a7cb6f
Signed by: neox
GPG Key ID: 2974E1D5F25DFCC8
15 changed files with 851 additions and 1056 deletions

View File

@ -1,45 +0,0 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: OpenGL utils header
*
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <unistd.h>
#include <stdbool.h>
#include <GL/glu.h>
/*
* 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);

View File

@ -37,6 +37,7 @@
#include <glib-2.0/glib.h> #include <glib-2.0/glib.h>
#define G_APPLICATION_DEFAULT_FLAGS 0 #define G_APPLICATION_DEFAULT_FLAGS 0
// Graphical axis
enum enum
{ {
X_AXIS, X_AXIS,
@ -46,6 +47,17 @@ enum
N_AXIS 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 * Read a file from filename into a provided buffer
* *

View File

@ -1,83 +0,0 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <time.h>
/*
* 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);

View File

@ -31,12 +31,19 @@
#include <GL/glu.h> #include <GL/glu.h>
#include <GL/glext.h> #include <GL/glext.h>
#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 * Structure describing a gl_area and its parameters, used to create a table
* of Gem-graph client current gl_areas * of Gem-graph client current gl_areas
*/ */
struct gl_area_entry { struct graphic_stack_t {
char name[16];
int id;
int mode;
void *glarea;
GLuint vao; // init_buffers GLuint vao; // init_buffers
GLuint position_buffer; // shutdown, draw GLuint position_buffer; // shutdown, draw
GLuint color_buffer; // shutdown, draw GLuint color_buffer; // shutdown, draw
@ -44,17 +51,30 @@ struct gl_area_entry {
GLuint m; // init_shaders, draw GLuint m; // init_shaders, draw
GLuint v; // init_shaders, draw GLuint v; // init_shaders, draw
GLuint p; // 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 * Dynamic array of ptrs to dynamically allocated gl_area_entry
*
* @param gl_area, ptr to the gl_area widget
*
*
* @return entry ptr
*/ */
struct gl_area_entry *graphics_find_glarea_from_ptr(const char *name); extern struct graphic_stack_t *graphic_stack;
/* /*
* Initializes a gl_area * Initializes a gl_area
@ -63,7 +83,7 @@ struct gl_area_entry *graphics_find_glarea_from_ptr(const char *name);
* *
* @return true if initialized * @return true if initialized
*/ */
bool graphics_init(const char *gl_area); int graphics_init(void *glarea);
/* /*
* Draws the current buffer to a gl_area * Draws the current buffer to a gl_area
@ -72,7 +92,7 @@ bool graphics_init(const char *gl_area);
* *
* @return void * @return void
*/ */
void graphics_draw(const void *gl_area); void graphics_draw(const int stack_id);
/* /*
* Shutdowns a gl_area * Shutdowns a gl_area
@ -81,7 +101,7 @@ void graphics_draw(const void *gl_area);
* *
* @return true if success * @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 * 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 * @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 /* Initializes the buffer of a gl_area
* Calls according to the user preferences * Calls according to the user preferences
* @param gl_area, ptr to the gl_area widget * @param gl_area, ptr to the gl_area widget
* @return void * @return void
*/ */
void graphics_init_buffers(const void *gl_area); void graphics_init_buffers(const int stack_id);
/* /*
* Draws a vertex (x, y, z) * Draws a vertex (x, y, z)
@ -107,7 +127,10 @@ void graphics_init_buffers(const void *gl_area);
* *
* @return void * @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 * 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 * @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 * 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 * @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 * 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 * @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 * Initializes an identity matrix
@ -206,7 +229,7 @@ static inline void compute_mvp(float *res, float phi, float theta, float psi)
* *
* @return shader id * @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; GLuint shader;
int status; int status;
@ -240,31 +263,75 @@ static inline GLuint create_shader(int type, const char *src)
return shader; 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 ***/ /*** 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);

View File

@ -1,49 +0,0 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: OpenGL utils header
*
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <unistd.h>
#include <stdbool.h>
#include <GL/glu.h>
/*
* 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);

View File

@ -1,110 +0,0 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: OpenGL utils header
*
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "base.h"
#include <unistd.h>
#include <stdbool.h>
#include <epoxy/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
/*
* 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);

View File

@ -33,8 +33,15 @@
* Z - Z = NORTH - SOUTH = bleu - jaune * Z - Z = NORTH - SOUTH = bleu - jaune
*/ */
int draw_one_arrow_vertex (int space_X_int, int space_Y_int, int space_Z_int, int draw_one_arrow_vertex (const int stack_id,
int weight, int site, int arrow_x, int arrow_y, int arrow_z, int console) 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); 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), 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); vz = (2 * k / space_Z_int - 1) * space_Z_int / max + (1 / max);
graphics_draw_vertex(vx, vy, vz, console); graphics_draw_vertex(stack_id, vx, vy, vz);
graphics_draw_color(0.4f, 0.4f, 0.4f, console); graphics_draw_color(stack_id, 0.4f, 0.4f, 0.4f);
// réduit légèrement les longueurs des flèches // réduit légèrement les longueurs des flèches
// pour qu'elles s'arrêtent avant les faces des cubes // 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){ switch(site){
case EAST: case EAST:
graphics_draw_vertex (vx - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vy, vz, console); graphics_draw_vertex (stack_id, vx - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vy, vz);
graphics_draw_color (1.0f, 0.0f, 0.0f, console); graphics_draw_color (stack_id, 1.0f, 0.0f, 0.0f);
break; break;
case WEST: case WEST:
graphics_draw_vertex (vx - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vy, vz, console); graphics_draw_vertex (stack_id, vx - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vy, vz);
graphics_draw_color (0.0f, 1.0f, 1.0f, console); graphics_draw_color (stack_id, 0.0f, 1.0f, 1.0f);
break; break;
case ZENITH: case ZENITH:
graphics_draw_vertex (vx, vy - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vz, console); graphics_draw_vertex (stack_id, vx, vy - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vz);
graphics_draw_color(0.0f, 0.6f, 0.1f, console); graphics_draw_color(stack_id, 0.0f, 0.6f, 0.1f);
break; break;
case NADIR: case NADIR:
graphics_draw_vertex (vx, vy - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vz, console); graphics_draw_vertex (stack_id, vx, vy - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vz);
graphics_draw_color(0.6f, 0.1f, 0.7f, console); graphics_draw_color(stack_id, 0.6f, 0.1f, 0.7f);
break; break;
case SOUTH: case SOUTH:
graphics_draw_vertex (vx, vy, vz - (site % 2 + 1) * (1 / max) + (site % 2 + 1) * arrow_tip_padding, console); graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 + 1) * (1 / max) + (site % 2 + 1) * arrow_tip_padding);
graphics_draw_color(0.05f, 0.4f, 1.0f, console); graphics_draw_color(stack_id, 0.05f, 0.4f, 1.0f);
break; break;
case NORTH: case NORTH:
graphics_draw_vertex (vx, vy, vz - (site % 2 - 2) * (1 / max) + (site % 2 - 2) * arrow_tip_padding, console); graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 - 2) * (1 / max) + (site % 2 - 2) * arrow_tip_padding);
graphics_draw_color(1.0f, 1.0f, 0.0f, console); graphics_draw_color(stack_id, 1.0f, 1.0f, 0.0f);
break; break;
default: 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; 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;
}

View File

@ -25,10 +25,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include "../../include/graphics.h" #include "../../include/graphics.h"
#include "../../include/arrows.h"
#include "../../include/displays.h"
/* Prints the arrows[] array /* Prints the arrows[] array
* *

186
src/graphics/draw.c Normal file
View File

@ -0,0 +1,186 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* Writes values to describe a vertex at (x,y,z) intoq the vertex buffer
*
* @param coords GLfloat(x,y,z)
*
* @return void
*/
#include <stdlib.h>
#include <time.h>
#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();
}

View File

@ -28,38 +28,12 @@
#include "../../include/base.h" #include "../../include/base.h"
#include "../../include/ui.h" #include "../../include/ui.h"
#include "../../include/graphics.h" #include "../../include/graphics.h"
#include "../../include/arrows.h"
#include "../../include/grid.h"
// #include <bits/stdc++.h> 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 #define TEST 0
/* size_t graphic_stack_size = 0;
* Dynamic array of ptrs to dynamically allocated gl_area_entry int *free_stack_slot = NULL;
*/ size_t free_stack_slot_size = 0;
struct gl_area_entry **gl_area_array = NULL;
/* /*
* Prints verbose human-readable debug messages * 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 * Initializes graphical stack
*
* @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
* *
* @param gl_area, ptr to the gl_area widget * @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; int cur_id = 0;
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;
entry = graphics_find_glarea_from_ptr(gl_area); if (glarea == NULL)
return 0;
if (entry == NULL) { if (graphic_stack == NULL) {
errno = EFAULT; graphic_stack = g_malloc(sizeof(struct graphic_stack_t));
perror("gl_area_array entry not found"); graphic_stack_size = 1;
return false; } 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 graphic_stack[cur_id].id = cur_id;
vertex_shader = read_file(VERTEX_SHADER_FILE); graphic_stack[cur_id].glarea = glarea;
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;
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
// Check if not already initialized if (!graphics_init_shaders(cur_id))
if (graphics_find_glarea_from_ptr(gl_area)) { return 0;
errno = EEXIST;
perror("gl_area_array already exists");
return false;
}
// Get actual array size graphics_init_buffers(cur_id);
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);
glDebugMessageCallback(graphics_debug_callback, NULL); 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 * @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 (id == 0 ||
id >= graphic_stack_size ||
if (entry == NULL) { graphic_stack_size == 0 ||
errno = EFAULT; graphic_stack == NULL)
perror("gl_area_array entry not found");
return false; 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; 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 /* TODO
* #pragma omp parallel schedule(static, 12) * #pragma omp parallel schedule(static, 12)
* void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {} * 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) * Attention, les vertex centraux de chaque unité d'espace (cube)
* peuvent être redondants (max 6) * 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); 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) { if (randomize) {
space_X = 1 + rand() % randomize; space_X = 1 + rand() % randomize;
space_Y = 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_space_ridges_lines (console);
draw_grids_on_space_faces_vertex (space_X, space_Y, space_Z, 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; graphic_stack[stack_id].buffer_vertex_0_arrow =
buffer_colors_0_arrow = buffer_colors_size; graphic_stack[stack_id].buffer_vertex_size;
buffer_lines_0_arrow = buffer_lines_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++) 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 1, // load
rand() % 6, // site rand() % 6, // site
rand() % space_X, // x rand() % space_X, // x
rand() % space_Y, // y rand() % space_Y, // y
rand() % space_Z, // z rand() % space_Z); // z
console);
if (i > 0 && i % 1000 == 0) printf("|"); if (i > 0 && i % 1000 == 0) printf("|");
if (i > 0 && i % 100000 == 0) printf("\n"); if (i > 0 && i % 100000 == 0) printf("\n");
} }
else for (int i = 0; i < 6; i++) 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); 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 = 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);
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;
} }

View File

@ -22,131 +22,139 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdlib.h>
#include <time.h>
#include "../../include/base.h" #include "../../include/base.h"
#include "../../include/ui.h"
#include "../../include/graphics.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); 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 (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 (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 (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 (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 (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 (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 (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
graphics_draw_color (0.8f, 0.6f, 0.5f, console); graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
return 8; 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 (stack_id, 0, 1); graphics_draw_line (stack_id, 7, 4);
graphics_draw_line ( 0, 2, console); graphics_draw_line ( 7, 5, console); graphics_draw_line (stack_id, 0, 2); graphics_draw_line (stack_id, 7, 5);
graphics_draw_line ( 0, 3, console); graphics_draw_line ( 7, 6, console); 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 (stack_id, 1, 4); graphics_draw_line (stack_id, 2, 4);
graphics_draw_line ( 1, 5, console); graphics_draw_line ( 3, 5, console); graphics_draw_line (stack_id, 1, 5); graphics_draw_line (stack_id, 3, 5);
graphics_draw_line ( 2, 6, console); graphics_draw_line ( 3, 6, console); graphics_draw_line (stack_id, 2, 6); graphics_draw_line (stack_id, 3, 6);
return 12; 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); float i, max = fmax(x, y); max = fmax(max, z);
for (i = 1; i < x; i++) { for (i = 1; i < x; i++) {
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 ((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 ((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 ((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_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
} }
/* offset_vertex += (x - 1) * 4; */ /* offset_colors += (x - 1) * 4; */ /* offset_vertex += (x - 1) * 4; */ /* offset_colors += (x - 1) * 4; */
for (i = 1; i < y; i++) { for (i = 1; i < y; i++) {
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 (- 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 ( 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 ( 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_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
} }
/* offset_vertex += (y - 1) * 4; */ /* offset_colors += (y - 1) * 4; */ /* offset_vertex += (y - 1) * 4; */ /* offset_colors += (y - 1) * 4; */
for (i = 1; i < z; i++) { for (i = 1; i < z; i++) {
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 (- 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 ( 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 ( 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_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
graphics_draw_color (0.55f, 0.55f, 0.55f, console); graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
} }
return (x + y + z - 3) * 3; 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; offset_vertex = offset_vertex / 3;
for (int i = 0; i < x - 1; i ++) { 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 (stack_id, offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2);
graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
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); */
} }
offset_vertex += (x - 1) * 4; offset_vertex += (x - 1) * 4;
for (int i = 0; i < y - 1; i ++) { 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 (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
/* graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); */ graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
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);
} }
offset_vertex += (y - 1) * 4; offset_vertex += (y - 1) * 4;
for (int i = 0; i < z - 1; i ++) { 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 (stack_id, offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1);
/* graphics_draw_line (offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2, console); */ graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
/* 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);
} }
return (x + y + z - 3) * 4; return (x + y + z - 3) * 4;

175
src/graphics/init.c Normal file
View File

@ -0,0 +1,175 @@
/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include <stdlib.h>
#include <time.h>
#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;
}

View File

@ -27,11 +27,13 @@
#include "../../include/base.h" #include "../../include/base.h"
#include "../../include/ui.h" #include "../../include/ui.h"
#include "../../include/graphics.h"
float rotation_angles[N_AXIS] = { 0.0 }; // Rotation angles on each axis float rotation_angles[N_AXIS] = { 0.0 }; // Rotation angles on each axis
GtkWidget *gl_area = NULL; GtkWidget *gl_area = NULL;
struct graphic_stack_t *graphic_stack = NULL;
static inline GtkWidget *create_axis_slider(int axis) static inline GtkWidget *create_axis_slider(int axis)
{ {