329 lines
11 KiB
C
329 lines
11 KiB
C
/*
|
|
* 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>
|
|
* 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>
|
|
#include "../../include/base.h"
|
|
#include "../../include/ui.h"
|
|
#include "../../include/parsing.h"
|
|
#include "../../include/graphics.h"
|
|
|
|
#define TEST 0
|
|
|
|
struct graphic_stack_t *graphic_stack = 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
|
|
*
|
|
* @param source, XXX
|
|
* type, XXX
|
|
* id, XXX
|
|
* severity, XXX
|
|
* length, XXX
|
|
* msg, XXX
|
|
* data, XXX
|
|
*
|
|
* @return void
|
|
*/
|
|
static void graphics_debug_callback(GLenum source, GLenum type, GLuint id,
|
|
GLenum severity, GLsizei length,
|
|
const GLchar *msg, const void *data)
|
|
{
|
|
const char *errsource;
|
|
const char *errtype;
|
|
const char *errseverity;
|
|
const GLubyte *string;
|
|
GLenum code;
|
|
|
|
switch (source) {
|
|
case GL_DEBUG_SOURCE_API: errsource = "API"; break;
|
|
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: errsource = "WINDOW SYSTEM"; break;
|
|
case GL_DEBUG_SOURCE_SHADER_COMPILER: errsource = "SHADER COMPILER"; break;
|
|
case GL_DEBUG_SOURCE_THIRD_PARTY: errsource = "THIRD PARTY"; break;
|
|
case GL_DEBUG_SOURCE_APPLICATION: errsource = "APPLICATION"; break;
|
|
case GL_DEBUG_SOURCE_OTHER: errsource = "UNKNOWN"; break;
|
|
default: errsource = "UNKNOWN"; break;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_DEBUG_TYPE_ERROR: errtype = "ERROR"; break;
|
|
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: errtype = "DEPRECATED BEHAVIOR";break;
|
|
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: errtype = "UNDEFINED BEHAVIOR"; break;
|
|
case GL_DEBUG_TYPE_PORTABILITY: errtype = "PORTABILITY"; break;
|
|
case GL_DEBUG_TYPE_PERFORMANCE: errtype = "PERFORMANCE"; break;
|
|
case GL_DEBUG_TYPE_OTHER: errtype = "OTHER"; break;
|
|
case GL_DEBUG_TYPE_MARKER: errtype = "MARKER"; break;
|
|
default: errtype = "UNKNOWN"; break;
|
|
}
|
|
|
|
switch (severity) {
|
|
case GL_DEBUG_SEVERITY_HIGH: errseverity = "CRITICAL"; break;
|
|
case GL_DEBUG_SEVERITY_MEDIUM: errseverity = "ERROR"; break;
|
|
case GL_DEBUG_SEVERITY_LOW: errseverity = "WARNING"; break;
|
|
case GL_DEBUG_SEVERITY_NOTIFICATION: errseverity = "INFO"; break;
|
|
default: errseverity = "UNKNOWN"; break;
|
|
}
|
|
|
|
code = glGetError();
|
|
string = gluErrorString(code);
|
|
|
|
g_printerr("[%s] %s (%s) from %s: %s\n",
|
|
errseverity, string, errtype, errsource, msg);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* Initializes graphical stack
|
|
*
|
|
* @param gl_area, ptr to the gl_area widget
|
|
*
|
|
* @return id if initialized
|
|
*/
|
|
int graphics_init(void *error_buffer)
|
|
{
|
|
int cur_id = 0;
|
|
struct graphic_stack_t *stack;
|
|
|
|
/* g_printerr("[debug] graphics_init()\n"); */
|
|
|
|
if (graphic_stack == NULL) {
|
|
graphic_stack = g_malloc0(sizeof(struct graphic_stack_t));
|
|
graphic_stack_size = 1;
|
|
/* g_printerr("[debug] graphics_init(): init graphic_stack @ %p\n", graphic_stack); */
|
|
} 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));
|
|
}
|
|
}
|
|
|
|
memset(&graphic_stack[cur_id], 0, sizeof(struct graphic_stack_t));
|
|
|
|
/* g_printerr("[debug] graphics_init() : graphic_stack (@0x%p) has %ld elements\n", */
|
|
/* graphic_stack, */
|
|
/* graphic_stack_size); */
|
|
|
|
stack = &graphic_stack[cur_id];
|
|
stack->id = cur_id;
|
|
|
|
glEnable(GL_DEBUG_OUTPUT);
|
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
glEnable(GL_MULTISAMPLE);
|
|
|
|
if (!graphics_init_shaders(cur_id))
|
|
return -1;
|
|
|
|
//print_stack(cur_id);
|
|
|
|
graphics_init_buffers(cur_id);
|
|
|
|
glDebugMessageCallback(graphics_debug_callback, NULL);
|
|
|
|
//print_stack(cur_id);
|
|
|
|
return cur_id;
|
|
}
|
|
|
|
/*
|
|
* Shutdowns a gl_area
|
|
*
|
|
* @param gl_area, ptr to the gl_area widget
|
|
*
|
|
* @return true if success
|
|
*/
|
|
bool graphics_shutdown(const int id, void *error_buffer)
|
|
{
|
|
struct graphic_stack_t *stack;
|
|
|
|
if (id >= graphic_stack_size ||
|
|
graphic_stack_size == 0 ||
|
|
graphic_stack == NULL)
|
|
return false;
|
|
|
|
stack = &graphic_stack[id];
|
|
|
|
//XXX
|
|
free(stack->arrows_ptr);
|
|
stack->arrows_ptr = NULL;
|
|
stack->arrows_nb = 0;
|
|
|
|
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;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* TODO
|
|
* #pragma omp parallel schedule(static, 12)
|
|
* void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {}
|
|
*
|
|
// assert : space dimensions (x,y,z) > 0
|
|
// assert : arrows localization within space and sites
|
|
// assert : no more than one arrow per address
|
|
// notify : weights are replaced, NOT added (could be !)
|
|
*
|
|
* Init space and arrows (= initial state)
|
|
* and allows ulterior creations, suppressions or modifications of the arrows[] array
|
|
*
|
|
* draws the space()
|
|
* triggers set_arrows() that modifies the list () and draws arrows
|
|
*
|
|
* Initialisation du générateur pseudo-aléatoire
|
|
* Attention, les vertex centraux de chaque unité d'espace (cube)
|
|
* peuvent être redondants (max 6)
|
|
*/
|
|
void graphics_model_setup (const int stack_id)
|
|
{
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/* I N I T I A L D A T A S P E C I F I C A T I O N */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
|
char dimension;
|
|
long space_X;
|
|
long space_Y;
|
|
long space_Z;
|
|
long announced_arrows_nb;
|
|
int density_max;
|
|
char multiplicity;
|
|
|
|
dimension = model_get_dim();
|
|
|
|
g_print("[GRAPH DEBUG] dim = %d\n", dimension);
|
|
|
|
space_X = 1;
|
|
space_Y = 1;
|
|
space_Z = 1;
|
|
|
|
switch(dimension) {
|
|
case 3:
|
|
space_Z = model_get_dim_value("z");
|
|
case 2:
|
|
space_Y = model_get_dim_value("y");
|
|
|
|
// even in 1D, we must be able to see a grid
|
|
if (!space_Y)
|
|
space_Y = 1;
|
|
case 1:
|
|
space_X = model_get_dim_value("x");
|
|
if (!space_X)
|
|
space_X = 1;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
g_print("[GRAPH DEBUG] x = %ld\n", space_X);
|
|
g_print("[GRAPH DEBUG] y = %ld\n", space_Y);
|
|
g_print("[GRAPH DEBUG] z = %ld\n", space_Z);
|
|
|
|
density_max = space_X * space_Y * space_Z;
|
|
stack->arrows_nb = 0;
|
|
|
|
multiplicity = model_get_multiplicity();
|
|
g_print("[GRAPH DEBUG] site_multiplicity = %ld\n", multiplicity);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/* S P A C E D R A W I N G */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
draw_space_ridges_vertex (stack_id, stack->buffer_vertex_size,
|
|
space_X, space_Y, space_Z);
|
|
draw_space_ridges_lines (stack_id);
|
|
draw_grids_on_space_faces_vertex (stack_id, space_X, space_Y, space_Z);
|
|
draw_grids_on_space_faces_lines (stack_id, stack->buffer_lines_size,
|
|
space_X, space_Y, space_Z);
|
|
|
|
stack->buffer_vertex_0_arrow = stack->buffer_vertex_size;
|
|
stack->buffer_colors_0_arrow = stack->buffer_colors_size;
|
|
stack->buffer_lines_0_arrow = stack->buffer_lines_size;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/* A R R O W S D R A W I N G */
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
char state_id[30] = {0};
|
|
struct arrow_t arrow = {0};
|
|
|
|
assert(model_get_next_state(&state_id));
|
|
|
|
g_print("[GRAPH DEBUG] first state is = %s\n", state_id);
|
|
|
|
announced_arrows_nb = model_get_state_arrows_count(state_id);
|
|
|
|
g_print("[GRAPH DEBUG] announced_arrows_nb is = %ld\n", announced_arrows_nb);
|
|
|
|
while (model_get_next_arrow(&arrow, &state_id, dimension)) {
|
|
g_print("[GRAPH DEBUG] cur arrow has x = %d\n", arrow.x);
|
|
stack->arrows_nb =
|
|
set_arrow (stack_id, stack->arrows_nb, space_X, space_Y, space_Z,
|
|
arrow.load, // load
|
|
arrow.site, // site
|
|
arrow.x, // x
|
|
arrow.y, // y
|
|
arrow.z); // z
|
|
}
|
|
|
|
if (stack->arrows_nb != announced_arrows_nb)
|
|
g_printerr("ARGH : all the arrows have not been parsed !\n");
|
|
}
|