Compare commits
2 Commits
4b352f326e
...
6d958c8466
Author | SHA1 | Date |
---|---|---|
Jean Sirmai | 6d958c8466 | |
Jean Sirmai | 9979d5f725 |
11
Makefile
11
Makefile
|
@ -1,12 +1,21 @@
|
||||||
.PHONY: run clean install all
|
.PHONY: run clean install all
|
||||||
|
.DELETE_ON_ERROR: $(BINDIR)/Getting_Started_with_GTK
|
||||||
.DEFAULT_GOAL: all
|
.DEFAULT_GOAL: all
|
||||||
|
|
||||||
|
NTHREADS= $(shell nproc)
|
||||||
|
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=`pkg-config --cflags gtk4 gl glib-2.0`
|
CFLAGS=`pkg-config --cflags gtk4 gl glib-2.0`
|
||||||
LDFLAGS=`pkg-config --libs gtk4 gl glib-2.0`
|
LDFLAGS=`pkg-config --libs gtk4 gl glib-2.0`
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
DEBUG = -ggdb -fno-omit-frame-pointer
|
DEBUG = -ggdb -fno-omit-frame-pointer #-fdiagnostics-color=always -fsanitize=bounds -fstack-check
|
||||||
OPTIMIZE = -O3
|
OPTIMIZE = -O3
|
||||||
|
INCLUDE= $(shell pkg-config --cflags glib-2.0 libxml-2.0 gtk4)
|
||||||
|
LIBS= $(shell pkg-config --libs glib-2.0 libxml-2.0 gtk4) -lGL -lGLU -lm -lepoxy -lX11 -lGLEW
|
||||||
|
|
||||||
|
BINDIR=bin
|
||||||
|
BUILDDIR=build
|
||||||
|
SRCDIR=src
|
||||||
|
|
||||||
sources = $(shell find . -maxdepth 1 -type f -name "*.c")
|
sources = $(shell find . -maxdepth 1 -type f -name "*.c")
|
||||||
objects = $(patsubst %.c,%.o,$(sources))
|
objects = $(patsubst %.c,%.o,$(sources))
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Gem-graph OpenGL experiments
|
||||||
|
*
|
||||||
|
* Desc: Base header
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <glib-2.0/glib.h>
|
||||||
|
//#define G_APPLICATION_DEFAULT_FLAGS 0
|
||||||
|
|
||||||
|
enum { X_AXIS, Y_AXIS, Z_AXIS, N_AXIS }; // Graphical axis
|
||||||
|
enum { HOME_MODE, RUN_MODE, EDIT_MODE, PRESENTATION_MODE, N_MODE }; // Gem-graph modes
|
||||||
|
struct arrow_t { uint load; uint site; uint x; uint y; uint z; }; // describes an arrow
|
||||||
|
static inline char *read_file(char *filename);
|
||||||
|
|
||||||
|
/* I'm standing on Earth (or any spinning spheroid) and looking towards its North pole, then :
|
||||||
|
X - X = EAST - WEST = rouge - cyan
|
||||||
|
Y - Y = ZENITH - NADIR = vert - magenta (fuschia)
|
||||||
|
Z - Z = NORTH - SOUTH = bleu - jaune */
|
||||||
|
|
||||||
|
#define EAST 0 // + x rouge
|
||||||
|
#define WEST 1 // - x cyan
|
||||||
|
#define ZENITH 2 // + y vert
|
||||||
|
#define NADIR 3 // - y magenta
|
||||||
|
#define SOUTH 4 // + z bleu
|
||||||
|
#define NORTH 5 // - z jaune
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* char *read_file(char *filename) reads a file from filename into a provided buffer
|
||||||
|
*
|
||||||
|
* @param filename, file name
|
||||||
|
* contents, target ptr
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
static inline char *read_file(char *filename)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int filesize;
|
||||||
|
char *contents;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if(fd < 0) {
|
||||||
|
printf("Couldn't read file: %s\n",filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesize = lseek(fd, 0, SEEK_END) + 1 ;
|
||||||
|
contents = g_malloc(filesize * sizeof(char));
|
||||||
|
assert (contents);
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
read(fd,contents,filesize);
|
||||||
|
|
||||||
|
contents[filesize-1] = '\0';
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ GtkWidget *get_SPACE_VIEW_box(){
|
||||||
|
|
||||||
GtkBox *middle_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
|
GtkBox *middle_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2));
|
||||||
gtk_box_append (middle_box, GTK_WIDGET (get_image_ALL_SPACE()));
|
gtk_box_append (middle_box, GTK_WIDGET (get_image_ALL_SPACE()));
|
||||||
|
////////////////////////// gtk_box_append (middle_box, GTK_WIDGET (get_GLArea()));
|
||||||
gtk_box_append (middle_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
|
gtk_box_append (middle_box, GTK_WIDGET (gtk_separator_new (GTK_ORIENTATION_VERTICAL)));
|
||||||
gtk_box_append (middle_box, GTK_WIDGET (right_box));
|
gtk_box_append (middle_box, GTK_WIDGET (right_box));
|
||||||
return GTK_WIDGET (middle_box);
|
return GTK_WIDGET (middle_box);
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
/* */
|
/* */
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#include <gtk-4.0/gtk/gtk.h>
|
||||||
|
|
||||||
#define W 1920
|
#define W 1920
|
||||||
#define H 960
|
#define H 960
|
||||||
#define W_IMAGE W - 320
|
#define W_IMAGE W - 320
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gem-graph-model version="0.2.1">
|
||||||
|
|
||||||
|
<identity>
|
||||||
|
<name>Modèle de test</name>
|
||||||
|
|
||||||
|
<owner>Léontine Patinette</owner>
|
||||||
|
|
||||||
|
<owner_id>2</owner_id>
|
||||||
|
|
||||||
|
<date>1630000000</date>
|
||||||
|
|
||||||
|
<version>1.0</version>
|
||||||
|
|
||||||
|
<g_ref id="Cause" date="1630000000" author="toujours" lang="en">Ref</g_ref>
|
||||||
|
</identity>
|
||||||
|
|
||||||
|
<parameters id="texte" date="0" author="Léontine Trottine.">
|
||||||
|
<simulation>
|
||||||
|
<max_thread>0</max_thread>
|
||||||
|
<max_cycles>9</max_cycles>
|
||||||
|
|
||||||
|
</simulation>
|
||||||
|
|
||||||
|
<space-param>
|
||||||
|
<!-- loop_on_zero="true" anything moved before zero reenters at the end of space-->
|
||||||
|
<!-- loop_on_zero="false" anything moved before zero is lost-->
|
||||||
|
<!-- loop_on_max="true" anything moved beyond max reenters at the zero of space-->
|
||||||
|
<!-- loop_on_max="false" anything moved beyond max is lost-->
|
||||||
|
|
||||||
|
<dimension x="29"/>
|
||||||
|
|
||||||
|
<!-- Site_multiplicity = number of sites in a space unit. -->
|
||||||
|
<!-- Each site points towards a neighbouring space unit. -->
|
||||||
|
<!-- Several arrows can be stacked in the same site. -->
|
||||||
|
|
||||||
|
<site_multiplicity>3</site_multiplicity>
|
||||||
|
|
||||||
|
</space-param>
|
||||||
|
|
||||||
|
</parameters>
|
||||||
|
|
||||||
|
<!-- Model objects definition -->
|
||||||
|
|
||||||
|
<objects id="only dimers in this model" date="1630000000" author="inanimés,... âme ?">
|
||||||
|
<object id="a dimer" date="1630000000" author="Alphonse">
|
||||||
|
<arrow site="1" weight="1" x="0"/>
|
||||||
|
<arrow site="2" weight="1" x="1"/>
|
||||||
|
</object>
|
||||||
|
|
||||||
|
</objects>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Saved space description (initial space is sequence 0) -->
|
||||||
|
|
||||||
|
<savedstates id="texte" date="1630000000" author="Qui courrait dans l'herbe'">
|
||||||
|
<state id="initial" date="1630000000" author="Une souris verte">
|
||||||
|
<arrow site="0" weight="1" x="0"/>
|
||||||
|
<arrow site="1" weight="1" x="1"/>
|
||||||
|
<arrow site="0" weight="1" x="10"/>
|
||||||
|
<arrow site="1" weight="1" x="11"/>
|
||||||
|
<arrow site="0" weight="1" x="20"/>
|
||||||
|
<arrow site="1" weight="1" x="21"/>
|
||||||
|
|
||||||
|
<!-- Three dimers 1-1 are drawn in the global space
|
||||||
|
at locations (0,1) (10,11) and (20,21) -->
|
||||||
|
|
||||||
|
</state>
|
||||||
|
|
||||||
|
</savedstates>
|
||||||
|
|
||||||
|
<!-- Model transitions definition (rules) -->
|
||||||
|
<!-- In this version : <xs:sequence minOccurs="0" maxOccurs="unbounded">-->
|
||||||
|
<!-- Transitions should be edited by hand and written in a 'human-readable' format -->
|
||||||
|
|
||||||
|
<conditions id="random walk of dimers" date="1630000000" author="Zazard le lézard !">
|
||||||
|
|
||||||
|
<condition site="1" weight="1" node_id="1" parent="0" x="0"/>
|
||||||
|
<condition site="2" weight="1" node_id="2" parent="1" x="1"/>
|
||||||
|
<!-- as soon as conditions 1 and 2 are satisfied, a dimer is identified at atation (0,1). -->
|
||||||
|
|
||||||
|
<condition site="1" weight="0" node_id="3" parent="2" x="2"/>
|
||||||
|
<!-- as soon as condition 3 is satisfied,
|
||||||
|
the neighbouring space unit to East of the dimer is empty
|
||||||
|
and the dimer identified by conditions (1,2) can be moved to East. -->
|
||||||
|
|
||||||
|
<condition site="2" weight="0" node_id="4" parent="2" x="-1"/>
|
||||||
|
<!-- as soon as condition 4 is satisfied,
|
||||||
|
the neighbouring space unit to West of the dimer is empty
|
||||||
|
and the dimer identified by conditions (1,2) can be moved to West. -->
|
||||||
|
|
||||||
|
</conditions>
|
||||||
|
|
||||||
|
<transitions>
|
||||||
|
|
||||||
|
<transition id="move_a_dimer_to_east" date="1630000000" author="Pas moi..."
|
||||||
|
parent="3" probability="1">
|
||||||
|
|
||||||
|
<arrow site="1" weight="0" x="0"/>
|
||||||
|
<arrow site="2" weight="0" x="1"/>
|
||||||
|
<arrow site="1" weight="1" x="1"/>
|
||||||
|
<arrow site="2" weight="1" x="2"/>
|
||||||
|
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
<transition id="move_a_dimer_to_west" date="1630000000" author="Ni moi !"
|
||||||
|
parent="4" probability="1">
|
||||||
|
|
||||||
|
<arrow site="1" weight="0" x="0"/>
|
||||||
|
<arrow site="2" weight="0" x="1"/>
|
||||||
|
<arrow site="2" weight="1" x="0"/>
|
||||||
|
<arrow site="1" weight="1" x="1"/>
|
||||||
|
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
</transitions>
|
||||||
|
|
||||||
|
</gem-graph-model>
|
|
@ -0,0 +1,323 @@
|
||||||
|
/*
|
||||||
|
* Gem-graph OpenGL experiments
|
||||||
|
*
|
||||||
|
* Desc: User interface functions
|
||||||
|
*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include <gtk-4.0/gtk/gtk.h>
|
||||||
|
#include <glib-2.0/glib.h>
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
#include "contain.h"
|
||||||
|
#include "graph_area.h"
|
||||||
|
|
||||||
|
struct stack_index_t {
|
||||||
|
long stack_id;
|
||||||
|
void *container_widget;
|
||||||
|
void *gl_area;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct stack_index_t *stack_index = NULL;
|
||||||
|
size_t stack_index_size = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and returns stack_id
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns stack_id
|
||||||
|
*/
|
||||||
|
long ui_get_graphic_stack(void *container_widget)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
return stack_index[i].stack_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and returns stack_id
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns stack_id
|
||||||
|
*/
|
||||||
|
long ui_is_graphic_stack_ready(void *container_widget)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
return stack_index[i].stack_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and initializes OpenGL for it
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
bool ui_init_graphic_stack(void *container_widget, GError *error_buffer)
|
||||||
|
{
|
||||||
|
//g_printerr("[debug] ui_init_graphic_stack()\n");
|
||||||
|
|
||||||
|
//g_printerr("[debug] ui_init_graphic_stack() : target is %p\n", container_widget);
|
||||||
|
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
//g_printerr("[debug] ui_init_graphic_stack() : i is %d\n", i);
|
||||||
|
//g_printerr("[debug] ui_init_graphic_stack() : target would be %p\n",
|
||||||
|
//stack_index[i].container_widget);
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
////////////////////////// stack_index[i].stack_id = graphics_init(&error_buffer);
|
||||||
|
//g_printerr("[debug] ui_init_graphic_stack() : stack_id is %d\n",
|
||||||
|
//stack_index[i].stack_id);
|
||||||
|
if (stack_index[i].stack_id >= 0)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and shutdowns OpenGL for it
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
bool ui_shutdown_graphic_stack(void *container_widget, GError *error_buffer)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
////////////////////////// if (graphics_shutdown(stack_index[i].stack_id,
|
||||||
|
////////////////////////// &error_buffer) == false) {
|
||||||
|
////////////////////////// return false;
|
||||||
|
////////////////////////// }
|
||||||
|
stack_index[i].stack_id = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ui_clean_stack_index(void)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
stack_index[i].stack_id = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and triggers OpenGL for drawing
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
bool ui_render_stack(GtkWidget *container_widget)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
////////////////////////// graphics_draw(stack_index[i].stack_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for stack entry and triggers OpenGL for drawing
|
||||||
|
*
|
||||||
|
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
bool ui_update_axis_stack(GtkWidget *container_widget, int axis, int value)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||||
|
////////////////////////// graphic_stack[stack_index[i].stack_id].rotation_angles[axis] = value;
|
||||||
|
gtk_widget_queue_draw((GtkWidget*)(stack_index[i].gl_area));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for every stack entry and shutdowns OpenGL for it
|
||||||
|
*
|
||||||
|
* @params void
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
void ui_shutdown_all_graphic_stacks(void)
|
||||||
|
{
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
////////////////////////// graphics_shutdown(stack_index[i].stack_id, NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a slider widget
|
||||||
|
*
|
||||||
|
* @params axis, meaning which axis we're building (for label)
|
||||||
|
*
|
||||||
|
* @returns GtkWidget*, pointer to the new widget
|
||||||
|
*/
|
||||||
|
GtkWidget *create_axis_slider(int axis)
|
||||||
|
{
|
||||||
|
GtkWidget *box, *label, *slider;
|
||||||
|
GtkAdjustment *adj;
|
||||||
|
const char *text;
|
||||||
|
|
||||||
|
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||||
|
|
||||||
|
switch (axis) {
|
||||||
|
case X_AXIS:
|
||||||
|
text = "X";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Y_AXIS:
|
||||||
|
text = "Y";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Z_AXIS:
|
||||||
|
text = "Z";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
label = gtk_label_new(text);
|
||||||
|
gtk_box_append(GTK_BOX(box), label);
|
||||||
|
gtk_widget_set_visible (label, TRUE);
|
||||||
|
|
||||||
|
adj = gtk_adjustment_new(0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
|
||||||
|
////////////////////////// g_signal_connect(adj, "value-changed",
|
||||||
|
////////////////////////// G_CALLBACK(on_axis_value_change),
|
||||||
|
////////////////////////// (gpointer) label);
|
||||||
|
slider = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adj);
|
||||||
|
gtk_box_append(GTK_BOX(box), slider);
|
||||||
|
gtk_widget_set_hexpand(slider, TRUE);
|
||||||
|
gtk_widget_set_visible (slider, TRUE);
|
||||||
|
|
||||||
|
gtk_widget_set_visible (box, TRUE);
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates GLArea and indexes it
|
||||||
|
*
|
||||||
|
* @params target_mode, meaning which ui_stack we're on
|
||||||
|
* target_widget, meaning the box that will host the GLArea
|
||||||
|
*
|
||||||
|
* @returns bool, true if success
|
||||||
|
*/
|
||||||
|
bool ui_setup_glarea(int target_mode, GtkWidget *target_widget)
|
||||||
|
{
|
||||||
|
GtkWidget *gl_area;
|
||||||
|
|
||||||
|
////g_printerr("[debug] ui_setup_glarea()\n");
|
||||||
|
|
||||||
|
assert(target_widget);
|
||||||
|
|
||||||
|
////g_printerr("[debug] ui_setup_glarea() : target is %p\n", target_widget);
|
||||||
|
|
||||||
|
if (stack_index == NULL) {
|
||||||
|
stack_index = g_malloc(sizeof(struct stack_index_t));
|
||||||
|
stack_index_size = 1;
|
||||||
|
} else {
|
||||||
|
// look for stack_index entry
|
||||||
|
for (int i = 0; i < stack_index_size; i++) {
|
||||||
|
if (stack_index[i].container_widget == (void *)target_widget) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create entry
|
||||||
|
stack_index =
|
||||||
|
g_realloc(stack_index,
|
||||||
|
++stack_index_size * sizeof(struct stack_index_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_area = GTK_WIDGET(gtk_gl_area_new());
|
||||||
|
assert(gl_area);
|
||||||
|
|
||||||
|
//gtk_widget_set_size_request(gl_area, 1000, 1000);
|
||||||
|
gtk_gl_area_set_auto_render(GTK_GL_AREA(gl_area), true);
|
||||||
|
gtk_widget_set_hexpand(gl_area, TRUE);
|
||||||
|
gtk_widget_set_vexpand(gl_area, TRUE);
|
||||||
|
//gtk_widget_set_halign(gl_area, GTK_ALIGN_CENTER);
|
||||||
|
//gtk_widget_set_valign(gl_area, GTK_ALIGN_CENTER);
|
||||||
|
|
||||||
|
// The main "draw" call for GtkGLArea
|
||||||
|
////////////////////////// g_signal_connect(GTK_GL_AREA(gl_area),
|
||||||
|
////////////////////////// "render",
|
||||||
|
////////////////////////// G_CALLBACK(on_glarea_render), NULL);
|
||||||
|
|
||||||
|
////////////////////////// g_signal_connect(gl_area,
|
||||||
|
////////////////////////// "realize",
|
||||||
|
////////////////////////// G_CALLBACK(on_glarea_realize), NULL);
|
||||||
|
|
||||||
|
////////////////////////// g_signal_connect(gl_area,
|
||||||
|
////////////////////////// "unrealize",
|
||||||
|
////////////////////////// G_CALLBACK(on_glarea_unrealize), NULL);
|
||||||
|
|
||||||
|
stack_index[stack_index_size-1].container_widget =
|
||||||
|
(void*)target_widget;
|
||||||
|
|
||||||
|
stack_index[stack_index_size-1].gl_area = (void*)gl_area;
|
||||||
|
|
||||||
|
////g_printerr("[debug] ui_setup_glarea() : set target to %p\n", target_widget);
|
||||||
|
|
||||||
|
////g_printerr("[debug] ui_setup_glarea() : stack_index (@0x%p) had %ld elements\n",
|
||||||
|
//stack_index,
|
||||||
|
//stack_index_size);
|
||||||
|
|
||||||
|
gtk_box_append(GTK_BOX(target_widget), gl_area);
|
||||||
|
gtk_widget_set_visible (GTK_WIDGET (gl_area), TRUE);
|
||||||
|
|
||||||
|
// Create sliders
|
||||||
|
for(int i = 0; i < N_AXIS; i++)
|
||||||
|
gtk_box_append(GTK_BOX(target_widget), create_axis_slider(i));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
* Gem-graph OpenGL experiments
|
||||||
|
*
|
||||||
|
* Desc: OpenGL utils header
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "base.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <epoxy/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#include <GL/glext.h>
|
||||||
|
#include <cglm/cglm.h>
|
||||||
|
|
||||||
|
#define VERTEX_SHADER_FILE "src/graphics/shaders/shader.vert"
|
||||||
|
#define FRAG_SHADER_FILE "src/graphics/shaders/shader.frag"
|
||||||
|
#define GL_TARGET_MAJOR_VERSION 0
|
||||||
|
#define GL_TARGET_MINOR_VERSION 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure describing a gl_area and its parameters, used to create a table
|
||||||
|
* of Gem-graph client current gl_areas
|
||||||
|
*/
|
||||||
|
struct graphic_stack_t {
|
||||||
|
|
||||||
|
int id;
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
float rotation_angles[N_AXIS]; // Rotation angles on each axis
|
||||||
|
|
||||||
|
GLuint vao; // init_buffers
|
||||||
|
GLuint position_buffer; // shutdown, draw
|
||||||
|
GLuint color_buffer; // shutdown, draw
|
||||||
|
GLuint program; // shutdown, init_shaders, draw
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamic array of ptrs to dynamically allocated gl_area_entry
|
||||||
|
*/
|
||||||
|
extern struct graphic_stack_t *graphic_stack;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes a gl_area
|
||||||
|
*
|
||||||
|
* @param gl_area, ptr to the gl_area widget
|
||||||
|
*
|
||||||
|
* @return true if initialized
|
||||||
|
*/
|
||||||
|
int graphics_init(void *error_buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shutdowns a gl_area
|
||||||
|
*
|
||||||
|
* @param gl_area, ptr to the gl_area widget
|
||||||
|
*
|
||||||
|
* @return true if success
|
||||||
|
*/
|
||||||
|
bool graphics_shutdown(const int stack_id, void *error_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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws a vertex (x, y, z)
|
||||||
|
* if (console) prints (x, y, z) values to console
|
||||||
|
*
|
||||||
|
* @param GLfloat x, GLfloat y, GLfloat z
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void graphics_draw_vertex (const int stack_id,
|
||||||
|
GLfloat x,
|
||||||
|
GLfloat y,
|
||||||
|
GLfloat z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws the color (r, g, b) associated to a vertex
|
||||||
|
* if (console) prints (r, g, b) values to console
|
||||||
|
*
|
||||||
|
* @param GLfloat r, GLfloat g, GLfloat b
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param coords GLuint (a,b)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param coords GLuint (a,b,c)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void graphics_draw_plan (const int stack_id, GLuint a, GLuint b, GLuint c);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Created and compile a shader
|
||||||
|
*
|
||||||
|
* @param type, shader type
|
||||||
|
* src, source code of shader
|
||||||
|
*
|
||||||
|
* @return shader id
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
static inline GLuint create_shader(const int stack_id, 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;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
static inline void print_stack(int stack_id)
|
||||||
|
{
|
||||||
|
static int n = 0;
|
||||||
|
|
||||||
|
printf("\n[n=%d]***************", n);
|
||||||
|
|
||||||
|
printf("id = %d\tmode = %d\n",
|
||||||
|
graphic_stack[stack_id].id,
|
||||||
|
graphic_stack[stack_id].mode);
|
||||||
|
|
||||||
|
printf("rotation_angles = ");
|
||||||
|
for (int i = 0; i < N_AXIS; i++) {
|
||||||
|
printf("%f\t", graphic_stack[stack_id].rotation_angles[i]); // Rotation angles on each axis
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("vao = %d\n", graphic_stack[stack_id].vao);
|
||||||
|
printf("position_buffer = %d\n", graphic_stack[stack_id].position_buffer);
|
||||||
|
printf("color_buffer = %d\n", graphic_stack[stack_id].color_buffer);
|
||||||
|
printf("program = %d\n", graphic_stack[stack_id].program);
|
||||||
|
printf("m = %d\n", graphic_stack[stack_id].m);
|
||||||
|
printf("v = %d\n", graphic_stack[stack_id].v);
|
||||||
|
printf("p = %d\n", graphic_stack[stack_id].p);
|
||||||
|
|
||||||
|
printf("arrows_ptr = %p\n", graphic_stack[stack_id].arrows_ptr);
|
||||||
|
printf("arrows_nb = %ld\n", graphic_stack[stack_id].arrows_nb);
|
||||||
|
|
||||||
|
printf("buffer_vertex_origin = %p\n", graphic_stack[stack_id].buffer_vertex_origin);
|
||||||
|
printf("buffer_colors_origin = %p\n", graphic_stack[stack_id].buffer_colors_origin);
|
||||||
|
printf("buffer_lines_origin = %p\n", graphic_stack[stack_id].buffer_lines_origin);
|
||||||
|
printf("buffer_plans_origin = %p\n", graphic_stack[stack_id].buffer_plans_origin);
|
||||||
|
|
||||||
|
printf("buffer_vertex_size = %ld\n", graphic_stack[stack_id].buffer_vertex_size);
|
||||||
|
printf("buffer_colors_size = %ld\n", graphic_stack[stack_id].buffer_colors_size);
|
||||||
|
printf("buffer_lines_size = %ld\n", graphic_stack[stack_id].buffer_lines_size);
|
||||||
|
printf("buffer_plans_size = %ld\n", graphic_stack[stack_id].buffer_plans_size);
|
||||||
|
|
||||||
|
printf("buffer_vertex_0_arrow = %ld\n", graphic_stack[stack_id].buffer_vertex_0_arrow);
|
||||||
|
printf("buffer_colors_0_arrow = %ld\n", graphic_stack[stack_id].buffer_colors_0_arrow);
|
||||||
|
printf("buffer_lines_0_arrow = %ld\n", graphic_stack[stack_id].buffer_lines_0_arrow);
|
||||||
|
printf("buffer_plans_0_arrow = %ld\n", graphic_stack[stack_id].buffer_plans_0_arrow);
|
||||||
|
|
||||||
|
printf("********************\n");
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void graphics_model_setup (const int stack_id);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
|
@ -0,0 +1,333 @@
|
||||||
|
/*
|
||||||
|
* 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 "base.h"
|
||||||
|
#include "contain.h"
|
||||||
|
//#include "parsing.h"
|
||||||
|
#include "graph_area.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();
|
||||||
|
dimension = 1; // AD HOC (2024-06-04)
|
||||||
|
|
||||||
|
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 (or not !)
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
;;
|
||||||
|
;; Dépendances sous GNU Guix
|
||||||
|
;;
|
||||||
|
|
||||||
|
|
||||||
|
(specifications->manifest
|
||||||
|
(list
|
||||||
|
"bash"
|
||||||
|
"coreutils"
|
||||||
|
"gcc-toolchain"
|
||||||
|
"pkg-config"
|
||||||
|
"valgrind"
|
||||||
|
"findutils"
|
||||||
|
"gdb"
|
||||||
|
"make"
|
||||||
|
"gtk"
|
||||||
|
"libxml2"
|
||||||
|
"glu"
|
||||||
|
"glew"
|
||||||
|
"glfw"
|
||||||
|
"cglm"
|
||||||
|
"libepoxy"
|
||||||
|
"pango@1.90.0"
|
||||||
|
"xorgproto"
|
||||||
|
"glib"
|
||||||
|
"mesa-headers"
|
||||||
|
"mesa"
|
||||||
|
"libadwaita"
|
||||||
|
)
|
||||||
|
)
|
|
@ -0,0 +1,483 @@
|
||||||
|
/*
|
||||||
|
* Gem-graph client
|
||||||
|
*
|
||||||
|
* Desc: Model parsing functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||||
|
* Copyright (C) 2024 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/xmlreader.h> // http://xmlsoft.org/examples/#parse1.c
|
||||||
|
// https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/general.html
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
#define READ_SITE 1 << 0
|
||||||
|
#define READ_WEIGHT 1 << 1
|
||||||
|
#define READ_X 1 << 2
|
||||||
|
#define READ_Y 1 << 3
|
||||||
|
#define READ_Z 1 << 4
|
||||||
|
#define SUCCESSFUL_READ_ARROW_X (READ_SITE | READ_WEIGHT | READ_X)
|
||||||
|
#define SUCCESSFUL_READ_ARROW_XY (READ_SITE | READ_WEIGHT | READ_X | READ_Y)
|
||||||
|
#define SUCCESSFUL_READ_ARROW_XYZ (READ_SITE | READ_WEIGHT | READ_X | READ_Y | READ_Z)
|
||||||
|
|
||||||
|
static xmlDocPtr model;
|
||||||
|
static xmlHashTablePtr model_hashtable;
|
||||||
|
|
||||||
|
bool model_init(const char *content, size_t length, const char *basename)
|
||||||
|
{
|
||||||
|
xmlNode *node;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this initialize the library and check potential ABI mismatches
|
||||||
|
* between the version it was compiled for and the actual shared
|
||||||
|
* library used.
|
||||||
|
*/
|
||||||
|
LIBXML_TEST_VERSION
|
||||||
|
|
||||||
|
model = xmlReadMemory(content, length, basename, NULL, 0);
|
||||||
|
|
||||||
|
if (model == NULL ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlDocGetRootElement(model);
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
g_printerr("Empty XML model !\n");
|
||||||
|
xmlFreeDoc(model);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) {
|
||||||
|
g_printerr("document of the wrong type, root node != gem-graph-model\n");
|
||||||
|
xmlFreeDoc(model);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
model_hashtable = xmlHashCreate(0);
|
||||||
|
|
||||||
|
if (model_hashtable == NULL) {
|
||||||
|
g_printerr("Can't create model hash table !\n");
|
||||||
|
xmlFreeDoc(model);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_shutdown(void)
|
||||||
|
{
|
||||||
|
xmlFreeDoc(model);
|
||||||
|
xmlHashFree(model_hashtable, NULL);
|
||||||
|
|
||||||
|
// Cleanup function for the XML library
|
||||||
|
xmlCleanupParser();
|
||||||
|
|
||||||
|
// This is to debug memory for regression tests
|
||||||
|
xmlMemoryDump();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last)
|
||||||
|
{
|
||||||
|
while (node != NULL && xmlStrcmp(node->name, last)) {
|
||||||
|
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name);
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
|
||||||
|
{
|
||||||
|
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
|
||||||
|
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
|
||||||
|
return toSplit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline xmlChar* getFirstTag(xmlChar *path)
|
||||||
|
{
|
||||||
|
xmlChar *preop = path;
|
||||||
|
path = (xmlChar *)xmlStrchr(path, '/');
|
||||||
|
path = xmlStrsub (path, 1, xmlStrlen(path));
|
||||||
|
|
||||||
|
//printf("%s = %s + / + %s\n", preop,\
|
||||||
|
xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1), path);
|
||||||
|
|
||||||
|
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline xmlChar* getLastTag(xmlChar *path)
|
||||||
|
{
|
||||||
|
while ((ulong)xmlStrchr (path, '/'))
|
||||||
|
path = splitStrAtSlash((xmlChar *)path);
|
||||||
|
|
||||||
|
// //printf("last tag in the path = <%s>\n", path);
|
||||||
|
return path; // which is no more the given path but only its last tag !
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static xmlNodePtr model_get_node(xmlChar *path)
|
||||||
|
{
|
||||||
|
xmlNodePtr node;
|
||||||
|
xmlChar *extrait;
|
||||||
|
xmlChar *reste, *last, *affich;
|
||||||
|
|
||||||
|
// Lookup for node from path in hash table
|
||||||
|
node = xmlHashLookup(model_hashtable, path);
|
||||||
|
|
||||||
|
// Found a node in hash table
|
||||||
|
if (node) {
|
||||||
|
return node;
|
||||||
|
|
||||||
|
// no node found in hash table
|
||||||
|
} else {
|
||||||
|
reste = path;
|
||||||
|
affich = reste;
|
||||||
|
last = getLastTag(reste);
|
||||||
|
node = xmlDocGetRootElement(model);
|
||||||
|
|
||||||
|
while (xmlStrchr (reste, '/')) {
|
||||||
|
extrait = getFirstTag(reste);
|
||||||
|
reste = splitStrAtSlash((xmlChar *)reste);
|
||||||
|
node = node->xmlChildrenNode;
|
||||||
|
node = getNextChild(node, extrait);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node && xmlStrcmp(node->name, last)) {
|
||||||
|
node = node->xmlChildrenNode;
|
||||||
|
|
||||||
|
while (node && xmlStrcmp(node->name, last)) {
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
xmlHashAddEntry (model_hashtable, path, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
|
||||||
|
{
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar* value;
|
||||||
|
long ret_value;
|
||||||
|
|
||||||
|
if (node && node->properties) {
|
||||||
|
attribute = node->properties;
|
||||||
|
while(attribute && attribute->name && attribute->children) {
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
|
||||||
|
value = xmlNodeListGetString(node->doc, attribute->children, 1);
|
||||||
|
ret_value = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
return ret_value;
|
||||||
|
}
|
||||||
|
attribute = attribute->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool model_get_node_str_attrib(xmlNodePtr node,
|
||||||
|
char *id,
|
||||||
|
char *dest)
|
||||||
|
{
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar* value;
|
||||||
|
|
||||||
|
if (node && node->properties) {
|
||||||
|
attribute = node->properties;
|
||||||
|
while(attribute && attribute->name && attribute->children) {
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
|
||||||
|
value = xmlNodeListGetString(node->doc, attribute->children, 1);
|
||||||
|
strcpy(dest, value);
|
||||||
|
xmlFree(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
attribute = attribute->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
char model_get_dim(void)
|
||||||
|
{
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar* value;
|
||||||
|
xmlNodePtr node = model_get_node(
|
||||||
|
(xmlChar *)"parameters/space-param/dimension");
|
||||||
|
|
||||||
|
if (xmlHasProp (node, (xmlChar *) "z")) return 3;
|
||||||
|
if (xmlHasProp (node, (xmlChar *) "y")) return 2;
|
||||||
|
if (xmlHasProp (node, (xmlChar *) "x")) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long model_get_dim_value(const char *axis)
|
||||||
|
{
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar *value;
|
||||||
|
long ret_value;
|
||||||
|
xmlNodePtr node = model_get_node(
|
||||||
|
(xmlChar *)"parameters/space-param/dimension");
|
||||||
|
|
||||||
|
return model_get_node_long_attrib(node, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
char model_get_multiplicity(void)
|
||||||
|
{
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar* value;
|
||||||
|
xmlNodePtr node = model_get_node(
|
||||||
|
(xmlChar *)"parameters/space-param/site_multiplicity");
|
||||||
|
|
||||||
|
if (node->children)
|
||||||
|
if (node->children->content)
|
||||||
|
return (char)strtol((char *)node->children->content, NULL, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_get_next_state(char *new_state_id)
|
||||||
|
{
|
||||||
|
static xmlNodePtr cur_node = NULL;
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar *value;
|
||||||
|
|
||||||
|
if (cur_node == NULL) {
|
||||||
|
// Get first state
|
||||||
|
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Get next state
|
||||||
|
if (cur_node->next)
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup in properties
|
||||||
|
if (model_get_node_str_attrib(cur_node, "id", new_state_id))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cur_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long model_get_state_arrows_count(const char *state_id)
|
||||||
|
{
|
||||||
|
xmlNodePtr cur_node = NULL;
|
||||||
|
xmlAttr *attribute;
|
||||||
|
long value = 0;
|
||||||
|
bool found = false;
|
||||||
|
char temp_char[25];
|
||||||
|
uint check = 0; // bit field checker
|
||||||
|
|
||||||
|
//printf("NEW CALL : cur_node = %p\n", cur_node);
|
||||||
|
|
||||||
|
assert(state_id);
|
||||||
|
|
||||||
|
// Get first state node
|
||||||
|
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||||
|
|
||||||
|
// Lookup in properties
|
||||||
|
while (cur_node && cur_node->properties) {
|
||||||
|
attribute = cur_node->properties;
|
||||||
|
|
||||||
|
// Look for the id attribute
|
||||||
|
if (model_get_node_str_attrib(cur_node, "id", &temp_char)) {
|
||||||
|
if (!xmlStrcmp(temp_char, (const xmlChar *)state_id)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the state has been found
|
||||||
|
if (!found) {
|
||||||
|
cur_node = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Count arrows
|
||||||
|
if (cur_node->children) {
|
||||||
|
cur_node = cur_node->children;
|
||||||
|
while (cur_node) {
|
||||||
|
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow"))
|
||||||
|
value++;
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_get_next_arrow(struct arrow_t *new_arrow,
|
||||||
|
const char *state_id,
|
||||||
|
char dimension)
|
||||||
|
{
|
||||||
|
static xmlNodePtr cur_node = NULL;
|
||||||
|
xmlAttr *attribute;
|
||||||
|
xmlChar *value;
|
||||||
|
bool found = false;
|
||||||
|
char temp_char[25];
|
||||||
|
uint check = 0; // bit field checker
|
||||||
|
|
||||||
|
//printf("NEW CALL : cur_node = %p\n", cur_node);
|
||||||
|
|
||||||
|
assert(new_arrow);
|
||||||
|
assert(state_id);
|
||||||
|
|
||||||
|
if (cur_node == NULL) {
|
||||||
|
// Get first state node
|
||||||
|
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||||
|
|
||||||
|
// Lookup in properties
|
||||||
|
while (cur_node && cur_node->properties) {
|
||||||
|
attribute = cur_node->properties;
|
||||||
|
|
||||||
|
// Look for the id attribute
|
||||||
|
if (model_get_node_str_attrib(cur_node, "id", &temp_char)) {
|
||||||
|
if (!xmlStrcmp(temp_char, (const xmlChar *)state_id)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the state has been found
|
||||||
|
if (!found) {
|
||||||
|
cur_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get first arrow
|
||||||
|
if (cur_node->children) {
|
||||||
|
cur_node = cur_node->children;
|
||||||
|
|
||||||
|
found = false;
|
||||||
|
while (cur_node && cur_node->name) {
|
||||||
|
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the state has been found
|
||||||
|
if (!found) {
|
||||||
|
cur_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Get next arrow
|
||||||
|
found = false;
|
||||||
|
while (cur_node->next) {
|
||||||
|
cur_node = cur_node->next;
|
||||||
|
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the state has been found
|
||||||
|
if (!found) {
|
||||||
|
cur_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("DURING CALL : cur_node = %p\n", cur_node);
|
||||||
|
//printf("DURING CALL : cur_node->name = %s\n", cur_node->name);
|
||||||
|
|
||||||
|
// Lookup in properties
|
||||||
|
if (cur_node && cur_node->properties) {
|
||||||
|
attribute = cur_node->properties;
|
||||||
|
|
||||||
|
while(attribute && attribute->name && attribute->children) {
|
||||||
|
//printf("attr name : %s\n", attribute->name);
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)"site")) {
|
||||||
|
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||||
|
new_arrow->site = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
check |= READ_SITE;
|
||||||
|
}
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)"weight")) {
|
||||||
|
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||||
|
new_arrow->load = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
check |= READ_WEIGHT;
|
||||||
|
}
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)"x")) {
|
||||||
|
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||||
|
new_arrow->x = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
check |= READ_X;
|
||||||
|
}
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)"y")) {
|
||||||
|
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||||
|
new_arrow->y = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
check |= READ_Y;
|
||||||
|
}
|
||||||
|
if (!xmlStrcmp(attribute->name, (const xmlChar *)"z")) {
|
||||||
|
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||||
|
new_arrow->z = strtol((char *)value, NULL, 0);
|
||||||
|
xmlFree(value);
|
||||||
|
check |= READ_Z;
|
||||||
|
}
|
||||||
|
attribute = attribute->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(dimension) {
|
||||||
|
case 3:
|
||||||
|
return (bool)(check & SUCCESSFUL_READ_ARROW_XYZ);
|
||||||
|
case 2:
|
||||||
|
return (bool)(check & SUCCESSFUL_READ_ARROW_XY);
|
||||||
|
case 1:
|
||||||
|
return (bool)(check & SUCCESSFUL_READ_ARROW_X);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Gem-graph OpenGL experiments
|
||||||
|
*
|
||||||
|
* Desc: Model parsing header
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
bool model_init(const char *content, size_t length, const char *basename);
|
||||||
|
bool model_shutdown(void);
|
||||||
|
|
||||||
|
char model_get_dim(void);
|
||||||
|
long model_get_dim_value(const char *axis);
|
||||||
|
char model_get_multiplicity(void);
|
||||||
|
bool model_get_next_state(char *new_state_id);
|
||||||
|
bool model_get_next_arrow(struct arrow_t *new_arrow,
|
||||||
|
const char *state_id,
|
||||||
|
char dimension);
|
Loading…
Reference in New Issue